Line data Source code
1 : /*<html><pre> -<a href="qh-poly_r.htm"
2 : >-------------------------------</a><a name="TOP">-</a>
3 :
4 : poly_r.c
5 : implements polygons and simplices
6 :
7 : see qh-poly_r.htm, poly_r.h and libqhull_r.h
8 :
9 : infrequent code is in poly2_r.c
10 : (all but top 50 and their callers 12/3/95)
11 :
12 : Copyright (c) 1993-2020 The Geometry Center.
13 : $Id: //main/2019/qhull/src/libqhull_r/poly_r.c#8 $$Change: 2953 $
14 : $DateTime: 2020/05/21 22:05:32 $$Author: bbarber $
15 : */
16 :
17 : #include "qhull_ra.h"
18 :
19 : /*======== functions in alphabetical order ==========*/
20 :
21 : /*-<a href="qh-poly_r.htm#TOC"
22 : >-------------------------------</a><a name="appendfacet">-</a>
23 :
24 : qh_appendfacet(qh, facet )
25 : appends facet to end of qh.facet_list,
26 :
27 : returns:
28 : updates qh.newfacet_list, facet_next, facet_list
29 : increments qh.numfacets
30 :
31 : notes:
32 : assumes qh.facet_list/facet_tail is defined (createsimplex)
33 :
34 : see:
35 : qh_removefacet()
36 :
37 : */
38 190465 : void qh_appendfacet(qhT *qh, facetT *facet) {
39 190465 : facetT *tail= qh->facet_tail;
40 :
41 190465 : if (tail == qh->newfacet_list) {
42 29069 : qh->newfacet_list= facet;
43 29069 : if (tail == qh->visible_list) /* visible_list is at or before newfacet_list */
44 14405 : qh->visible_list= facet;
45 : }
46 190465 : if (tail == qh->facet_next)
47 4 : qh->facet_next= facet;
48 190465 : facet->previous= tail->previous;
49 190465 : facet->next= tail;
50 190465 : if (tail->previous)
51 190461 : tail->previous->next= facet;
52 : else
53 4 : qh->facet_list= facet;
54 190465 : tail->previous= facet;
55 190465 : qh->num_facets++;
56 190465 : trace4((qh, qh->ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
57 190465 : } /* appendfacet */
58 :
59 :
60 : /*-<a href="qh-poly_r.htm#TOC"
61 : >-------------------------------</a><a name="appendvertex">-</a>
62 :
63 : qh_appendvertex(qh, vertex )
64 : appends vertex to end of qh.vertex_list,
65 :
66 : returns:
67 : sets vertex->newfacet
68 : updates qh.vertex_list, newvertex_list
69 : increments qh.num_vertices
70 :
71 : notes:
72 : assumes qh.vertex_list/vertex_tail is defined (createsimplex)
73 :
74 : */
75 150967 : void qh_appendvertex(qhT *qh, vertexT *vertex) {
76 150967 : vertexT *tail= qh->vertex_tail;
77 :
78 150967 : if (tail == qh->newvertex_list)
79 14666 : qh->newvertex_list= vertex;
80 150967 : vertex->newfacet= True;
81 150967 : vertex->previous= tail->previous;
82 150967 : vertex->next= tail;
83 150967 : if (tail->previous)
84 150963 : tail->previous->next= vertex;
85 : else
86 4 : qh->vertex_list= vertex;
87 150967 : tail->previous= vertex;
88 150967 : qh->num_vertices++;
89 150967 : trace4((qh, qh->ferr, 4045, "qh_appendvertex: append v%d to qh.newvertex_list and set v.newfacet\n", vertex->id));
90 150967 : } /* appendvertex */
91 :
92 :
93 : /*-<a href="qh-poly_r.htm#TOC"
94 : >-------------------------------</a><a name="attachnewfacets">-</a>
95 :
96 : qh_attachnewfacets(qh)
97 : attach horizon facets to new facets in qh.newfacet_list
98 : newfacets have neighbor and ridge links to horizon but not vice versa
99 :
100 : returns:
101 : clears qh.NEWtentative
102 : set qh.NEWfacets
103 : horizon facets linked to new facets
104 : ridges changed from visible facets to new facets
105 : simplicial ridges deleted
106 : qh.visible_list, no ridges valid
107 : facet->f.replace is a newfacet (if any)
108 :
109 : notes:
110 : used for qh.NEWtentative, otherwise see qh_makenew_nonsimplicial and qh_makenew_simplicial
111 : qh_delridge_merge not needed (as tested by qh_checkdelridge)
112 :
113 : design:
114 : delete interior ridges and neighbor sets by
115 : for each visible, non-simplicial facet
116 : for each ridge
117 : if last visit or if neighbor is simplicial
118 : if horizon neighbor
119 : delete ridge for horizon's ridge set
120 : delete ridge
121 : erase neighbor set
122 : attach horizon facets and new facets by
123 : for all new facets
124 : if corresponding horizon facet is simplicial
125 : locate corresponding visible facet {may be more than one}
126 : link visible facet to new facet
127 : replace visible facet with new facet in horizon
128 : else it is non-simplicial
129 : for all visible neighbors of the horizon facet
130 : link visible neighbor to new facet
131 : delete visible neighbor from horizon facet
132 : append new facet to horizon's neighbors
133 : the first ridge of the new facet is the horizon ridge
134 : link the new facet into the horizon ridge
135 : */
136 0 : void qh_attachnewfacets(qhT *qh /* qh.visible_list, qh.newfacet_list */) {
137 0 : facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
138 : ridgeT *ridge, **ridgep;
139 :
140 0 : trace3((qh, qh->ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
141 0 : if (qh->CHECKfrequently) {
142 0 : qh_checkdelridge(qh);
143 : }
144 0 : qh->visit_id++;
145 0 : FORALLvisible_facets {
146 0 : visible->visitid= qh->visit_id;
147 0 : if (visible->ridges) {
148 0 : FOREACHridge_(visible->ridges) {
149 0 : neighbor= otherfacet_(ridge, visible);
150 0 : if (neighbor->visitid == qh->visit_id
151 0 : || (!neighbor->visible && neighbor->simplicial)) {
152 0 : if (!neighbor->visible) /* delete ridge for simplicial horizon */
153 0 : qh_setdel(neighbor->ridges, ridge);
154 0 : qh_delridge(qh, ridge); /* delete on second visit */
155 : }
156 : }
157 : }
158 : }
159 0 : trace1((qh, qh->ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
160 0 : FORALLnew_facets {
161 0 : horizon= SETfirstt_(newfacet->neighbors, facetT);
162 0 : if (horizon->simplicial) {
163 0 : visible= NULL;
164 0 : FOREACHneighbor_(horizon) { /* may have more than one horizon ridge */
165 0 : if (neighbor->visible) {
166 0 : if (visible) {
167 0 : if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
168 0 : SETindex_(horizon->neighbors, neighbor))) {
169 0 : visible= neighbor;
170 0 : break;
171 : }
172 : }else
173 0 : visible= neighbor;
174 : }
175 : }
176 0 : if (visible) {
177 0 : visible->f.replace= newfacet;
178 0 : qh_setreplace(qh, horizon->neighbors, visible, newfacet);
179 : }else {
180 0 : qh_fprintf(qh, qh->ferr, 6102, "qhull internal error (qh_attachnewfacets): could not find visible facet for horizon f%d of newfacet f%d\n",
181 : horizon->id, newfacet->id);
182 0 : qh_errexit2(qh, qh_ERRqhull, horizon, newfacet);
183 : }
184 : }else { /* non-simplicial, with a ridge for newfacet */
185 0 : FOREACHneighbor_(horizon) { /* may hold for many new facets */
186 0 : if (neighbor->visible) {
187 0 : neighbor->f.replace= newfacet;
188 0 : qh_setdelnth(qh, horizon->neighbors, SETindex_(horizon->neighbors, neighbor));
189 0 : neighborp--; /* repeat */
190 : }
191 : }
192 0 : qh_setappend(qh, &horizon->neighbors, newfacet);
193 0 : ridge= SETfirstt_(newfacet->ridges, ridgeT);
194 0 : if (ridge->top == horizon) {
195 0 : ridge->bottom= newfacet;
196 0 : ridge->simplicialbot= True;
197 : }else {
198 0 : ridge->top= newfacet;
199 0 : ridge->simplicialtop= True;
200 : }
201 : }
202 : } /* newfacets */
203 0 : trace4((qh, qh->ferr, 4094, "qh_attachnewfacets: clear f.ridges and f.neighbors for visible facets, may become invalid before qh_deletevisible\n"));
204 0 : FORALLvisible_facets {
205 0 : if (visible->ridges)
206 0 : SETfirst_(visible->ridges)= NULL;
207 0 : SETfirst_(visible->neighbors)= NULL;
208 : }
209 0 : qh->NEWtentative= False;
210 0 : qh->NEWfacets= True;
211 0 : if (qh->PRINTstatistics) {
212 0 : FORALLvisible_facets {
213 0 : if (!visible->f.replace)
214 0 : zinc_(Zinsidevisible);
215 : }
216 : }
217 0 : } /* attachnewfacets */
218 :
219 : /*-<a href="qh-poly_r.htm#TOC"
220 : >-------------------------------</a><a name="checkflipped">-</a>
221 :
222 : qh_checkflipped(qh, facet, dist, allerror )
223 : checks facet orientation to interior point
224 :
225 : if allerror set,
226 : tests against -qh.DISTround
227 : else
228 : tests against 0.0 since tested against -qh.DISTround before
229 :
230 : returns:
231 : False if it flipped orientation (sets facet->flipped)
232 : distance if non-NULL
233 :
234 : notes:
235 : called by qh_setfacetplane, qh_initialhull, and qh_checkflipped_all
236 : */
237 53386 : boolT qh_checkflipped(qhT *qh, facetT *facet, realT *distp, boolT allerror) {
238 : realT dist;
239 :
240 53386 : if (facet->flipped && !distp)
241 0 : return False;
242 53386 : zzinc_(Zdistcheck);
243 53386 : qh_distplane(qh, qh->interior_point, facet, &dist);
244 53386 : if (distp)
245 0 : *distp= dist;
246 53386 : if ((allerror && dist >= -qh->DISTround) || (!allerror && dist > 0.0)) {
247 5 : facet->flipped= True;
248 5 : trace0((qh, qh->ferr, 19, "qh_checkflipped: facet f%d flipped, allerror? %d, distance= %6.12g during p%d\n",
249 : facet->id, allerror, dist, qh->furthest_id));
250 5 : if (qh->num_facets > qh->hull_dim+1) { /* qh_initialhull reverses orientation if !qh_checkflipped */
251 0 : zzinc_(Zflippedfacets);
252 0 : qh_joggle_restart(qh, "flipped facet");
253 : }
254 5 : return False;
255 : }
256 53381 : return True;
257 : } /* checkflipped */
258 :
259 : /*-<a href="qh-poly_r.htm#TOC"
260 : >-------------------------------</a><a name="delfacet">-</a>
261 :
262 : qh_delfacet(qh, facet )
263 : removes facet from facet_list and frees up its memory
264 :
265 : notes:
266 : assumes vertices and ridges already freed or referenced elsewhere
267 : */
268 102172 : void qh_delfacet(qhT *qh, facetT *facet) {
269 : void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
270 :
271 102172 : trace3((qh, qh->ferr, 3057, "qh_delfacet: delete f%d\n", facet->id));
272 102172 : if (qh->CHECKfrequently || qh->VERIFYoutput) {
273 0 : if (!qh->NOerrexit) {
274 0 : qh_checkdelfacet(qh, facet, qh->facet_mergeset);
275 0 : qh_checkdelfacet(qh, facet, qh->degen_mergeset);
276 0 : qh_checkdelfacet(qh, facet, qh->vertex_mergeset);
277 : }
278 : }
279 102172 : if (facet == qh->tracefacet)
280 0 : qh->tracefacet= NULL;
281 102172 : if (facet == qh->GOODclosest)
282 0 : qh->GOODclosest= NULL;
283 102172 : qh_removefacet(qh, facet);
284 102172 : if (!facet->tricoplanar || facet->keepcentrum) {
285 73362 : qh_memfree_(qh, facet->normal, qh->normal_size, freelistp);
286 73362 : if (qh->CENTERtype == qh_ASvoronoi) { /* braces for macro calls */
287 0 : qh_memfree_(qh, facet->center, qh->center_size, freelistp);
288 : }else /* AScentrum */ {
289 73362 : qh_memfree_(qh, facet->center, qh->normal_size, freelistp);
290 : }
291 : }
292 102172 : qh_setfree(qh, &(facet->neighbors));
293 102172 : if (facet->ridges)
294 52123 : qh_setfree(qh, &(facet->ridges));
295 102172 : qh_setfree(qh, &(facet->vertices));
296 102172 : if (facet->outsideset)
297 26519 : qh_setfree(qh, &(facet->outsideset));
298 102172 : if (facet->coplanarset)
299 3 : qh_setfree(qh, &(facet->coplanarset));
300 102172 : qh_memfree_(qh, facet, (int)sizeof(facetT), freelistp);
301 102172 : } /* delfacet */
302 :
303 :
304 : /*-<a href="qh-poly_r.htm#TOC"
305 : >-------------------------------</a><a name="deletevisible">-</a>
306 :
307 : qh_deletevisible()
308 : delete visible facets and vertices
309 :
310 : returns:
311 : deletes each facet and removes from facetlist
312 : deletes vertices on qh.del_vertices and ridges in qh.del_ridges
313 : at exit, qh.visible_list empty (== qh.newfacet_list)
314 :
315 : notes:
316 : called by qh_all_vertexmerges, qh_addpoint, and qh_qhull
317 : ridges already deleted or moved elsewhere
318 : deleted vertices on qh.del_vertices
319 : horizon facets do not reference facets on qh.visible_list
320 : new facets in qh.newfacet_list
321 : uses qh.visit_id;
322 : */
323 14660 : void qh_deletevisible(qhT *qh /* qh.visible_list */) {
324 : facetT *visible, *nextfacet;
325 : vertexT *vertex, **vertexp;
326 14660 : int numvisible= 0, numdel= qh_setsize(qh, qh->del_vertices);
327 :
328 14660 : trace1((qh, qh->ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
329 : qh->num_visible, numdel));
330 73617 : for (visible=qh->visible_list; visible && visible->visible;
331 58957 : visible= nextfacet) { /* deleting current */
332 58957 : nextfacet= visible->next;
333 58957 : numvisible++;
334 58957 : qh_delfacet(qh, visible); /* f.ridges deleted or moved elsewhere, deleted f.vertices on qh.del_vertices */
335 : }
336 14660 : if (numvisible != qh->num_visible) {
337 0 : qh_fprintf(qh, qh->ferr, 6103, "qhull internal error (qh_deletevisible): qh->num_visible %d is not number of visible facets %d\n",
338 : qh->num_visible, numvisible);
339 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
340 : }
341 14660 : qh->num_visible= 0;
342 14660 : zadd_(Zvisfacettot, numvisible);
343 14660 : zmax_(Zvisfacetmax, numvisible);
344 14660 : zzadd_(Zdelvertextot, numdel);
345 14660 : zmax_(Zdelvertexmax, numdel);
346 14660 : FOREACHvertex_(qh->del_vertices)
347 0 : qh_delvertex(qh, vertex);
348 14660 : qh_settruncate(qh, qh->del_vertices, 0);
349 14660 : } /* deletevisible */
350 :
351 : /*-<a href="qh-poly_r.htm#TOC"
352 : >-------------------------------</a><a name="facetintersect">-</a>
353 :
354 : qh_facetintersect(qh, facetA, facetB, skipa, skipB, prepend )
355 : return vertices for intersection of two simplicial facets
356 : may include 1 prepended entry (if more, need to settemppush)
357 :
358 : returns:
359 : returns set of qh.hull_dim-1 + prepend vertices
360 : returns skipped index for each test and checks for exactly one
361 :
362 : notes:
363 : does not need settemp since set in quick memory
364 :
365 : see also:
366 : qh_vertexintersect and qh_vertexintersect_new
367 : use qh_setnew_delnthsorted to get nth ridge (no skip information)
368 :
369 : design:
370 : locate skipped vertex by scanning facet A's neighbors
371 : locate skipped vertex by scanning facet B's neighbors
372 : intersect the vertex sets
373 : */
374 49253 : setT *qh_facetintersect(qhT *qh, facetT *facetA, facetT *facetB,
375 : int *skipA,int *skipB, int prepend) {
376 : setT *intersect;
377 49253 : int dim= qh->hull_dim, i, j;
378 : facetT **neighborsA, **neighborsB;
379 :
380 49253 : neighborsA= SETaddr_(facetA->neighbors, facetT);
381 49253 : neighborsB= SETaddr_(facetB->neighbors, facetT);
382 49253 : i= j= 0;
383 49253 : if (facetB == *neighborsA++)
384 20564 : *skipA= 0;
385 : /* coverity[overrun-local] */
386 28689 : else if (facetB == *neighborsA++)
387 15063 : *skipA= 1;
388 : /* coverity[overrun-local] */
389 13626 : else if (facetB == *neighborsA++)
390 13626 : *skipA= 2;
391 : else {
392 0 : for (i=3; i < dim; i++) {
393 0 : if (facetB == *neighborsA++) {
394 0 : *skipA= i;
395 0 : break;
396 : }
397 : }
398 : }
399 49253 : if (facetA == *neighborsB++)
400 12805 : *skipB= 0;
401 : /* coverity[overrun-local] */
402 36448 : else if (facetA == *neighborsB++)
403 19769 : *skipB= 1;
404 : /* coverity[overrun-local] */
405 16679 : else if (facetA == *neighborsB++)
406 16679 : *skipB= 2;
407 : else {
408 0 : for (j=3; j < dim; j++) {
409 0 : if (facetA == *neighborsB++) {
410 0 : *skipB= j;
411 0 : break;
412 : }
413 : }
414 : }
415 49253 : if (i >= dim || j >= dim) {
416 0 : qh_fprintf(qh, qh->ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in other's neighbors\n",
417 : facetA->id, facetB->id);
418 0 : qh_errexit2(qh, qh_ERRqhull, facetA, facetB);
419 : }
420 49253 : intersect= qh_setnew_delnthsorted(qh, facetA->vertices, qh->hull_dim, *skipA, prepend);
421 49253 : trace4((qh, qh->ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
422 : facetA->id, *skipA, facetB->id, *skipB));
423 49253 : return(intersect);
424 : } /* facetintersect */
425 :
426 : /*-<a href="qh-poly_r.htm#TOC"
427 : >-------------------------------</a><a name="gethash">-</a>
428 :
429 : qh_gethash(qh, hashsize, set, size, firstindex, skipelem )
430 : return hashvalue for a set with firstindex and skipelem
431 :
432 : notes:
433 : returned hash is in [0,hashsize)
434 : assumes at least firstindex+1 elements
435 : assumes skipelem is NULL, in set, or part of hash
436 :
437 : hashes memory addresses which may change over different runs of the same data
438 : using sum for hash does badly in high d
439 : */
440 262984 : int qh_gethash(qhT *qh, int hashsize, setT *set, int size, int firstindex, void *skipelem) {
441 262984 : void **elemp= SETelemaddr_(set, firstindex, void);
442 262984 : ptr_intT hash= 0, elem;
443 : unsigned int uresult;
444 : int i;
445 : #ifdef _MSC_VER /* Microsoft Visual C++ -- warn about 64-bit issues */
446 : #pragma warning( push) /* WARN64 -- ptr_intT holds a 64-bit pointer */
447 : #pragma warning( disable : 4311) /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
448 : #endif
449 :
450 262984 : switch (size-firstindex) {
451 0 : case 1:
452 0 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) - (ptr_intT) skipelem);
453 0 : break;
454 262984 : case 2:
455 : /* coverity[overrun-local] */
456 262984 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem);
457 262984 : break;
458 0 : case 3:
459 0 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
460 0 : - (ptr_intT) skipelem);
461 0 : break;
462 0 : case 4:
463 0 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
464 0 : + (ptr_intT)elemp[3] - (ptr_intT) skipelem);
465 0 : break;
466 0 : case 5:
467 0 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
468 0 : + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem);
469 0 : break;
470 0 : case 6:
471 0 : hash= (ptr_intT)((long long)(ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
472 0 : + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
473 0 : - (ptr_intT) skipelem);
474 0 : break;
475 0 : default:
476 0 : hash= 0;
477 0 : i= 3;
478 : do { /* this is about 10% in 10-d */
479 0 : if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
480 0 : hash ^= (elem << i) + (elem >> (32-i));
481 0 : i += 3;
482 0 : if (i >= 32)
483 0 : i -= 32;
484 : }
485 0 : }while (*elemp);
486 0 : break;
487 : }
488 262984 : if (hashsize<0) {
489 0 : qh_fprintf(qh, qh->ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly_r.c]\n", hashsize);
490 0 : qh_errexit2(qh, qh_ERRqhull, NULL, NULL);
491 : }
492 262984 : uresult= (unsigned int)hash;
493 262984 : uresult %= (unsigned int)hashsize;
494 : /* result= 0; for debugging */
495 262984 : return (int)uresult;
496 : #ifdef _MSC_VER
497 : #pragma warning( pop)
498 : #endif
499 : } /* gethash */
500 :
501 : /*-<a href="qh-poly_r.htm#TOC"
502 : >-------------------------------</a><a name="getreplacement">-</a>
503 :
504 : qh_getreplacement(qh, visible )
505 : get replacement for visible facet
506 :
507 : returns:
508 : valid facet from visible.replace (may be chained)
509 : */
510 26522 : facetT *qh_getreplacement(qhT *qh, facetT *visible) {
511 26522 : unsigned int count= 0;
512 :
513 26522 : facetT *result= visible;
514 58607 : while (result && result->visible) {
515 32085 : result= result->f.replace;
516 32085 : if (count++ > qh->facet_id)
517 0 : qh_infiniteloop(qh, visible);
518 : }
519 26522 : return result;
520 : }
521 :
522 : /*-<a href="qh-poly_r.htm#TOC"
523 : >-------------------------------</a><a name="makenewfacet">-</a>
524 :
525 : qh_makenewfacet(qh, vertices, toporient, horizon )
526 : creates a toporient? facet from vertices
527 :
528 : returns:
529 : returns newfacet
530 : adds newfacet to qh.facet_list
531 : newfacet->vertices= vertices
532 : if horizon
533 : newfacet->neighbor= horizon, but not vice versa
534 : newvertex_list updated with vertices
535 : */
536 131492 : facetT *qh_makenewfacet(qhT *qh, setT *vertices, boolT toporient, facetT *horizon) {
537 : facetT *newfacet;
538 : vertexT *vertex, **vertexp;
539 :
540 525968 : FOREACHvertex_(vertices) {
541 394476 : if (!vertex->newfacet) {
542 88049 : qh_removevertex(qh, vertex);
543 88049 : qh_appendvertex(qh, vertex);
544 : }
545 : }
546 131492 : newfacet= qh_newfacet(qh);
547 131492 : newfacet->vertices= vertices;
548 131492 : if (toporient)
549 65686 : newfacet->toporient= True;
550 131492 : if (horizon)
551 131492 : qh_setappend(qh, &(newfacet->neighbors), horizon);
552 131492 : qh_appendfacet(qh, newfacet);
553 131492 : return(newfacet);
554 : } /* makenewfacet */
555 :
556 :
557 : /*-<a href="qh-poly_r.htm#TOC"
558 : >-------------------------------</a><a name="makenewplanes">-</a>
559 :
560 : qh_makenewplanes()
561 : make new hyperplanes for facets on qh.newfacet_list
562 :
563 : returns:
564 : all facets have hyperplanes or are marked for merging
565 : doesn't create hyperplane if horizon is coplanar (will merge)
566 : updates qh.min_vertex if qh.JOGGLEmax
567 :
568 : notes:
569 : facet->f.samecycle is defined for facet->mergehorizon facets
570 : */
571 14660 : void qh_makenewplanes(qhT *qh /* qh.newfacet_list */) {
572 : facetT *newfacet;
573 :
574 14660 : trace4((qh, qh->ferr, 4074, "qh_makenewplanes: make new hyperplanes for facets on qh.newfacet_list f%d\n",
575 : qh->newfacet_list->id));
576 88064 : FORALLnew_facets {
577 73404 : if (!newfacet->mergehorizon)
578 53357 : qh_setfacetplane(qh, newfacet); /* updates Wnewvertexmax */
579 : }
580 14660 : if (qh->JOGGLEmax < REALmax/2)
581 0 : minimize_(qh->min_vertex, -wwval_(Wnewvertexmax));
582 14660 : } /* makenewplanes */
583 :
584 : #ifndef qh_NOmerge
585 : /*-<a href="qh-poly_r.htm#TOC"
586 : >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
587 :
588 : qh_makenew_nonsimplicial(qh, visible, apex, numnew )
589 : make new facets for ridges of a visible facet
590 :
591 : returns:
592 : first newfacet, bumps numnew as needed
593 : attaches new facets if !qh->NEWtentative
594 : marks ridge neighbors for simplicial visible
595 : if (qh.NEWtentative)
596 : ridges on newfacet, horizon, and visible
597 : else
598 : ridge and neighbors between newfacet and horizon
599 : visible facet's ridges are deleted
600 : visible facet's f.neighbors is empty
601 :
602 : notes:
603 : called by qh_makenewfacets and qh_triangulatefacet
604 : qh.visit_id if visible has already been processed
605 : sets neighbor->seen for building f.samecycle
606 : assumes all 'seen' flags initially false
607 : qh_delridge_merge not needed (as tested by qh_checkdelridge in qh_makenewfacets)
608 :
609 : design:
610 : for each ridge of visible facet
611 : get neighbor of visible facet
612 : if neighbor was already processed
613 : delete the ridge (will delete all visible facets later)
614 : if neighbor is a horizon facet
615 : create a new facet
616 : if neighbor coplanar
617 : adds newfacet to f.samecycle for later merging
618 : else
619 : updates neighbor's neighbor set
620 : (checks for non-simplicial facet with multiple ridges to visible facet)
621 : updates neighbor's ridge set
622 : (checks for simplicial neighbor to non-simplicial visible facet)
623 : (deletes ridge if neighbor is simplicial)
624 :
625 : */
626 32075 : facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
627 : void **freelistp; /* used if !qh_NOmem by qh_memfree_() */
628 : ridgeT *ridge, **ridgep;
629 32075 : facetT *neighbor, *newfacet= NULL, *samecycle;
630 : setT *vertices;
631 : boolT toporient;
632 : unsigned int ridgeid;
633 :
634 121748 : FOREACHridge_(visible->ridges) {
635 89673 : ridgeid= ridge->id;
636 89673 : neighbor= otherfacet_(ridge, visible);
637 89673 : if (neighbor->visible) {
638 7434 : if (!qh->NEWtentative) {
639 7434 : if (neighbor->visitid == qh->visit_id) {
640 3717 : if (qh->traceridge == ridge)
641 0 : qh->traceridge= NULL;
642 3717 : qh_setfree(qh, &(ridge->vertices)); /* delete on 2nd visit */
643 3717 : qh_memfree_(qh, ridge, (int)sizeof(ridgeT), freelistp);
644 : }
645 : }
646 : }else { /* neighbor is an horizon facet */
647 82239 : toporient= (ridge->top == visible);
648 82239 : vertices= qh_setnew(qh, qh->hull_dim); /* makes sure this is quick */
649 82239 : qh_setappend(qh, &vertices, apex);
650 82239 : qh_setappend_set(qh, &vertices, ridge->vertices);
651 82239 : newfacet= qh_makenewfacet(qh, vertices, toporient, neighbor);
652 82239 : (*numnew)++;
653 82239 : if (neighbor->coplanarhorizon) {
654 6675 : newfacet->mergehorizon= True;
655 6675 : if (!neighbor->seen) {
656 6675 : newfacet->f.samecycle= newfacet;
657 6675 : neighbor->f.newcycle= newfacet;
658 : }else {
659 0 : samecycle= neighbor->f.newcycle;
660 0 : newfacet->f.samecycle= samecycle->f.samecycle;
661 0 : samecycle->f.samecycle= newfacet;
662 : }
663 : }
664 82239 : if (qh->NEWtentative) {
665 0 : if (!neighbor->simplicial)
666 0 : qh_setappend(qh, &(newfacet->ridges), ridge);
667 : }else { /* qh_attachnewfacets */
668 82239 : if (neighbor->seen) {
669 0 : if (neighbor->simplicial) {
670 0 : qh_fprintf(qh, qh->ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
671 : neighbor->id, visible->id);
672 0 : qh_errexit2(qh, qh_ERRqhull, neighbor, visible);
673 : }
674 0 : qh_setappend(qh, &(neighbor->neighbors), newfacet);
675 : }else
676 82239 : qh_setreplace(qh, neighbor->neighbors, visible, newfacet);
677 82239 : if (neighbor->simplicial) {
678 40765 : qh_setdel(neighbor->ridges, ridge);
679 40765 : qh_delridge(qh, ridge);
680 : }else {
681 41474 : qh_setappend(qh, &(newfacet->ridges), ridge);
682 41474 : if (toporient) {
683 20815 : ridge->top= newfacet;
684 20815 : ridge->simplicialtop= True;
685 : }else {
686 20659 : ridge->bottom= newfacet;
687 20659 : ridge->simplicialbot= True;
688 : }
689 : }
690 : }
691 82239 : trace4((qh, qh->ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
692 : newfacet->id, apex->id, ridgeid, neighbor->id));
693 : }
694 89673 : neighbor->seen= True;
695 : } /* for each ridge */
696 32075 : return newfacet;
697 : } /* makenew_nonsimplicial */
698 :
699 : #else /* qh_NOmerge */
700 : facetT *qh_makenew_nonsimplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
701 : QHULL_UNUSED(qh)
702 : QHULL_UNUSED(visible)
703 : QHULL_UNUSED(apex)
704 : QHULL_UNUSED(numnew)
705 :
706 : return NULL;
707 : }
708 : #endif /* qh_NOmerge */
709 :
710 : /*-<a href="qh-poly_r.htm#TOC"
711 : >-------------------------------</a><a name="makenew_simplicial">-</a>
712 :
713 : qh_makenew_simplicial(qh, visible, apex, numnew )
714 : make new facets for simplicial visible facet and apex
715 :
716 : returns:
717 : attaches new facets if !qh.NEWtentative
718 : neighbors between newfacet and horizon
719 :
720 : notes:
721 : nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
722 :
723 : design:
724 : locate neighboring horizon facet for visible facet
725 : determine vertices and orientation
726 : create new facet
727 : if coplanar,
728 : add new facet to f.samecycle
729 : update horizon facet's neighbor list
730 : */
731 34070 : facetT *qh_makenew_simplicial(qhT *qh, facetT *visible, vertexT *apex, int *numnew) {
732 34070 : facetT *neighbor, **neighborp, *newfacet= NULL;
733 : setT *vertices;
734 : boolT flip, toporient;
735 34070 : int horizonskip= 0, visibleskip= 0;
736 :
737 136280 : FOREACHneighbor_(visible) {
738 102210 : if (!neighbor->seen && !neighbor->visible) {
739 49253 : vertices= qh_facetintersect(qh, neighbor,visible, &horizonskip, &visibleskip, 1);
740 49253 : SETfirst_(vertices)= apex;
741 49253 : flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
742 49253 : if (neighbor->toporient)
743 24768 : toporient= horizonskip & 0x1;
744 : else
745 24485 : toporient= (horizonskip & 0x1) ^ 0x1;
746 49253 : newfacet= qh_makenewfacet(qh, vertices, toporient, neighbor);
747 49253 : (*numnew)++;
748 49253 : if (neighbor->coplanarhorizon && (qh->PREmerge || qh->MERGEexact)) {
749 : #ifndef qh_NOmerge
750 13372 : newfacet->f.samecycle= newfacet;
751 13372 : newfacet->mergehorizon= True;
752 : #endif
753 : }
754 49253 : if (!qh->NEWtentative)
755 49253 : SETelem_(neighbor->neighbors, horizonskip)= newfacet;
756 49253 : trace4((qh, qh->ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
757 : newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
758 : neighbor->toporient, visible->id, visibleskip, flip));
759 : }
760 : }
761 34070 : return newfacet;
762 : } /* makenew_simplicial */
763 :
764 : /*-<a href="qh-poly_r.htm#TOC"
765 : >-------------------------------</a><a name="matchneighbor">-</a>
766 :
767 : qh_matchneighbor(qh, newfacet, newskip, hashsize, hashcount )
768 : either match subridge of newfacet with neighbor or add to hash_table
769 :
770 : returns:
771 : matched ridges of newfacet, except for duplicate ridges
772 : duplicate ridges marked by qh_DUPLICATEridge for qh_matchdupridge
773 :
774 : notes:
775 : called by qh_matchnewfacets
776 : assumes newfacet is simplicial
777 : ridge is newfacet->vertices w/o newskip vertex
778 : do not allocate memory (need to free hash_table cleanly)
779 : uses linear hash chains
780 : see qh_matchdupridge (poly2_r.c)
781 :
782 : design:
783 : for each possible matching facet in qh.hash_table
784 : if vertices match
785 : set ismatch, if facets have opposite orientation
786 : if ismatch and matching facet doesn't have a match
787 : match the facets by updating their neighbor sets
788 : else
789 : note: dupridge detected when a match 'f&d skip %d' has already been seen
790 : need to mark all of the dupridges for qh_matchdupridge
791 : indicate a duplicate ridge by qh_DUPLICATEridge and f.dupridge
792 : add facet to hashtable
793 : unless the other facet was already a duplicate ridge
794 : mark both facets with a duplicate ridge
795 : add other facet (if defined) to hash table
796 :
797 : state at "indicate a duplicate ridge":
798 : newfacet@newskip= the argument
799 : facet= the hashed facet@skip that has the same vertices as newfacet@newskip
800 : same= true if matched vertices have the same orientation
801 : matchfacet= neighbor at facet@skip
802 : matchfacet=qh_DUPLICATEridge, matchfacet was previously detected as a dupridge of facet@skip
803 : ismatch if 'vertex orientation (same) matches facet/newfacet orientation (toporient)
804 : unknown facet will match later
805 :
806 : details at "indicate a duplicate ridge":
807 : if !ismatch and matchfacet,
808 : dupridge is between hashed facet@skip/matchfacet@matchskip and arg newfacet@newskip/unknown
809 : set newfacet@newskip, facet@skip, and matchfacet@matchskip to qh_DUPLICATEridge
810 : add newfacet and matchfacet to hash_table
811 : if ismatch and matchfacet,
812 : same as !ismatch and matchfacet -- it matches facet instead of matchfacet
813 : if !ismatch and !matchfacet
814 : dupridge between hashed facet@skip/unknown and arg newfacet@newskip/unknown
815 : set newfacet@newskip and facet@skip to qh_DUPLICATEridge
816 : add newfacet to hash_table
817 : if ismatch and matchfacet==qh_DUPLICATEridge
818 : dupridge with already duplicated hashed facet@skip and arg newfacet@newskip/unknown
819 : set newfacet@newskip to qh_DUPLICATEridge
820 : add newfacet to hash_table
821 : facet's hyperplane already set
822 : */
823 262984 : void qh_matchneighbor(qhT *qh, facetT *newfacet, int newskip, int hashsize, int *hashcount) {
824 262984 : boolT newfound= False; /* True, if new facet is already in hash chain */
825 : boolT same, ismatch;
826 : int hash, scan;
827 : facetT *facet, *matchfacet;
828 : int skip, matchskip;
829 :
830 262984 : hash= qh_gethash(qh, hashsize, newfacet->vertices, qh->hull_dim, 1,
831 262984 : SETelem_(newfacet->vertices, newskip));
832 262984 : trace4((qh, qh->ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
833 : newfacet->id, newskip, hash, *hashcount));
834 262984 : zinc_(Zhashlookup);
835 284743 : for (scan=hash; (facet= SETelemt_(qh->hash_table, scan, facetT));
836 21759 : scan= (++scan >= hashsize ? 0 : scan)) {
837 153251 : if (facet == newfacet) {
838 1604 : newfound= True;
839 1604 : continue;
840 : }
841 151647 : zinc_(Zhashtests);
842 151647 : if (qh_matchvertices(qh, 1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
843 131492 : if (SETelem_(newfacet->vertices, newskip) == SETelem_(facet->vertices, skip)) {
844 0 : qh_joggle_restart(qh, "two new facets with the same vertices");
845 : /* duplicated for multiple skips, not easily avoided */
846 0 : qh_fprintf(qh, qh->ferr, 7084, "qhull topology warning (qh_matchneighbor): will merge vertices to undo new facets -- f%d and f%d have the same vertices (skip %d, skip %d) and same horizon ridges to f%d and f%d\n",
847 0 : facet->id, newfacet->id, skip, newskip, SETfirstt_(facet->neighbors, facetT)->id, SETfirstt_(newfacet->neighbors, facetT)->id);
848 : /* will rename a vertex (QH3053). The fault was duplicate ridges (same vertices) in different facets due to a previous rename. Expensive to detect beforehand */
849 : }
850 131492 : ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
851 131492 : matchfacet= SETelemt_(facet->neighbors, skip, facetT);
852 131492 : if (ismatch && !matchfacet) {
853 131492 : SETelem_(facet->neighbors, skip)= newfacet;
854 131492 : SETelem_(newfacet->neighbors, newskip)= facet;
855 131492 : (*hashcount)--;
856 131492 : trace4((qh, qh->ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
857 : facet->id, skip, newfacet->id, newskip));
858 131492 : return;
859 : }
860 0 : if (!qh->PREmerge && !qh->MERGEexact) {
861 0 : qh_joggle_restart(qh, "a ridge with more than two neighbors");
862 0 : qh_fprintf(qh, qh->ferr, 6107, "qhull topology error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors. Can not continue due to no qh.PREmerge and no 'Qx' (MERGEexact)\n",
863 0 : facet->id, newfacet->id, getid_(matchfacet));
864 0 : qh_errexit2(qh, qh_ERRtopology, facet, newfacet);
865 : }
866 0 : SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
867 0 : newfacet->dupridge= True;
868 0 : qh_addhash(newfacet, qh->hash_table, hashsize, hash);
869 0 : (*hashcount)++;
870 0 : if (matchfacet != qh_DUPLICATEridge) {
871 0 : SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
872 0 : facet->dupridge= True;
873 0 : if (matchfacet) {
874 0 : matchskip= qh_setindex(matchfacet->neighbors, facet);
875 0 : if (matchskip<0) {
876 0 : qh_fprintf(qh, qh->ferr, 6260, "qhull topology error (qh_matchneighbor): matchfacet f%d is in f%d neighbors but not vice versa. Can not continue.\n",
877 : matchfacet->id, facet->id);
878 0 : qh_errexit2(qh, qh_ERRtopology, matchfacet, facet);
879 : }
880 : else {
881 0 : SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge; /* matchskip>=0 by QH6260 */
882 0 : matchfacet->dupridge= True;
883 0 : qh_addhash(matchfacet, qh->hash_table, hashsize, hash);
884 0 : *hashcount += 2;
885 : }
886 : }
887 : }
888 0 : trace4((qh, qh->ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
889 : newfacet->id, newskip, facet->id, skip,
890 : (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
891 : ismatch, hash));
892 0 : return; /* end of duplicate ridge */
893 : }
894 : }
895 131492 : if (!newfound)
896 129888 : SETelem_(qh->hash_table, scan)= newfacet; /* same as qh_addhash */
897 131492 : (*hashcount)++;
898 131492 : trace4((qh, qh->ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
899 : newfacet->id, newskip, hash));
900 : } /* matchneighbor */
901 :
902 :
903 : /*-<a href="qh-poly_r.htm#TOC"
904 : >-------------------------------</a><a name="matchnewfacets">-</a>
905 :
906 : qh_matchnewfacets(qh )
907 : match new facets in qh.newfacet_list to their newfacet neighbors
908 : all facets are simplicial
909 :
910 : returns:
911 : if dupridges and merging
912 : returns maxdupdist (>=0.0) from vertex to opposite facet
913 : sets facet->dupridge
914 : missing neighbor links identify dupridges to be merged (qh_DUPLICATEridge)
915 : else
916 : qh.newfacet_list with full neighbor sets
917 : vertices for the nth neighbor match all but the nth vertex
918 : if not merging and qh.FORCEoutput
919 : for facets with normals (i.e., with dupridges)
920 : sets facet->flippped for flipped normals, also prevents point partitioning
921 :
922 : notes:
923 : called by qh_buildcone* and qh_triangulate_facet
924 : neighbor[0] of new facets is the horizon facet
925 : if NEWtentative, new facets not attached to the horizon
926 : assumes qh.hash_table is NULL
927 : vertex->neighbors has not been updated yet
928 : do not allocate memory after qh.hash_table (need to free it cleanly)
929 :
930 : design:
931 : truncate neighbor sets to horizon facet for all new facets
932 : initialize a hash table
933 : for all new facets
934 : match facet with neighbors
935 : if unmatched facets (due to duplicate ridges)
936 : for each new facet with a duplicate ridge
937 : try to match facets with the same coplanar horizon
938 : if not all matched
939 : for each new facet with a duplicate ridge
940 : match it with a coplanar facet, or identify a pinched vertex
941 : if not merging and qh.FORCEoutput
942 : check for flipped facets
943 : */
944 29065 : coordT qh_matchnewfacets(qhT *qh /* qh.newfacet_list */) {
945 29065 : int numnew=0, hashcount=0, newskip;
946 : facetT *newfacet, *neighbor;
947 29065 : coordT maxdupdist= 0.0, maxdist2;
948 29065 : int dim= qh->hull_dim, hashsize, neighbor_i, neighbor_n;
949 : setT *neighbors;
950 : #ifndef qh_NOtrace
951 29065 : int facet_i, facet_n, numunused= 0;
952 : facetT *facet;
953 : #endif
954 :
955 29065 : trace1((qh, qh->ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
956 160557 : FORALLnew_facets {
957 131492 : numnew++;
958 : { /* inline qh_setzero(qh, newfacet->neighbors, 1, qh->hull_dim); */
959 131492 : neighbors= newfacet->neighbors;
960 131492 : neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
961 131492 : memset((char *)SETelemaddr_(neighbors, 1, void), 0, (size_t)(dim * SETelemsize));
962 : }
963 : }
964 :
965 29065 : qh_newhashtable(qh, numnew*(qh->hull_dim-1)); /* twice what is normally needed,
966 : but every ridge could be DUPLICATEridge */
967 29065 : hashsize= qh_setsize(qh, qh->hash_table);
968 29065 : if( hashsize == 0 ) return 0.0; /* make coverity happy */
969 160557 : FORALLnew_facets {
970 131492 : if (!newfacet->simplicial) {
971 0 : qh_fprintf(qh, qh->ferr, 6377, "qhull internal error (qh_matchnewfacets): expecting simplicial facets on qh.newfacet_list f%d for qh_matchneighbors, qh_matchneighbor, and qh_matchdupridge. Got non-simplicial f%d\n",
972 0 : qh->newfacet_list->id, newfacet->id);
973 0 : qh_errexit2(qh, qh_ERRqhull, newfacet, qh->newfacet_list);
974 : }
975 394476 : for (newskip=1; newskip<qh->hull_dim; newskip++) /* furthest/horizon already matched */
976 : /* hashsize>0 because hull_dim>1 and numnew>0 */
977 262984 : qh_matchneighbor(qh, newfacet, newskip, hashsize, &hashcount);
978 : #if 0 /* use the following to trap hashcount errors */
979 : {
980 : int count= 0, k;
981 : facetT *facet, *neighbor;
982 :
983 : count= 0;
984 : FORALLfacet_(qh->newfacet_list) { /* newfacet already in use */
985 : for (k=1; k < qh->hull_dim; k++) {
986 : neighbor= SETelemt_(facet->neighbors, k, facetT);
987 : if (!neighbor || neighbor == qh_DUPLICATEridge)
988 : count++;
989 : }
990 : if (facet == newfacet)
991 : break;
992 : }
993 : if (count != hashcount) {
994 : qh_fprintf(qh, qh->ferr, 6266, "qhull error (qh_matchnewfacets): after adding facet %d, hashcount %d != count %d\n",
995 : newfacet->id, hashcount, count);
996 : qh_errexit(qh, qh_ERRdebug, newfacet, NULL);
997 : }
998 : }
999 : #endif /* end of trap code */
1000 : } /* end FORALLnew_facets */
1001 29065 : if (hashcount) { /* all neighbors matched, except for qh_DUPLICATEridge neighbors */
1002 0 : qh_joggle_restart(qh, "ridge with multiple neighbors");
1003 0 : if (hashcount) {
1004 0 : FORALLnew_facets {
1005 0 : if (newfacet->dupridge) {
1006 0 : FOREACHneighbor_i_(qh, newfacet) {
1007 0 : if (neighbor == qh_DUPLICATEridge) {
1008 0 : maxdist2= qh_matchdupridge(qh, newfacet, neighbor_i, hashsize, &hashcount);
1009 0 : maximize_(maxdupdist, maxdist2);
1010 : }
1011 : }
1012 : }
1013 : }
1014 : }
1015 : }
1016 29065 : if (hashcount) {
1017 0 : qh_fprintf(qh, qh->ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
1018 : hashcount);
1019 0 : qh_printhashtable(qh, qh->ferr);
1020 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
1021 : }
1022 : #ifndef qh_NOtrace
1023 29065 : if (qh->IStracing >= 3) {
1024 0 : FOREACHfacet_i_(qh, qh->hash_table) {
1025 0 : if (!facet)
1026 0 : numunused++;
1027 : }
1028 0 : qh_fprintf(qh, qh->ferr, 3063, "qh_matchnewfacets: maxdupdist %2.2g, new facets %d, unused hash entries %d, hashsize %d\n",
1029 : maxdupdist, numnew, numunused, qh_setsize(qh, qh->hash_table));
1030 : }
1031 : #endif /* !qh_NOtrace */
1032 29065 : qh_setfree(qh, &qh->hash_table);
1033 29065 : if (qh->PREmerge || qh->MERGEexact) {
1034 29065 : if (qh->IStracing >= 4)
1035 0 : qh_printfacetlist(qh, qh->newfacet_list, NULL, qh_ALL);
1036 : }
1037 29065 : return maxdupdist;
1038 : } /* matchnewfacets */
1039 :
1040 :
1041 : /*-<a href="qh-poly_r.htm#TOC"
1042 : >-------------------------------</a><a name="matchvertices">-</a>
1043 :
1044 : qh_matchvertices(qh, firstindex, verticesA, skipA, verticesB, skipB, same )
1045 : tests whether vertices match with a single skip
1046 : starts match at firstindex since all new facets have a common vertex
1047 :
1048 : returns:
1049 : true if matched vertices
1050 : skip index for skipB
1051 : sets same iff vertices have the same orientation
1052 :
1053 : notes:
1054 : called by qh_matchneighbor and qh_matchdupridge
1055 : assumes skipA is in A and both sets are the same size
1056 :
1057 : design:
1058 : set up pointers
1059 : scan both sets checking for a match
1060 : test orientation
1061 : */
1062 151647 : boolT qh_matchvertices(qhT *qh, int firstindex, setT *verticesA, int skipA,
1063 : setT *verticesB, int *skipB, boolT *same) {
1064 151647 : vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
1065 :
1066 151647 : elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
1067 151647 : elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
1068 151647 : skipAp= SETelemaddr_(verticesA, skipA, vertexT);
1069 291249 : do if (elemAp != skipAp) {
1070 226961 : while (*elemAp != *elemBp++) {
1071 95469 : if (skipBp)
1072 20155 : return False;
1073 75314 : skipBp= elemBp; /* one extra like FOREACH */
1074 : }
1075 : /* coverity[overrun-local] */
1076 271094 : }while (*(++elemAp));
1077 131492 : if (!skipBp)
1078 76333 : skipBp= ++elemBp;
1079 131492 : *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB
1080 : verticesA and verticesB are the same size, otherwise trace4 may segfault */
1081 131492 : *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
1082 : /* coverity[overrun-local] */
1083 131492 : trace4((qh, qh->ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
1084 : skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
1085 131492 : return(True);
1086 : } /* matchvertices */
1087 :
1088 : /*-<a href="qh-poly_r.htm#TOC"
1089 : >-------------------------------</a><a name="newfacet">-</a>
1090 :
1091 : qh_newfacet(qh)
1092 : return a new facet
1093 :
1094 : returns:
1095 : all fields initialized or cleared (NULL)
1096 : preallocates neighbors set
1097 : */
1098 131512 : facetT *qh_newfacet(qhT *qh) {
1099 : facetT *facet;
1100 : void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
1101 :
1102 131512 : qh_memalloc_(qh, (int)sizeof(facetT), freelistp, facet, facetT);
1103 131512 : memset((char *)facet, (size_t)0, sizeof(facetT));
1104 131512 : if (qh->facet_id == qh->tracefacet_id)
1105 0 : qh->tracefacet= facet;
1106 131512 : facet->id= qh->facet_id++;
1107 131512 : facet->neighbors= qh_setnew(qh, qh->hull_dim);
1108 : #if !qh_COMPUTEfurthest
1109 131512 : facet->furthestdist= 0.0;
1110 : #endif
1111 : #if qh_MAXoutside
1112 131512 : if (qh->FORCEoutput && qh->APPROXhull)
1113 0 : facet->maxoutside= qh->MINoutside;
1114 : else
1115 131512 : facet->maxoutside= qh->DISTround; /* same value as test for QH7082 */
1116 : #endif
1117 131512 : facet->simplicial= True;
1118 131512 : facet->good= True;
1119 131512 : facet->newfacet= True;
1120 131512 : trace4((qh, qh->ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
1121 131512 : return(facet);
1122 : } /* newfacet */
1123 :
1124 :
1125 : /*-<a href="qh-poly_r.htm#TOC"
1126 : >-------------------------------</a><a name="newridge">-</a>
1127 :
1128 : qh_newridge()
1129 : return a new ridge
1130 : notes:
1131 : caller sets qh.traceridge
1132 : */
1133 64530 : ridgeT *qh_newridge(qhT *qh) {
1134 : ridgeT *ridge;
1135 : void **freelistp; /* used if !qh_NOmem by qh_memalloc_() */
1136 :
1137 64530 : qh_memalloc_(qh, (int)sizeof(ridgeT), freelistp, ridge, ridgeT);
1138 64530 : memset((char *)ridge, (size_t)0, sizeof(ridgeT));
1139 64530 : zinc_(Ztotridges);
1140 64530 : ridge->id= qh->ridge_id;
1141 64530 : if (qh->ridge_id == UINT_MAX) {
1142 0 : qh_fprintf(qh, qh->ferr, 7074, "qhull warning: more than 2^32 ridges. Qhull results are OK. Since the ridge ID wraps around to 0, two ridges may have the same identifier.\n");
1143 0 : qh->ridge_id = 0;
1144 : } else {
1145 64530 : qh->ridge_id++;
1146 : }
1147 64530 : trace4((qh, qh->ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
1148 64530 : return(ridge);
1149 : } /* newridge */
1150 :
1151 :
1152 : /*-<a href="qh-poly_r.htm#TOC"
1153 : >-------------------------------</a><a name="pointid">-</a>
1154 :
1155 : qh_pointid(qh, point )
1156 : return id for a point,
1157 : returns qh_IDnone(-3) if null, qh_IDinterior(-2) if interior, or qh_IDunknown(-1) if not known
1158 :
1159 : alternative code if point is in qh.first_point...
1160 : unsigned long id;
1161 : id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
1162 :
1163 : notes:
1164 : Valid points are non-negative
1165 : WARN64 -- id truncated to 32-bits, at most 2G points
1166 : NOerrors returned (QhullPoint::id)
1167 : if point not in point array
1168 : the code does a comparison of unrelated pointers.
1169 : */
1170 159888 : int qh_pointid(qhT *qh, pointT *point) {
1171 : ptr_intT offset, id;
1172 :
1173 159888 : if (!point || !qh)
1174 3 : return qh_IDnone;
1175 159885 : else if (point == qh->interior_point)
1176 0 : return qh_IDinterior;
1177 159885 : else if (point >= qh->first_point
1178 159885 : && point < qh->first_point + qh->num_points * qh->hull_dim) {
1179 159885 : offset= (ptr_intT)(point - qh->first_point);
1180 : /* coverity[divide_arg] */
1181 159885 : id= offset / qh->hull_dim;
1182 : } else {
1183 0 : id = qh_setindex(qh->other_points, point);
1184 0 : if (id >= 0) {
1185 0 : id += qh->num_points;
1186 : } else {
1187 0 : return qh_IDunknown;
1188 : }
1189 : }
1190 159885 : return (int)id;
1191 : } /* pointid */
1192 :
1193 : /*-<a href="qh-poly_r.htm#TOC"
1194 : >-------------------------------</a><a name="removefacet">-</a>
1195 :
1196 : qh_removefacet(qh, facet )
1197 : unlinks facet from qh.facet_list,
1198 :
1199 : returns:
1200 : updates qh.facet_list .newfacet_list .facet_next visible_list
1201 : decrements qh.num_facets
1202 :
1203 : see:
1204 : qh_appendfacet
1205 : */
1206 224395 : void qh_removefacet(qhT *qh, facetT *facet) {
1207 224395 : facetT *next= facet->next, *previous= facet->previous; /* next is always defined */
1208 :
1209 224395 : if (facet == qh->newfacet_list)
1210 11390 : qh->newfacet_list= next;
1211 224395 : if (facet == qh->facet_next)
1212 20349 : qh->facet_next= next;
1213 224395 : if (facet == qh->visible_list)
1214 58957 : qh->visible_list= next;
1215 224395 : if (previous) {
1216 224386 : previous->next= next;
1217 224386 : next->previous= previous;
1218 : }else { /* 1st facet in qh->facet_list */
1219 9 : qh->facet_list= next;
1220 9 : qh->facet_list->previous= NULL;
1221 : }
1222 224395 : qh->num_facets--;
1223 224395 : trace4((qh, qh->ferr, 4057, "qh_removefacet: removed f%d from facet_list, newfacet_list, and visible_list\n", facet->id));
1224 224395 : } /* removefacet */
1225 :
1226 :
1227 : /*-<a href="qh-poly_r.htm#TOC"
1228 : >-------------------------------</a><a name="removevertex">-</a>
1229 :
1230 : qh_removevertex(qh, vertex )
1231 : unlinks vertex from qh.vertex_list,
1232 :
1233 : returns:
1234 : updates qh.vertex_list .newvertex_list
1235 : decrements qh.num_vertices
1236 : */
1237 136291 : void qh_removevertex(qhT *qh, vertexT *vertex) {
1238 136291 : vertexT *next= vertex->next, *previous= vertex->previous; /* next is always defined */
1239 :
1240 136291 : trace4((qh, qh->ferr, 4058, "qh_removevertex: remove v%d from qh.vertex_list\n", vertex->id));
1241 136291 : if (vertex == qh->newvertex_list)
1242 0 : qh->newvertex_list= next;
1243 136291 : if (previous) {
1244 136274 : previous->next= next;
1245 136274 : next->previous= previous;
1246 : }else { /* 1st vertex in qh->vertex_list */
1247 17 : qh->vertex_list= next;
1248 17 : qh->vertex_list->previous= NULL;
1249 : }
1250 136291 : qh->num_vertices--;
1251 136291 : } /* removevertex */
1252 :
1253 :
1254 : /*-<a href="qh-poly_r.htm#TOC"
1255 : >-------------------------------</a><a name="update_vertexneighbors">-</a>
1256 :
1257 : qh_update_vertexneighbors(qh )
1258 : update vertex neighbors and delete interior vertices
1259 :
1260 : returns:
1261 : if qh.VERTEXneighbors,
1262 : if qh.newvertex_list,
1263 : removes visible neighbors from vertex neighbors
1264 : if qh.newfacet_list
1265 : adds new facets to vertex neighbors
1266 : if qh.visible_list
1267 : interior vertices added to qh.del_vertices for later partitioning as coplanar points
1268 : if not qh.VERTEXneighbors (not merging)
1269 : interior vertices of visible facets added to qh.del_vertices for later partitioning as coplanar points
1270 :
1271 : notes
1272 : [jan'19] split off qh_update_vertexneighbors_cone. Optimize the remaining cases in a future release
1273 : called by qh_triangulate_facet after triangulating a non-simplicial facet, followed by reset_lists
1274 : called by qh_triangulate after triangulating null and mirror facets
1275 : called by qh_all_vertexmerges after calling qh_merge_pinchedvertices
1276 :
1277 : design:
1278 : if qh.VERTEXneighbors
1279 : for each vertex on newvertex_list (i.e., new vertices and vertices of new facets)
1280 : delete visible facets from vertex neighbors
1281 : for each new facet on newfacet_list
1282 : for each vertex of facet
1283 : append facet to vertex neighbors
1284 : for each visible facet on qh.visible_list
1285 : for each vertex of facet
1286 : if the vertex is not on a new facet and not itself deleted
1287 : if the vertex has a not-visible neighbor (due to merging)
1288 : remove the visible facet from the vertex's neighbors
1289 : otherwise
1290 : add the vertex to qh.del_vertices for later deletion
1291 :
1292 : if not qh.VERTEXneighbors (not merging)
1293 : for each vertex of a visible facet
1294 : if the vertex is not on a new facet and not itself deleted
1295 : add the vertex to qh.del_vertices for later deletion
1296 : */
1297 14408 : void qh_update_vertexneighbors(qhT *qh /* qh.newvertex_list, newfacet_list, visible_list */) {
1298 14408 : facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
1299 : vertexT *vertex, **vertexp;
1300 14408 : int neighborcount= 0;
1301 :
1302 14408 : if (qh->VERTEXneighbors) {
1303 14408 : trace3((qh, qh->ferr, 3013, "qh_update_vertexneighbors: update v.neighbors for qh.newvertex_list (v%d) and qh.newfacet_list (f%d)\n",
1304 : getid_(qh->newvertex_list), getid_(qh->newfacet_list)));
1305 29053 : FORALLvertex_(qh->newvertex_list) {
1306 14645 : neighborcount= 0;
1307 247019 : FOREACHneighbor_(vertex) {
1308 232374 : if (neighbor->visible) {
1309 144518 : neighborcount++;
1310 144518 : SETref_(neighbor)= NULL;
1311 : }
1312 : }
1313 14645 : if (neighborcount) {
1314 14645 : trace4((qh, qh->ferr, 4046, "qh_update_vertexneighbors: delete %d of %d vertex neighbors for v%d. Removes to-be-deleted, visible facets\n",
1315 : neighborcount, qh_setsize(qh, vertex->neighbors), vertex->id));
1316 14645 : qh_setcompact(qh, vertex->neighbors);
1317 : }
1318 : }
1319 72496 : FORALLnew_facets {
1320 58088 : if (qh->first_newfacet && newfacet->id >= qh->first_newfacet) {
1321 232352 : FOREACHvertex_(newfacet->vertices)
1322 174264 : qh_setappend(qh, &vertex->neighbors, newfacet);
1323 : }else { /* called after qh_merge_pinchedvertices. In 7-D, many more neighbors than new facets. qh_setin is expensive */
1324 0 : FOREACHvertex_(newfacet->vertices)
1325 0 : qh_setunique(qh, &vertex->neighbors, newfacet);
1326 : }
1327 : }
1328 14408 : trace3((qh, qh->ferr, 3058, "qh_update_vertexneighbors: delete interior vertices for qh.visible_list (f%d)\n",
1329 : getid_(qh->visible_list)));
1330 14408 : FORALLvisible_facets {
1331 0 : FOREACHvertex_(visible->vertices) {
1332 0 : if (!vertex->newfacet && !vertex->deleted) {
1333 0 : FOREACHneighbor_(vertex) { /* this can happen under merging */
1334 0 : if (!neighbor->visible)
1335 0 : break;
1336 : }
1337 0 : if (neighbor)
1338 0 : qh_setdel(vertex->neighbors, visible);
1339 : else {
1340 0 : vertex->deleted= True;
1341 0 : qh_setappend(qh, &qh->del_vertices, vertex);
1342 0 : trace2((qh, qh->ferr, 2041, "qh_update_vertexneighbors: delete interior vertex p%d(v%d) of visible f%d\n",
1343 : qh_pointid(qh, vertex->point), vertex->id, visible->id));
1344 : }
1345 : }
1346 : }
1347 : }
1348 : }else { /* !VERTEXneighbors */
1349 0 : trace3((qh, qh->ferr, 3058, "qh_update_vertexneighbors: delete old vertices for qh.visible_list (f%d)\n",
1350 : getid_(qh->visible_list)));
1351 0 : FORALLvisible_facets {
1352 0 : FOREACHvertex_(visible->vertices) {
1353 0 : if (!vertex->newfacet && !vertex->deleted) {
1354 0 : vertex->deleted= True;
1355 0 : qh_setappend(qh, &qh->del_vertices, vertex);
1356 0 : trace2((qh, qh->ferr, 2042, "qh_update_vertexneighbors: will delete interior vertex p%d(v%d) of visible f%d\n",
1357 : qh_pointid(qh, vertex->point), vertex->id, visible->id));
1358 : }
1359 : }
1360 : }
1361 : }
1362 14408 : } /* update_vertexneighbors */
1363 :
1364 : /*-<a href="qh-poly_r.htm#TOC"
1365 : >-------------------------------</a><a name="update_vertexneighbors_cone">-</a>
1366 :
1367 : qh_update_vertexneighbors_cone(qh )
1368 : update vertex neighbors for a cone of new facets and delete interior vertices
1369 :
1370 : returns:
1371 : if qh.VERTEXneighbors,
1372 : if qh.newvertex_list,
1373 : removes visible neighbors from vertex neighbors
1374 : if qh.newfacet_list
1375 : adds new facets to vertex neighbors
1376 : if qh.visible_list
1377 : interior vertices added to qh.del_vertices for later partitioning as coplanar points
1378 : if not qh.VERTEXneighbors (not merging)
1379 : interior vertices of visible facets added to qh.del_vertices for later partitioning as coplanar points
1380 :
1381 : notes
1382 : called by qh_addpoint after create cone and before premerge
1383 :
1384 : design:
1385 : if qh.VERTEXneighbors
1386 : for each vertex on newvertex_list (i.e., new vertices and vertices of new facets)
1387 : delete visible facets from vertex neighbors
1388 : for each new facet on newfacet_list
1389 : for each vertex of facet
1390 : append facet to vertex neighbors
1391 : for each visible facet on qh.visible_list
1392 : for each vertex of facet
1393 : if the vertex is not on a new facet and not itself deleted
1394 : if the vertex has a not-visible neighbor (due to merging)
1395 : remove the visible facet from the vertex's neighbors
1396 : otherwise
1397 : add the vertex to qh.del_vertices for later deletion
1398 :
1399 : if not qh.VERTEXneighbors (not merging)
1400 : for each vertex of a visible facet
1401 : if the vertex is not on a new facet and not itself deleted
1402 : add the vertex to qh.del_vertices for later deletion
1403 :
1404 : */
1405 14660 : void qh_update_vertexneighbors_cone(qhT *qh /* qh.newvertex_list, newfacet_list, visible_list */) {
1406 14660 : facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
1407 : vertexT *vertex, **vertexp;
1408 14660 : int delcount= 0;
1409 :
1410 14660 : if (qh->VERTEXneighbors) {
1411 14650 : trace3((qh, qh->ferr, 3059, "qh_update_vertexneighbors_cone: update v.neighbors for qh.newvertex_list (v%d) and qh.newfacet_list (f%d)\n",
1412 : getid_(qh->newvertex_list), getid_(qh->newfacet_list)));
1413 102662 : FORALLvertex_(qh->newvertex_list) {
1414 88012 : delcount= 0;
1415 503720 : FOREACHneighbor_(vertex) {
1416 415708 : if (neighbor->visible) { /* alternative design is a loop over visible facets, but needs qh_setdel() */
1417 121836 : delcount++;
1418 121836 : qh_setdelnth(qh, vertex->neighbors, SETindex_(vertex->neighbors, neighbor));
1419 121836 : neighborp--; /* repeat */
1420 : }
1421 : }
1422 88012 : if (delcount) {
1423 73362 : trace4((qh, qh->ferr, 4021, "qh_update_vertexneighbors_cone: deleted %d visible vertexneighbors of v%d\n",
1424 : delcount, vertex->id));
1425 : }
1426 : }
1427 88012 : FORALLnew_facets {
1428 293448 : FOREACHvertex_(newfacet->vertices)
1429 220086 : qh_setappend(qh, &vertex->neighbors, newfacet);
1430 : }
1431 14650 : trace3((qh, qh->ferr, 3065, "qh_update_vertexneighbors_cone: delete interior vertices, if any, for qh.visible_list (f%d)\n",
1432 : getid_(qh->visible_list)));
1433 53537 : FORALLvisible_facets {
1434 160723 : FOREACHvertex_(visible->vertices) {
1435 121836 : if (!vertex->newfacet && !vertex->deleted) {
1436 0 : FOREACHneighbor_(vertex) { /* this can happen under merging, qh_checkfacet QH4025 */
1437 0 : if (!neighbor->visible)
1438 0 : break;
1439 : }
1440 0 : if (neighbor)
1441 0 : qh_setdel(vertex->neighbors, visible);
1442 : else {
1443 0 : vertex->deleted= True;
1444 0 : qh_setappend(qh, &qh->del_vertices, vertex);
1445 0 : trace2((qh, qh->ferr, 2102, "qh_update_vertexneighbors_cone: will delete interior vertex p%d(v%d) of visible f%d\n",
1446 : qh_pointid(qh, vertex->point), vertex->id, visible->id));
1447 : }
1448 : }
1449 : }
1450 : }
1451 : }else { /* !VERTEXneighbors */
1452 10 : trace3((qh, qh->ferr, 3066, "qh_update_vertexneighbors_cone: delete interior vertices for qh.visible_list (f%d)\n",
1453 : getid_(qh->visible_list)));
1454 32 : FORALLvisible_facets {
1455 88 : FOREACHvertex_(visible->vertices) {
1456 66 : if (!vertex->newfacet && !vertex->deleted) {
1457 0 : vertex->deleted= True;
1458 0 : qh_setappend(qh, &qh->del_vertices, vertex);
1459 0 : trace2((qh, qh->ferr, 2059, "qh_update_vertexneighbors_cone: will delete interior vertex p%d(v%d) of visible f%d\n",
1460 : qh_pointid(qh, vertex->point), vertex->id, visible->id));
1461 : }
1462 : }
1463 : }
1464 : }
1465 14660 : } /* update_vertexneighbors_cone */
1466 :
|