26 p0 = (*(convex_tri->points))[tri[0]];
27 p1 = (*(convex_tri->points))[tri[1]];
28 p2 = (*(convex_tri->points))[tri[2]];
30 Vec3s barycentre_tri, center_barycenter;
31 barycentre_tri = (p0 +
p1 + p2) / 3;
32 center_barycenter = barycentre_tri - convex_tri->center;
34 Vec3s edge_tri1, edge_tri2, n_tri;
37 n_tri = edge_tri1.cross(edge_tri2);
39 if (center_barycenter.dot(n_tri) < 0) {
40 tri.
set(tri[1], tri[0], tri[2]);
45 unsigned int num_points,
bool keepTriangles,
46 const char* qhullCommand) {
56 const char* qhullCommand) {
60 "You shouldn't use this function with less than"
62 std::invalid_argument);
64 assert(pts[0].
data() + 3 == pts[1].
data());
68 qhullCommand ? qhullCommand : (keepTriangles ?
"Qt" :
"");
69 qh.runQhull(
"", 3,
static_cast<int>(
num_points), pts[0].data(), command);
72 if (
qh.hasQhullMessage()) std::cerr <<
qh.qhullMessage() << std::endl;
76 typedef std::size_t index_type;
77 typedef int size_type;
80 std::vector<int> pts_to_vertices(
num_points, -1);
83 size_t nvertex =
static_cast<size_t>(
qh.vertexCount());
84 std::shared_ptr<std::vector<Vec3s>> vertices(
85 new std::vector<Vec3s>(
size_t(nvertex)));
88 for (QhullVertexList::const_iterator
v = vertexList.begin();
89 v != vertexList.end(); ++
v) {
90 QhullPoint pt((*v).point());
91 pts_to_vertices[(size_t)pt.id()] = (int)i_vertex;
92 (*vertices)[i_vertex] =
Vec3s(pt[0], pt[1], pt[2]);
95 assert(i_vertex == nvertex);
103 convex->
initialize(vertices,
static_cast<unsigned int>(nvertex));
106 convex->
neighbors.reset(
new std::vector<Neighbors>(
size_t(nvertex)));
107 std::vector<std::set<index_type>> nneighbors(
static_cast<size_t>(nvertex));
109 convex_tri->
num_polygons =
static_cast<unsigned int>(
qh.facetCount());
112 convex_tri->computeCenter();
115 unsigned int c_nneighbors = 0;
116 unsigned int i_polygon = 0;
119 for (QhullFacet facet =
qh.beginFacet(); facet !=
qh.endFacet();
120 facet = facet.next()) {
121 if (facet.isSimplicial()) {
123 QhullVertexSet f_vertices(facet.vertices());
124 size_t n =
static_cast<size_t>(f_vertices.count());
128 pts_to_vertices[
static_cast<size_t>(f_vertices[0].point().
id())]),
130 pts_to_vertices[
static_cast<size_t>(f_vertices[1].point().
id())]),
131 static_cast<size_t>(pts_to_vertices[
static_cast<size_t>(
132 f_vertices[2].point().
id())]));
135 (*convex_tri->
polygons)[i_polygon++] = tri;
137 for (
size_t j = 0; j < n; ++j) {
138 size_t i = (j == 0) ? n - 1 : j - 1;
139 size_t k = (j == n - 1) ? 0 : j + 1;
141 if (nneighbors[tri[j]].insert(tri[i]).second) c_nneighbors++;
142 if (nneighbors[tri[j]].insert(tri[k]).second) c_nneighbors++;
147 "You requested to keep triangles so you "
148 "must pass option \"Qt\" to qhull via the qhull command argument.",
149 std::invalid_argument);
155 for (size_type j = 0; j < f_ridges.count(); ++j) {
156 assert(f_ridges[j].vertices().count() == 2);
157 int pi = pts_to_vertices[
static_cast<size_t>(
158 f_ridges[j].vertices()[0].point().id())],
159 pj = pts_to_vertices[
static_cast<size_t>(
160 f_ridges[j].vertices()[1].point().id())];
162 if (nneighbors[
static_cast<size_t>(pj)]
163 .insert(
static_cast<size_t>(
pi))
166 if (nneighbors[
static_cast<size_t>(
pi)]
167 .insert(
static_cast<size_t>(pj))
173 assert(!keepTriangles ||
static_cast<int>(i_polygon) ==
qh.facetCount());
177 convex->buildDoubleDescriptionFromQHullResult(
qh);
180 convex->
nneighbors_.reset(
new std::vector<unsigned int>(c_nneighbors));
181 unsigned int* p_nneighbors = convex->
nneighbors_->data();
182 std::vector<Neighbors>& neighbors_ = *(convex->
neighbors);
183 for (
size_t i = 0; i < static_cast<size_t>(nvertex); ++i) {
185 if (nneighbors[i].size() >= (std::numeric_limits<unsigned char>::max)())
187 n.
count_ = (
unsigned char)nneighbors[i].size();
190 std::copy(nneighbors[i].begin(), nneighbors[i].end(), p_nneighbors);
192 assert(p_nneighbors == convex->
nneighbors_->data() + c_nneighbors);
200 "Library built without qhull. Cannot build object of this type.",
209 #ifdef COAL_HAS_QHULL
210 void ConvexBase::buildDoubleDescription() {
213 "You shouldn't use this function with a convex less than"
215 std::invalid_argument);
219 const char* command =
"Qt";
224 if (
qh.hasQhullMessage()) std::cerr <<
qh.qhullMessage() << std::endl;
228 buildDoubleDescriptionFromQHullResult(
qh);
231 void ConvexBase::buildDoubleDescriptionFromQHullResult(
const Qhull&
qh) {
234 std::vector<Vec3s>& normals_ = *
normals;
236 std::vector<double>& offsets_ = *
offsets;
237 unsigned int i_normal = 0;
238 for (QhullFacet facet =
qh.beginFacet(); facet !=
qh.endFacet();
239 facet = facet.next()) {
243 offsets_[i_normal] = plane.
offset();
246 assert(
static_cast<int>(i_normal) ==
qh.facetCount());