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 const std::vector<double> *vertices = &self->getTriangleVertices();
52 const std::vector<uint32_t> *triangleFaces = &self->getTriangleFaces();
53 std::unique_ptr<GeometryTriangulator> localTriangulator;
54
55 if (triangleFaces->empty() || vertices->empty()) {
56 localTriangulator = std::make_unique<GeometryTriangulator>(self);
57 vertices = &localTriangulator->getTriangleVertices();
58 triangleFaces = &localTriangulator->getTriangleFaces();
59 if (triangleFaces->empty() || vertices->empty()) {
60 return getEmptyArrayObject();
61 }
62 }
63
64 const size_t numberTriangles = triangleFaces->size() / 3;
65 npy_intp dims[3] = {static_cast<npy_intp>(numberTriangles), 3, 3};
66 auto *meshCoords = new double[numberTriangles * 9];
67
68 const size_t vertexCapacity = vertices->size();
69 for (size_t corner = 0; corner < triangleFaces->size(); ++corner) {
70 const size_t src = static_cast<size_t>((*triangleFaces)[corner]) * 3;
71 const size_t dst = corner * 3;
72 if (src + 2 < vertexCapacity) {
73 meshCoords[dst] = (*vertices)[src];
74 meshCoords[dst + 1] = (*vertices)[src + 1];
75 meshCoords[dst + 2] = (*vertices)[src + 2];
76 } else {
77 meshCoords[dst] = 0.0;
78 meshCoords[dst + 1] = 0.0;
79 meshCoords[dst + 2] = 0.0;
80 }
81 }
82
83 PyObject *ndarray = Impl::wrapWithNDArray(meshCoords, 3, dims, NumpyWrapMode::ReadOnly, OwnershipMode::Python);
84 return object(handle<>(ndarray));
85
86 } catch (const std::exception &e) {
87 g_log.error(e.what());
88 return getEmptyArrayObject();
89 }
90}
91
93 register_ptr_to_python<std::shared_ptr<CSGObject>>();
94
95 class_<CSGObject, boost::python::bases<IObject>, boost::noncopyable>("CSGObject", no_init)
96 .def("getBoundingBox", (const BoundingBox &(CSGObject::*)() const) & CSGObject::getBoundingBox, arg("self"),
97 return_value_policy<copy_const_reference>(), "Return the axis-aligned bounding box for this shape")
98
99 .def("getShapeXML", &CSGObject::getShapeXML, arg("self"), "Returns the XML that was used to create this shape.")
100
101 .def("volume", &CSGObject::volume, arg("self"), "Returns the volume of this shape.")
102
103 .def("getMesh", &wrapMeshWithNDArray, (arg("self")), "Get the vertices, grouped by triangles, from mesh")
104 .def("hasValidShape", &CSGObject::hasValidShape, arg("self"), "Check if the shape is valid")
105 .def("shapeInfo", &CSGObject::shapeInfo, arg("self"), return_value_policy<copy_const_reference>(),
106 "Get the shape information for this object");
107}
#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:92
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.
const std::vector< uint32_t > & getTriangleFaces() const
get faces
const std::vector< double > & getTriangleVertices() const
get vertices
std::string getShapeXML() const
Getter for the shape xml.
bool hasValidShape() const override
Return whether this object has a valid shape.
const detail::ShapeInfo & shapeInfo() const override
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.