Mantid
Loading...
Searching...
No Matches
CSGObject.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
13
14#include <boost/python/class.hpp>
15#include <boost/python/copy_const_reference.hpp>
16#include <boost/python/register_ptr_to_python.hpp>
17#include <boost/python/self.hpp>
18#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
19
20#include <numpy/arrayobject.h>
21
22#define PY_ARRAY_UNIQUE_SYMBOL GEOMETRY_ARRAY_API
23#define NO_IMPORT_ARRAY
24
30using namespace boost::python;
31
32namespace {
33Mantid::Kernel::Logger g_log("CSGObject");
34}
35
37
38boost::python::object getEmptyArrayObject() {
39 npy_intp dims[3] = {0, 3, 3};
40 auto *emptyData = new double[1]; // Minimal allocation for empty array
41 emptyData[0] = 0.0;
42 PyObject *ndarray = Impl::wrapWithNDArray(emptyData, 3, dims, NumpyWrapMode::ReadOnly, OwnershipMode::Python);
43 return object(handle<>(ndarray));
44}
45
46boost::python::object wrapMeshWithNDArray(const CSGObject *self) {
47 if (self->getShapeXML().find("infinite") != std::string::npos) {
48 throw std::runtime_error("Cannot plot Shapes of infinite extent.");
49 }
50 try {
51 auto localTriangulator = GeometryTriangulator(self);
52 const auto &vertices = localTriangulator.getTriangleVertices();
53 const auto &triangles = localTriangulator.getTriangleFaces();
54 const size_t &numberTriangles = localTriangulator.numTriangleFaces();
55 npy_intp dims[3] = {static_cast<npy_intp>(numberTriangles), 3, 3};
56
57 if (numberTriangles == 0 || vertices.empty() || triangles.empty()) {
58 return getEmptyArrayObject();
59 }
60
61 size_t totalSize = dims[0] * dims[1] * dims[2];
62 auto *meshCoords = new double[totalSize];
63 std::fill(meshCoords, meshCoords + totalSize, 0.0);
64
65 // Copy triangle data with bounds checking
66 for (size_t corner_index = 0; corner_index < triangles.size() && corner_index < totalSize; ++corner_index) {
67 for (size_t xyz = 0; xyz < 3; xyz++) {
68 size_t vertex_idx = triangles[corner_index];
69 if (vertex_idx * 3 + xyz < vertices.size()) {
70 meshCoords[3 * corner_index + xyz] = vertices[3 * vertex_idx + xyz];
71 }
72 } // for each coordinate of that corner
73 } // for each corner of the triangle
74 PyObject *ndarray = Impl::wrapWithNDArray(meshCoords, 3, dims, NumpyWrapMode::ReadOnly, OwnershipMode::Python);
75 return object(handle<>(ndarray));
76
77 } catch (const std::exception &e) {
78 // Return empty array on failure
79 g_log.error(e.what());
80 return getEmptyArrayObject();
81 }
82}
83
85 register_ptr_to_python<std::shared_ptr<CSGObject>>();
86
87 class_<CSGObject, boost::python::bases<IObject>, boost::noncopyable>("CSGObject", no_init)
88 .def("getBoundingBox", (const BoundingBox &(CSGObject::*)() const) & CSGObject::getBoundingBox, arg("self"),
89 return_value_policy<copy_const_reference>(), "Return the axis-aligned bounding box for this shape")
90
91 .def("getShapeXML", &CSGObject::getShapeXML, arg("self"), "Returns the XML that was used to create this shape.")
92
93 .def("volume", &CSGObject::volume, arg("self"), "Returns the volume of this shape.")
94
95 .def("getMesh", &wrapMeshWithNDArray, (arg("self")), "Get the vertices, grouped by triangles, from mesh");
96}
#define GET_POINTER_SPECIALIZATION(TYPE)
Definition GetPointer.h:17
boost::python::object wrapMeshWithNDArray(const CSGObject *self)
Definition CSGObject.cpp:46
boost::python::object getEmptyArrayObject()
Definition CSGObject.cpp:38
void export_Object()
Definition CSGObject.cpp:84
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
Constructive Solid Geometry object.
Definition CSGObject.h:51
const BoundingBox & getBoundingBox() const override
Return cached value of axis-aligned bounding box.
double volume() const override
Calculates the volume of this object.
std::string getShapeXML() const
Getter for the shape xml.
IObject : Interface for geometry objects.
Definition IObject.h:42
GeometryTriangulator : Triangulates object surfaces.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition Logger.h:51
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
PyObject * wrapWithNDArray(const ElementType *, const int ndims, Py_intptr_t *dims, const NumpyWrapMode mode, const OwnershipMode oMode=OwnershipMode::Cpp)
Defines the wrapWithNDArray specialization for C array types.