20 #include "libqhullcpp/PointCoordinates.h"
21 #include "libqhullcpp/Qhull.h"
22 #include "libqhullcpp/QhullFacet.h"
23 #include "libqhullcpp/QhullFacetList.h"
24 #include "libqhullcpp/QhullVertexSet.h"
27 #include <unordered_map>
28 #include <unordered_set>
33 std::tuple<std::shared_ptr<ccMesh>, std::vector<size_t>>
38 std::tuple<std::shared_ptr<ccMesh>, std::vector<size_t>>
45 auto convex_hull = std::make_shared<ccMesh>(baseVertices);
46 convex_hull->addChild(baseVertices);
47 convex_hull->setName(
"ConvexMesh");
48 std::vector<size_t> pt_map;
50 std::vector<double> qhull_points_data(
points.size() * 3);
51 for (
size_t pidx = 0; pidx <
points.size(); ++pidx) {
52 const auto& pt =
points[pidx];
53 qhull_points_data[pidx * 3 + 0] = pt[0];
54 qhull_points_data[pidx * 3 + 1] = pt[1];
55 qhull_points_data[pidx * 3 + 2] = pt[2];
58 orgQhull::PointCoordinates qhull_points(3,
"");
59 qhull_points.append(qhull_points_data);
61 orgQhull::Qhull qhull;
62 qhull.runQhull(qhull_points.comment().c_str(), qhull_points.dimension(),
63 qhull_points.count(), qhull_points.coordinates(),
"Qt");
65 orgQhull::QhullFacetList facets = qhull.facetList();
67 if (!convex_hull->resize(facets.count())) {
70 std::unordered_map<unsigned int, unsigned int> vert_map;
71 std::unordered_set<unsigned int> inserted_vertices;
73 for (orgQhull::QhullFacetList::iterator it = facets.begin();
74 it != facets.end(); ++it) {
75 if (!(*it).isGood())
continue;
77 orgQhull::QhullFacet f = *it;
78 orgQhull::QhullVertexSet vSet = f.vertices();
79 int triangle_subscript = 0;
80 for (orgQhull::QhullVertexSet::iterator vIt = vSet.begin();
81 vIt != vSet.end(); ++vIt) {
82 orgQhull::QhullVertex v = *vIt;
83 orgQhull::QhullPoint p = v.point();
85 unsigned int vidx =
static_cast<unsigned int>(p.id());
86 convex_hull->getTriangleVertIndexes(tidx)->i[triangle_subscript] =
90 if (inserted_vertices.count(vidx) == 0) {
91 inserted_vertices.insert(vidx);
92 vert_map[vidx] = baseVertices->
size();
93 double* coords = p.coordinates();
98 pt_map.push_back(vidx);
105 for (
unsigned int i = 0; i < convex_hull->size(); ++i) {
107 convex_hull->getTriangleVertIndexes(i);
108 tsi->
i1 = vert_map[tsi->
i1];
109 tsi->
i2 = vert_map[tsi->
i2];
110 tsi->
i3 = vert_map[tsi->
i3];
116 convex_hull->shrinkToFit();
123 return std::make_tuple(convex_hull, pt_map);
126 std::tuple<std::shared_ptr<TetraMesh>, std::vector<size_t>>
132 std::tuple<std::shared_ptr<TetraMesh>, std::vector<size_t>>
134 const std::vector<Eigen::Vector3d>&
points) {
136 auto delaunay_triangulation = std::make_shared<TetraMesh>();
137 std::vector<size_t> pt_map;
141 "[ComputeDelaunayTriangulation3D] not enough points to create "
142 "a tetrahedral mesh.");
147 delaunay_triangulation->vertices_ =
points;
148 delaunay_triangulation->tetras_.push_back(
Vector4i(0, 1, 2, 3));
149 return std::make_tuple(delaunay_triangulation, pt_map);
152 std::vector<double> qhull_points_data(
points.size() * 3);
153 for (
size_t pidx = 0; pidx <
points.size(); ++pidx) {
154 const auto& pt =
points[pidx];
155 qhull_points_data[pidx * 3 + 0] = pt[0];
156 qhull_points_data[pidx * 3 + 1] = pt[1];
157 qhull_points_data[pidx * 3 + 2] = pt[2];
160 orgQhull::PointCoordinates qhull_points(3,
"");
161 qhull_points.append(qhull_points_data);
163 orgQhull::Qhull qhull;
164 qhull.runQhull(qhull_points.comment().c_str(), qhull_points.dimension(),
165 qhull_points.count(), qhull_points.coordinates(),
168 orgQhull::QhullFacetList facets = qhull.facetList();
169 delaunay_triangulation->tetras_.resize(facets.count());
170 std::unordered_map<int, int> vert_map;
171 std::unordered_set<int> inserted_vertices;
173 for (orgQhull::QhullFacetList::iterator it = facets.begin();
174 it != facets.end(); ++it) {
175 if (!(*it).isGood())
continue;
177 orgQhull::QhullFacet f = *it;
178 orgQhull::QhullVertexSet vSet = f.vertices();
179 int tetra_subscript = 0;
180 for (orgQhull::QhullVertexSet::iterator vIt = vSet.begin();
181 vIt != vSet.end(); ++vIt) {
182 orgQhull::QhullVertex v = *vIt;
183 orgQhull::QhullPoint p = v.point();
186 delaunay_triangulation->tetras_[tidx](tetra_subscript) = vidx;
189 if (inserted_vertices.count(vidx) == 0) {
190 inserted_vertices.insert(vidx);
191 vert_map[vidx] = int(delaunay_triangulation->vertices_.size());
192 double* coords = p.coordinates();
193 delaunay_triangulation->vertices_.push_back(
194 Eigen::Vector3d(coords[0], coords[1], coords[2]));
195 pt_map.push_back(vidx);
202 for (
auto& tetra : delaunay_triangulation->tetras_) {
203 tetra(0) = vert_map[tetra(0)];
204 tetra(1) = vert_map[tetra(1)];
205 tetra(2) = vert_map[tetra(2)];
206 tetra(3) = vert_map[tetra(3)];
209 return std::make_tuple(delaunay_triangulation, pt_map);
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Array of compressed 3D normals (single index)
static std::vector< Eigen::Matrix< double, 3, 1 > > fromArrayContainer(const std::vector< Vector3Tpl< PointCoordinateType >> &container)
virtual void setLocked(bool state)
Sets the "enabled" property.
virtual void setEnabled(bool state)
Sets the "enabled" property.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void shrinkToFit()
Removes unused capacity.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
static std::tuple< std::shared_ptr< ccMesh >, std::vector< size_t > > ComputeConvexHull(const std::vector< Eigen::Vector3d > &points)
static std::tuple< std::shared_ptr< TetraMesh >, std::vector< size_t > > ComputeDelaunayTetrahedralization(const std::vector< Eigen::Vector3d > &points)
std::vector< Eigen::Vector4i, cloudViewer::utility::Vector4i_allocator > tetras_
List of tetras denoted by the index of points forming the tetra.
Generic file read and write utility for python interface.
Eigen::Matrix< Index, 4, 1 > Vector4i
Triangle described by the indexes of its 3 vertices.