| 1 | chuckv | 3138 | /*<html><pre>  -<a                             href="qh-io.htm" | 
| 2 |  |  | >-------------------------------</a><a name="TOP">-</a> | 
| 3 |  |  |  | 
| 4 |  |  | io.c | 
| 5 |  |  | Input/Output routines of qhull application | 
| 6 |  |  |  | 
| 7 |  |  | see qh-io.htm and io.h | 
| 8 |  |  |  | 
| 9 |  |  | see user.c for qh_errprint and qh_printfacetlist | 
| 10 |  |  |  | 
| 11 |  |  | unix.c calls qh_readpoints and qh_produce_output | 
| 12 |  |  |  | 
| 13 |  |  | unix.c and user.c are the only callers of io.c functions | 
| 14 |  |  | This allows the user to avoid loading io.o from qhull.a | 
| 15 |  |  |  | 
| 16 |  |  | copyright (c) 1993-2003 The Geometry Center | 
| 17 |  |  | */ | 
| 18 |  |  |  | 
| 19 |  |  | #include "QuickHull/qhull_a.h" | 
| 20 |  |  |  | 
| 21 |  |  | /*========= -functions in alphabetical order after qh_produce_output()  =====*/ | 
| 22 |  |  |  | 
| 23 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 24 |  |  | >-------------------------------</a><a name="produce_output">-</a> | 
| 25 |  |  |  | 
| 26 |  |  | qh_produce_output() | 
| 27 |  |  | prints out the result of qhull in desired format | 
| 28 |  |  | if qh.GETarea | 
| 29 |  |  | computes and prints area and volume | 
| 30 |  |  | qh.PRINTout[] is an array of output formats | 
| 31 |  |  |  | 
| 32 |  |  | notes: | 
| 33 |  |  | prints output in qh.PRINTout order | 
| 34 |  |  | */ | 
| 35 |  |  | void qh_produce_output(void) { | 
| 36 |  |  | int i, tempsize= qh_setsize ((setT*)qhmem.tempstack), d_1; | 
| 37 |  |  |  | 
| 38 |  |  | if (qh VORONOI) { | 
| 39 |  |  | qh_clearcenters (qh_ASvoronoi); | 
| 40 |  |  | qh_vertexneighbors(); | 
| 41 |  |  | } | 
| 42 |  |  | if (qh TRIangulate) { | 
| 43 |  |  | qh_triangulate(); | 
| 44 |  |  | if (qh VERIFYoutput && !qh CHECKfrequently) | 
| 45 |  |  | qh_checkpolygon (qh facet_list); | 
| 46 |  |  | } | 
| 47 |  |  | qh_findgood_all (qh facet_list); | 
| 48 |  |  | if (qh GETarea) | 
| 49 |  |  | qh_getarea(qh facet_list); | 
| 50 |  |  | if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2) | 
| 51 |  |  | qh_markkeep (qh facet_list); | 
| 52 |  |  | if (qh PRINTsummary) | 
| 53 |  |  | qh_printsummary(qh ferr); | 
| 54 |  |  | else if (qh PRINTout[0] == qh_PRINTnone) | 
| 55 |  |  | qh_printsummary(qh fout); | 
| 56 |  |  | for (i= 0; i < qh_PRINTEND; i++) | 
| 57 |  |  | qh_printfacets (qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL); | 
| 58 |  |  | qh_allstatistics(); | 
| 59 |  |  | if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN)) | 
| 60 |  |  | qh_printstats (qh ferr, qhstat precision, NULL); | 
| 61 |  |  | if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0)) | 
| 62 |  |  | qh_printstats (qh ferr, qhstat vridges, NULL); | 
| 63 |  |  | if (qh PRINTstatistics) { | 
| 64 |  |  | qh_collectstatistics(); | 
| 65 |  |  | qh_printstatistics(qh ferr, ""); | 
| 66 |  |  | qh_memstatistics (qh ferr); | 
| 67 |  |  | d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize; | 
| 68 |  |  | fprintf(qh ferr, "\ | 
| 69 |  |  | size in bytes: merge %d ridge %d vertex %d facet %d\n\ | 
| 70 |  |  | normal %d ridge vertices %d facet vertices or neighbors %d\n", | 
| 71 |  |  | sizeof(mergeT), sizeof(ridgeT), | 
| 72 |  |  | sizeof(vertexT), sizeof(facetT), | 
| 73 |  |  | qh normal_size, d_1, d_1 + SETelemsize); | 
| 74 |  |  | } | 
| 75 |  |  | if (qh_setsize ((setT*)qhmem.tempstack) != tempsize) { | 
| 76 |  |  | fprintf (qh ferr, "qhull internal error (qh_produce_output): temporary sets not empty (%d)\n", | 
| 77 |  |  | qh_setsize ((setT*)qhmem.tempstack)); | 
| 78 |  |  | qh_errexit (qh_ERRqhull, NULL, NULL); | 
| 79 |  |  | } | 
| 80 |  |  | } /* produce_output */ | 
| 81 |  |  |  | 
| 82 |  |  |  | 
| 83 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 84 |  |  | >-------------------------------</a><a name="dfacet">-</a> | 
| 85 |  |  |  | 
| 86 |  |  | dfacet( id ) | 
| 87 |  |  | print facet by id, for debugging | 
| 88 |  |  |  | 
| 89 |  |  | */ | 
| 90 |  |  | void dfacet (unsigned id) { | 
| 91 |  |  | facetT *facet; | 
| 92 |  |  |  | 
| 93 |  |  | FORALLfacets { | 
| 94 |  |  | if (facet->id == id) { | 
| 95 |  |  | qh_printfacet (qh fout, facet); | 
| 96 |  |  | break; | 
| 97 |  |  | } | 
| 98 |  |  | } | 
| 99 |  |  | } /* dfacet */ | 
| 100 |  |  |  | 
| 101 |  |  |  | 
| 102 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 103 |  |  | >-------------------------------</a><a name="dvertex">-</a> | 
| 104 |  |  |  | 
| 105 |  |  | dvertex( id ) | 
| 106 |  |  | print vertex by id, for debugging | 
| 107 |  |  | */ | 
| 108 |  |  | void dvertex (unsigned id) { | 
| 109 |  |  | vertexT *vertex; | 
| 110 |  |  |  | 
| 111 |  |  | FORALLvertices { | 
| 112 |  |  | if (vertex->id == id) { | 
| 113 |  |  | qh_printvertex (qh fout, vertex); | 
| 114 |  |  | break; | 
| 115 |  |  | } | 
| 116 |  |  | } | 
| 117 |  |  | } /* dvertex */ | 
| 118 |  |  |  | 
| 119 |  |  |  | 
| 120 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 121 |  |  | >-------------------------------</a><a name="compare_vertexpoint">-</a> | 
| 122 |  |  |  | 
| 123 |  |  | qh_compare_vertexpoint( p1, p2 ) | 
| 124 |  |  | used by qsort() to order vertices by point id | 
| 125 |  |  | */ | 
| 126 |  |  | int qh_compare_vertexpoint(const void *p1, const void *p2) { | 
| 127 |  |  | vertexT *a= *((vertexT **)p1), *b= *((vertexT **)p2); | 
| 128 |  |  |  | 
| 129 |  |  | return ((qh_pointid(a->point) > qh_pointid(b->point)?1:-1)); | 
| 130 |  |  | } /* compare_vertexpoint */ | 
| 131 |  |  |  | 
| 132 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 133 |  |  | >-------------------------------</a><a name="compare_facetarea">-</a> | 
| 134 |  |  |  | 
| 135 |  |  | qh_compare_facetarea( p1, p2 ) | 
| 136 |  |  | used by qsort() to order facets by area | 
| 137 |  |  | */ | 
| 138 |  |  | int qh_compare_facetarea(const void *p1, const void *p2) { | 
| 139 |  |  | facetT *a= *((facetT **)p1), *b= *((facetT **)p2); | 
| 140 |  |  |  | 
| 141 |  |  | if (!a->isarea) | 
| 142 |  |  | return -1; | 
| 143 |  |  | if (!b->isarea) | 
| 144 |  |  | return 1; | 
| 145 |  |  | if (a->f.area > b->f.area) | 
| 146 |  |  | return 1; | 
| 147 |  |  | else if (a->f.area == b->f.area) | 
| 148 |  |  | return 0; | 
| 149 |  |  | return -1; | 
| 150 |  |  | } /* compare_facetarea */ | 
| 151 |  |  |  | 
| 152 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 153 |  |  | >-------------------------------</a><a name="compare_facetmerge">-</a> | 
| 154 |  |  |  | 
| 155 |  |  | qh_compare_facetmerge( p1, p2 ) | 
| 156 |  |  | used by qsort() to order facets by number of merges | 
| 157 |  |  | */ | 
| 158 |  |  | int qh_compare_facetmerge(const void *p1, const void *p2) { | 
| 159 |  |  | facetT *a= *((facetT **)p1), *b= *((facetT **)p2); | 
| 160 |  |  |  | 
| 161 |  |  | return (a->nummerge - b->nummerge); | 
| 162 |  |  | } /* compare_facetvisit */ | 
| 163 |  |  |  | 
| 164 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 165 |  |  | >-------------------------------</a><a name="compare_facetvisit">-</a> | 
| 166 |  |  |  | 
| 167 |  |  | qh_compare_facetvisit( p1, p2 ) | 
| 168 |  |  | used by qsort() to order facets by visit id or id | 
| 169 |  |  | */ | 
| 170 |  |  | int qh_compare_facetvisit(const void *p1, const void *p2) { | 
| 171 |  |  | facetT *a= *((facetT **)p1), *b= *((facetT **)p2); | 
| 172 |  |  | int i,j; | 
| 173 |  |  |  | 
| 174 |  |  | if (!(i= a->visitid)) | 
| 175 |  |  | i= - a->id; /* do not convert to int */ | 
| 176 |  |  | if (!(j= b->visitid)) | 
| 177 |  |  | j= - b->id; | 
| 178 |  |  | return (i - j); | 
| 179 |  |  | } /* compare_facetvisit */ | 
| 180 |  |  |  | 
| 181 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 182 |  |  | >-------------------------------</a><a name="countfacets">-</a> | 
| 183 |  |  |  | 
| 184 |  |  | qh_countfacets( facetlist, facets, printall, | 
| 185 |  |  | numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  ) | 
| 186 |  |  | count good facets for printing and set visitid | 
| 187 |  |  | if allfacets, ignores qh_skipfacet() | 
| 188 |  |  |  | 
| 189 |  |  | notes: | 
| 190 |  |  | qh_printsummary and qh_countfacets must match counts | 
| 191 |  |  |  | 
| 192 |  |  | returns: | 
| 193 |  |  | numfacets, numsimplicial, total neighbors, numridges, coplanars | 
| 194 |  |  | each facet with ->visitid indicating 1-relative position | 
| 195 |  |  | ->visitid==0 indicates not good | 
| 196 |  |  |  | 
| 197 |  |  | notes | 
| 198 |  |  | numfacets >= numsimplicial | 
| 199 |  |  | if qh.NEWfacets, | 
| 200 |  |  | does not count visible facets (matches qh_printafacet) | 
| 201 |  |  |  | 
| 202 |  |  | design: | 
| 203 |  |  | for all facets on facetlist and in facets set | 
| 204 |  |  | unless facet is skipped or visible (i.e., will be deleted) | 
| 205 |  |  | mark facet->visitid | 
| 206 |  |  | update counts | 
| 207 |  |  | */ | 
| 208 |  |  | void qh_countfacets (facetT *facetlist, setT *facets, boolT printall, | 
| 209 |  |  | int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) { | 
| 210 |  |  | facetT *facet, **facetp; | 
| 211 |  |  | int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0; | 
| 212 |  |  |  | 
| 213 |  |  | FORALLfacet_(facetlist) { | 
| 214 |  |  | if ((facet->visible && qh NEWfacets) | 
| 215 |  |  | || (!printall && qh_skipfacet(facet))) | 
| 216 |  |  | facet->visitid= 0; | 
| 217 |  |  | else { | 
| 218 |  |  | facet->visitid= ++numfacets; | 
| 219 |  |  | totneighbors += qh_setsize (facet->neighbors); | 
| 220 |  |  | if (facet->simplicial) { | 
| 221 |  |  | numsimplicial++; | 
| 222 |  |  | if (facet->keepcentrum && facet->tricoplanar) | 
| 223 |  |  | numtricoplanars++; | 
| 224 |  |  | }else | 
| 225 |  |  | numridges += qh_setsize (facet->ridges); | 
| 226 |  |  | if (facet->coplanarset) | 
| 227 |  |  | numcoplanars += qh_setsize (facet->coplanarset); | 
| 228 |  |  | } | 
| 229 |  |  | } | 
| 230 |  |  | FOREACHfacet_(facets) { | 
| 231 |  |  | if ((facet->visible && qh NEWfacets) | 
| 232 |  |  | || (!printall && qh_skipfacet(facet))) | 
| 233 |  |  | facet->visitid= 0; | 
| 234 |  |  | else { | 
| 235 |  |  | facet->visitid= ++numfacets; | 
| 236 |  |  | totneighbors += qh_setsize (facet->neighbors); | 
| 237 |  |  | if (facet->simplicial){ | 
| 238 |  |  | numsimplicial++; | 
| 239 |  |  | if (facet->keepcentrum && facet->tricoplanar) | 
| 240 |  |  | numtricoplanars++; | 
| 241 |  |  | }else | 
| 242 |  |  | numridges += qh_setsize (facet->ridges); | 
| 243 |  |  | if (facet->coplanarset) | 
| 244 |  |  | numcoplanars += qh_setsize (facet->coplanarset); | 
| 245 |  |  | } | 
| 246 |  |  | } | 
| 247 |  |  | qh visit_id += numfacets+1; | 
| 248 |  |  | *numfacetsp= numfacets; | 
| 249 |  |  | *numsimplicialp= numsimplicial; | 
| 250 |  |  | *totneighborsp= totneighbors; | 
| 251 |  |  | *numridgesp= numridges; | 
| 252 |  |  | *numcoplanarsp= numcoplanars; | 
| 253 |  |  | *numtricoplanarsp= numtricoplanars; | 
| 254 |  |  | } /* countfacets */ | 
| 255 |  |  |  | 
| 256 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 257 |  |  | >-------------------------------</a><a name="detvnorm">-</a> | 
| 258 |  |  |  | 
| 259 |  |  | qh_detvnorm( vertex, vertexA, centers, offset ) | 
| 260 |  |  | compute separating plane of the Voronoi diagram for a pair of input sites | 
| 261 |  |  | centers= set of facets (i.e., Voronoi vertices) | 
| 262 |  |  | facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded) | 
| 263 |  |  |  | 
| 264 |  |  | assumes: | 
| 265 |  |  | qh_ASvoronoi and qh_vertexneighbors() already set | 
| 266 |  |  |  | 
| 267 |  |  | returns: | 
| 268 |  |  | norm | 
| 269 |  |  | a pointer into qh.gm_matrix to qh.hull_dim-1 reals | 
| 270 |  |  | copy the data before reusing qh.gm_matrix | 
| 271 |  |  | offset | 
| 272 |  |  | if 'QVn' | 
| 273 |  |  | sign adjusted so that qh.GOODvertexp is inside | 
| 274 |  |  | else | 
| 275 |  |  | sign adjusted so that vertex is inside | 
| 276 |  |  |  | 
| 277 |  |  | qh.gm_matrix= simplex of points from centers relative to first center | 
| 278 |  |  |  | 
| 279 |  |  | notes: | 
| 280 |  |  | in io.c so that code for 'v Tv' can be removed by removing io.c | 
| 281 |  |  | returns pointer into qh.gm_matrix to avoid tracking of temporary memory | 
| 282 |  |  |  | 
| 283 |  |  | design: | 
| 284 |  |  | determine midpoint of input sites | 
| 285 |  |  | build points as the set of Voronoi vertices | 
| 286 |  |  | select a simplex from points (if necessary) | 
| 287 |  |  | incl. midpoint if the Voronoi region is unbounded | 
| 288 |  |  | relocate the first vertex of the simplex to the origin | 
| 289 |  |  | compute the normalized hyperplane through the simplex | 
| 290 |  |  | orient the hyperplane toward 'QVn' or 'vertex' | 
| 291 |  |  | if 'Tv' or 'Ts' | 
| 292 |  |  | if bounded | 
| 293 |  |  | test that hyperplane is the perpendicular bisector of the input sites | 
| 294 |  |  | test that Voronoi vertices not in the simplex are still on the hyperplane | 
| 295 |  |  | free up temporary memory | 
| 296 |  |  | */ | 
| 297 |  |  | pointT *qh_detvnorm (vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) { | 
| 298 |  |  | facetT *facet, **facetp; | 
| 299 |  |  | int  i, k, pointid, pointidA, point_i, point_n; | 
| 300 |  |  | setT *simplex= NULL; | 
| 301 |  |  | pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint; | 
| 302 |  |  | coordT *coord, *gmcoord, *normalp; | 
| 303 |  |  | setT *points= qh_settemp (qh TEMPsize); | 
| 304 |  |  | boolT nearzero= False; | 
| 305 |  |  | boolT unbounded= False; | 
| 306 |  |  | int numcenters= 0; | 
| 307 |  |  | int dim= qh hull_dim - 1; | 
| 308 |  |  | realT dist, offset, angle, zero= 0.0; | 
| 309 |  |  |  | 
| 310 |  |  | midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */ | 
| 311 |  |  | for (k= 0; k < dim; k++) | 
| 312 |  |  | midpoint[k]= (vertex->point[k] + vertexA->point[k])/2; | 
| 313 |  |  | FOREACHfacet_(centers) { | 
| 314 |  |  | numcenters++; | 
| 315 |  |  | if (!facet->visitid) | 
| 316 |  |  | unbounded= True; | 
| 317 |  |  | else { | 
| 318 |  |  | if (!facet->center) | 
| 319 |  |  | facet->center= qh_facetcenter (facet->vertices); | 
| 320 |  |  | qh_setappend (&points, facet->center); | 
| 321 |  |  | } | 
| 322 |  |  | } | 
| 323 |  |  | if (numcenters > dim) { | 
| 324 |  |  | simplex= qh_settemp (qh TEMPsize); | 
| 325 |  |  | qh_setappend (&simplex, vertex->point); | 
| 326 |  |  | if (unbounded) | 
| 327 |  |  | qh_setappend (&simplex, midpoint); | 
| 328 |  |  | qh_maxsimplex (dim, points, NULL, 0, &simplex); | 
| 329 |  |  | qh_setdelnth (simplex, 0); | 
| 330 |  |  | }else if (numcenters == dim) { | 
| 331 |  |  | if (unbounded) | 
| 332 |  |  | qh_setappend (&points, midpoint); | 
| 333 |  |  | simplex= points; | 
| 334 |  |  | }else { | 
| 335 |  |  | fprintf(qh ferr, "qh_detvnorm: too few points (%d) to compute separating plane\n", numcenters); | 
| 336 |  |  | qh_errexit (qh_ERRqhull, NULL, NULL); | 
| 337 |  |  | } | 
| 338 |  |  | i= 0; | 
| 339 |  |  | gmcoord= qh gm_matrix; | 
| 340 |  |  | point0= SETfirstt_(simplex, pointT); | 
| 341 |  |  | FOREACHpoint_(simplex) { | 
| 342 |  |  | if (qh IStracing >= 4) | 
| 343 |  |  | qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint", | 
| 344 |  |  | &point, 1, dim); | 
| 345 |  |  | if (point != point0) { | 
| 346 |  |  | qh gm_row[i++]= gmcoord; | 
| 347 |  |  | coord= point0; | 
| 348 |  |  | for (k= dim; k--; ) | 
| 349 |  |  | *(gmcoord++)= *point++ - *coord++; | 
| 350 |  |  | } | 
| 351 |  |  | } | 
| 352 |  |  | qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */ | 
| 353 |  |  | normal= gmcoord; | 
| 354 |  |  | qh_sethyperplane_gauss (dim, qh gm_row, point0, True, | 
| 355 |  |  | normal, &offset, &nearzero); | 
| 356 |  |  | if (qh GOODvertexp == vertexA->point) | 
| 357 |  |  | inpoint= vertexA->point; | 
| 358 |  |  | else | 
| 359 |  |  | inpoint= vertex->point; | 
| 360 |  |  | zinc_(Zdistio); | 
| 361 |  |  | dist= qh_distnorm (dim, inpoint, normal, &offset); | 
| 362 |  |  | if (dist > 0) { | 
| 363 |  |  | offset= -offset; | 
| 364 |  |  | normalp= normal; | 
| 365 |  |  | for (k= dim; k--; ) { | 
| 366 |  |  | *normalp= -(*normalp); | 
| 367 |  |  | normalp++; | 
| 368 |  |  | } | 
| 369 |  |  | } | 
| 370 |  |  | if (qh VERIFYoutput || qh PRINTstatistics) { | 
| 371 |  |  | pointid= qh_pointid (vertex->point); | 
| 372 |  |  | pointidA= qh_pointid (vertexA->point); | 
| 373 |  |  | if (!unbounded) { | 
| 374 |  |  | zinc_(Zdiststat); | 
| 375 |  |  | dist= qh_distnorm (dim, midpoint, normal, &offset); | 
| 376 |  |  | if (dist < 0) | 
| 377 |  |  | dist= -dist; | 
| 378 |  |  | zzinc_(Zridgemid); | 
| 379 |  |  | wwmax_(Wridgemidmax, dist); | 
| 380 |  |  | wwadd_(Wridgemid, dist); | 
| 381 |  |  | trace4((qh ferr, "qh_detvnorm: points %d %d midpoint dist %2.2g\n", pointid, pointidA, dist)); | 
| 382 |  |  | for (k= 0; k < dim; k++) | 
| 383 |  |  | midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */ | 
| 384 |  |  | qh_normalize (midpoint, dim, False); | 
| 385 |  |  | angle= qh_distnorm (dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */ | 
| 386 |  |  | if (angle < 0.0) | 
| 387 |  |  | angle= angle + 1.0; | 
| 388 |  |  | else | 
| 389 |  |  | angle= angle - 1.0; | 
| 390 |  |  | if (angle < 0.0) | 
| 391 |  |  | angle -= angle; | 
| 392 |  |  | trace4((qh ferr, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n", pointid, pointidA, angle, nearzero)); | 
| 393 |  |  | if (nearzero) { | 
| 394 |  |  | zzinc_(Zridge0); | 
| 395 |  |  | wwmax_(Wridge0max, angle); | 
| 396 |  |  | wwadd_(Wridge0, angle); | 
| 397 |  |  | }else { | 
| 398 |  |  | zzinc_(Zridgeok) | 
| 399 |  |  | wwmax_(Wridgeokmax, angle); | 
| 400 |  |  | wwadd_(Wridgeok, angle); | 
| 401 |  |  | } | 
| 402 |  |  | } | 
| 403 |  |  | if (simplex != points) { | 
| 404 |  |  | FOREACHpoint_i_(points) { | 
| 405 |  |  | if (!qh_setin (simplex, point)) { | 
| 406 |  |  | facet= SETelemt_(centers, point_i, facetT); | 
| 407 |  |  | zinc_(Zdiststat); | 
| 408 |  |  | dist= qh_distnorm (dim, point, normal, &offset); | 
| 409 |  |  | if (dist < 0) | 
| 410 |  |  | dist= -dist; | 
| 411 |  |  | zzinc_(Zridge); | 
| 412 |  |  | wwmax_(Wridgemax, dist); | 
| 413 |  |  | wwadd_(Wridge, dist); | 
| 414 |  |  | trace4((qh ferr, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n", pointid, pointidA, facet->visitid, dist)); | 
| 415 |  |  | } | 
| 416 |  |  | } | 
| 417 |  |  | } | 
| 418 |  |  | } | 
| 419 |  |  | *offsetp= offset; | 
| 420 |  |  | if (simplex != points) | 
| 421 |  |  | qh_settempfree (&simplex); | 
| 422 |  |  | qh_settempfree (&points); | 
| 423 |  |  | return normal; | 
| 424 |  |  | } /* detvnorm */ | 
| 425 |  |  |  | 
| 426 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 427 |  |  | >-------------------------------</a><a name="detvridge">-</a> | 
| 428 |  |  |  | 
| 429 |  |  | qh_detvridge( vertexA ) | 
| 430 |  |  | determine Voronoi ridge from 'seen' neighbors of vertexA | 
| 431 |  |  | incl. one vertex-at-infinite if an !neighbor->visitid | 
| 432 |  |  |  | 
| 433 |  |  | returns: | 
| 434 |  |  | temporary set of centers (facets, i.e., Voronoi vertices) | 
| 435 |  |  | sorted by center id | 
| 436 |  |  | */ | 
| 437 |  |  | setT *qh_detvridge (vertexT *vertex) { | 
| 438 |  |  | setT *centers= qh_settemp (qh TEMPsize); | 
| 439 |  |  | setT *tricenters= qh_settemp (qh TEMPsize); | 
| 440 |  |  | facetT *neighbor, **neighborp; | 
| 441 |  |  | boolT firstinf= True; | 
| 442 |  |  |  | 
| 443 |  |  | FOREACHneighbor_(vertex) { | 
| 444 |  |  | if (neighbor->seen) { | 
| 445 |  |  | if (neighbor->visitid) { | 
| 446 |  |  | if (!neighbor->tricoplanar || qh_setunique (&tricenters, neighbor->center)) | 
| 447 |  |  | qh_setappend (¢ers, neighbor); | 
| 448 |  |  | }else if (firstinf) { | 
| 449 |  |  | firstinf= False; | 
| 450 |  |  | qh_setappend (¢ers, neighbor); | 
| 451 |  |  | } | 
| 452 |  |  | } | 
| 453 |  |  | } | 
| 454 |  |  | qsort (SETaddr_(centers, facetT), qh_setsize (centers), | 
| 455 |  |  | sizeof (facetT *), qh_compare_facetvisit); | 
| 456 |  |  | qh_settempfree (&tricenters); | 
| 457 |  |  | return centers; | 
| 458 |  |  | } /* detvridge */ | 
| 459 |  |  |  | 
| 460 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 461 |  |  | >-------------------------------</a><a name="detvridge3">-</a> | 
| 462 |  |  |  | 
| 463 |  |  | qh_detvridge3( atvertex, vertex ) | 
| 464 |  |  | determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex | 
| 465 |  |  | incl. one vertex-at-infinite for !neighbor->visitid | 
| 466 |  |  | assumes all facet->seen2= True | 
| 467 |  |  |  | 
| 468 |  |  | returns: | 
| 469 |  |  | temporary set of centers (facets, i.e., Voronoi vertices) | 
| 470 |  |  | listed in adjacency order (not oriented) | 
| 471 |  |  | all facet->seen2= True | 
| 472 |  |  |  | 
| 473 |  |  | design: | 
| 474 |  |  | mark all neighbors of atvertex | 
| 475 |  |  | for each adjacent neighbor of both atvertex and vertex | 
| 476 |  |  | if neighbor selected | 
| 477 |  |  | add neighbor to set of Voronoi vertices | 
| 478 |  |  | */ | 
| 479 |  |  | setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) { | 
| 480 |  |  | setT *centers= qh_settemp (qh TEMPsize); | 
| 481 |  |  | setT *tricenters= qh_settemp (qh TEMPsize); | 
| 482 |  |  | facetT *neighbor, **neighborp, *facet= NULL; | 
| 483 |  |  | boolT firstinf= True; | 
| 484 |  |  |  | 
| 485 |  |  | FOREACHneighbor_(atvertex) | 
| 486 |  |  | neighbor->seen2= False; | 
| 487 |  |  | FOREACHneighbor_(vertex) { | 
| 488 |  |  | if (!neighbor->seen2) { | 
| 489 |  |  | facet= neighbor; | 
| 490 |  |  | break; | 
| 491 |  |  | } | 
| 492 |  |  | } | 
| 493 |  |  | while (facet) { | 
| 494 |  |  | facet->seen2= True; | 
| 495 |  |  | if (neighbor->seen) { | 
| 496 |  |  | if (facet->visitid) { | 
| 497 |  |  | if (!facet->tricoplanar || qh_setunique (&tricenters, facet->center)) | 
| 498 |  |  | qh_setappend (¢ers, facet); | 
| 499 |  |  | }else if (firstinf) { | 
| 500 |  |  | firstinf= False; | 
| 501 |  |  | qh_setappend (¢ers, facet); | 
| 502 |  |  | } | 
| 503 |  |  | } | 
| 504 |  |  | FOREACHneighbor_(facet) { | 
| 505 |  |  | if (!neighbor->seen2) { | 
| 506 |  |  | if (qh_setin (vertex->neighbors, neighbor)) | 
| 507 |  |  | break; | 
| 508 |  |  | else | 
| 509 |  |  | neighbor->seen2= True; | 
| 510 |  |  | } | 
| 511 |  |  | } | 
| 512 |  |  | facet= neighbor; | 
| 513 |  |  | } | 
| 514 |  |  | if (qh CHECKfrequently) { | 
| 515 |  |  | FOREACHneighbor_(vertex) { | 
| 516 |  |  | if (!neighbor->seen2) { | 
| 517 |  |  | fprintf (stderr, "qh_detvridge3: neigbors of vertex p%d are not connected at facet %d\n", | 
| 518 |  |  | qh_pointid (vertex->point), neighbor->id); | 
| 519 |  |  | qh_errexit (qh_ERRqhull, neighbor, NULL); | 
| 520 |  |  | } | 
| 521 |  |  | } | 
| 522 |  |  | } | 
| 523 |  |  | FOREACHneighbor_(atvertex) | 
| 524 |  |  | neighbor->seen2= True; | 
| 525 |  |  | qh_settempfree (&tricenters); | 
| 526 |  |  | return centers; | 
| 527 |  |  | } /* detvridge3 */ | 
| 528 |  |  |  | 
| 529 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 530 |  |  | >-------------------------------</a><a name="eachvoronoi">-</a> | 
| 531 |  |  |  | 
| 532 |  |  | qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder ) | 
| 533 |  |  | if visitall, | 
| 534 |  |  | visit all Voronoi ridges for vertex (i.e., an input site) | 
| 535 |  |  | else | 
| 536 |  |  | visit all unvisited Voronoi ridges for vertex | 
| 537 |  |  | all vertex->seen= False if unvisited | 
| 538 |  |  | assumes | 
| 539 |  |  | all facet->seen= False | 
| 540 |  |  | all facet->seen2= True (for qh_detvridge3) | 
| 541 |  |  | all facet->visitid == 0 if vertex_at_infinity | 
| 542 |  |  | == index of Voronoi vertex | 
| 543 |  |  | >= qh.num_facets if ignored | 
| 544 |  |  | innerouter: | 
| 545 |  |  | qh_RIDGEall--  both inner (bounded) and outer (unbounded) ridges | 
| 546 |  |  | qh_RIDGEinner- only inner | 
| 547 |  |  | qh_RIDGEouter- only outer | 
| 548 |  |  |  | 
| 549 |  |  | if inorder | 
| 550 |  |  | orders vertices for 3-d Voronoi diagrams | 
| 551 |  |  |  | 
| 552 |  |  | returns: | 
| 553 |  |  | number of visited ridges (does not include previously visited ridges) | 
| 554 |  |  |  | 
| 555 |  |  | if printvridge, | 
| 556 |  |  | calls printvridge( fp, vertex, vertexA, centers) | 
| 557 |  |  | fp== any pointer (assumes FILE*) | 
| 558 |  |  | vertex,vertexA= pair of input sites that define a Voronoi ridge | 
| 559 |  |  | centers= set of facets (i.e., Voronoi vertices) | 
| 560 |  |  | ->visitid == index or 0 if vertex_at_infinity | 
| 561 |  |  | ordered for 3-d Voronoi diagram | 
| 562 |  |  | notes: | 
| 563 |  |  | uses qh.vertex_visit | 
| 564 |  |  |  | 
| 565 |  |  | see: | 
| 566 |  |  | qh_eachvoronoi_all() | 
| 567 |  |  |  | 
| 568 |  |  | design: | 
| 569 |  |  | mark selected neighbors of atvertex | 
| 570 |  |  | for each selected neighbor (either Voronoi vertex or vertex-at-infinity) | 
| 571 |  |  | for each unvisited vertex | 
| 572 |  |  | if atvertex and vertex share more than d-1 neighbors | 
| 573 |  |  | bump totalcount | 
| 574 |  |  | if printvridge defined | 
| 575 |  |  | build the set of shared neighbors (i.e., Voronoi vertices) | 
| 576 |  |  | call printvridge | 
| 577 |  |  | */ | 
| 578 |  |  | int qh_eachvoronoi (FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) { | 
| 579 |  |  | boolT unbounded; | 
| 580 |  |  | int count; | 
| 581 |  |  | facetT *neighbor, **neighborp, *neighborA, **neighborAp; | 
| 582 |  |  | setT *centers; | 
| 583 |  |  | setT *tricenters= qh_settemp (qh TEMPsize); | 
| 584 |  |  |  | 
| 585 |  |  | vertexT *vertex, **vertexp; | 
| 586 |  |  | boolT firstinf; | 
| 587 |  |  | unsigned int numfacets= (unsigned int)qh num_facets; | 
| 588 |  |  | int totridges= 0; | 
| 589 |  |  |  | 
| 590 |  |  | qh vertex_visit++; | 
| 591 |  |  | atvertex->seen= True; | 
| 592 |  |  | if (visitall) { | 
| 593 |  |  | FORALLvertices | 
| 594 |  |  | vertex->seen= False; | 
| 595 |  |  | } | 
| 596 |  |  | FOREACHneighbor_(atvertex) { | 
| 597 |  |  | if (neighbor->visitid < numfacets) | 
| 598 |  |  | neighbor->seen= True; | 
| 599 |  |  | } | 
| 600 |  |  | FOREACHneighbor_(atvertex) { | 
| 601 |  |  | if (neighbor->seen) { | 
| 602 |  |  | FOREACHvertex_(neighbor->vertices) { | 
| 603 |  |  | if (vertex->visitid != qh vertex_visit && !vertex->seen) { | 
| 604 |  |  | vertex->visitid= qh vertex_visit; | 
| 605 |  |  | count= 0; | 
| 606 |  |  | firstinf= True; | 
| 607 |  |  | qh_settruncate (tricenters, 0); | 
| 608 |  |  | FOREACHneighborA_(vertex) { | 
| 609 |  |  | if (neighborA->seen) { | 
| 610 |  |  | if (neighborA->visitid) { | 
| 611 |  |  | if (!neighborA->tricoplanar || qh_setunique (&tricenters, neighborA->center)) | 
| 612 |  |  | count++; | 
| 613 |  |  | }else if (firstinf) { | 
| 614 |  |  | count++; | 
| 615 |  |  | firstinf= False; | 
| 616 |  |  | } | 
| 617 |  |  | } | 
| 618 |  |  | } | 
| 619 |  |  | if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */ | 
| 620 |  |  | if (firstinf) { | 
| 621 |  |  | if (innerouter == qh_RIDGEouter) | 
| 622 |  |  | continue; | 
| 623 |  |  | unbounded= False; | 
| 624 |  |  | }else { | 
| 625 |  |  | if (innerouter == qh_RIDGEinner) | 
| 626 |  |  | continue; | 
| 627 |  |  | unbounded= True; | 
| 628 |  |  | } | 
| 629 |  |  | totridges++; | 
| 630 |  |  | trace4((qh ferr, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n", count, qh_pointid (atvertex->point), qh_pointid (vertex->point))); | 
| 631 |  |  | if (printvridge) { | 
| 632 |  |  | if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */ | 
| 633 |  |  | centers= qh_detvridge3 (atvertex, vertex); | 
| 634 |  |  | else | 
| 635 |  |  | centers= qh_detvridge (vertex); | 
| 636 |  |  | (*printvridge) (fp, atvertex, vertex, centers, unbounded); | 
| 637 |  |  | qh_settempfree (¢ers); | 
| 638 |  |  | } | 
| 639 |  |  | } | 
| 640 |  |  | } | 
| 641 |  |  | } | 
| 642 |  |  | } | 
| 643 |  |  | } | 
| 644 |  |  | FOREACHneighbor_(atvertex) | 
| 645 |  |  | neighbor->seen= False; | 
| 646 |  |  | qh_settempfree (&tricenters); | 
| 647 |  |  | return totridges; | 
| 648 |  |  | } /* eachvoronoi */ | 
| 649 |  |  |  | 
| 650 |  |  |  | 
| 651 |  |  | /*-<a                             href="qh-poly.htm#TOC" | 
| 652 |  |  | >-------------------------------</a><a name="eachvoronoi_all">-</a> | 
| 653 |  |  |  | 
| 654 |  |  | qh_eachvoronoi_all( fp, printvridge, isupper, innerouter, inorder ) | 
| 655 |  |  | visit all Voronoi ridges | 
| 656 |  |  |  | 
| 657 |  |  | innerouter: | 
| 658 |  |  | see qh_eachvoronoi() | 
| 659 |  |  |  | 
| 660 |  |  | if inorder | 
| 661 |  |  | orders vertices for 3-d Voronoi diagrams | 
| 662 |  |  |  | 
| 663 |  |  | returns | 
| 664 |  |  | total number of ridges | 
| 665 |  |  |  | 
| 666 |  |  | if isupper == facet->upperdelaunay  (i.e., a Vornoi vertex) | 
| 667 |  |  | facet->visitid= Voronoi vertex index (same as 'o' format) | 
| 668 |  |  | else | 
| 669 |  |  | facet->visitid= 0 | 
| 670 |  |  |  | 
| 671 |  |  | if printvridge, | 
| 672 |  |  | calls printvridge( fp, vertex, vertexA, centers) | 
| 673 |  |  | [see qh_eachvoronoi] | 
| 674 |  |  |  | 
| 675 |  |  | notes: | 
| 676 |  |  | Not used for qhull.exe | 
| 677 |  |  | same effect as qh_printvdiagram but ridges not sorted by point id | 
| 678 |  |  | */ | 
| 679 |  |  | int qh_eachvoronoi_all (FILE *fp, printvridgeT printvridge, boolT isupper, qh_RIDGE innerouter, boolT inorder) { | 
| 680 |  |  | facetT *facet; | 
| 681 |  |  | vertexT *vertex; | 
| 682 |  |  | int numcenters= 1;  /* vertex 0 is vertex-at-infinity */ | 
| 683 |  |  | int totridges= 0; | 
| 684 |  |  |  | 
| 685 |  |  | qh_clearcenters (qh_ASvoronoi); | 
| 686 |  |  | qh_vertexneighbors(); | 
| 687 |  |  | maximize_(qh visit_id, (unsigned) qh num_facets); | 
| 688 |  |  | FORALLfacets { | 
| 689 |  |  | facet->visitid= 0; | 
| 690 |  |  | facet->seen= False; | 
| 691 |  |  | facet->seen2= True; | 
| 692 |  |  | } | 
| 693 |  |  | FORALLfacets { | 
| 694 |  |  | if (facet->upperdelaunay == isupper) | 
| 695 |  |  | facet->visitid= numcenters++; | 
| 696 |  |  | } | 
| 697 |  |  | FORALLvertices | 
| 698 |  |  | vertex->seen= False; | 
| 699 |  |  | FORALLvertices { | 
| 700 |  |  | if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex) | 
| 701 |  |  | continue; | 
| 702 |  |  | totridges += qh_eachvoronoi (fp, printvridge, vertex, | 
| 703 |  |  | !qh_ALL, innerouter, inorder); | 
| 704 |  |  | } | 
| 705 |  |  | return totridges; | 
| 706 |  |  | } /* eachvoronoi_all */ | 
| 707 |  |  |  | 
| 708 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 709 |  |  | >-------------------------------</a><a name="facet2point">-</a> | 
| 710 |  |  |  | 
| 711 |  |  | qh_facet2point( facet, point0, point1, mindist ) | 
| 712 |  |  | return two projected temporary vertices for a 2-d facet | 
| 713 |  |  | may be non-simplicial | 
| 714 |  |  |  | 
| 715 |  |  | returns: | 
| 716 |  |  | point0 and point1 oriented and projected to the facet | 
| 717 |  |  | returns mindist (maximum distance below plane) | 
| 718 |  |  | */ | 
| 719 |  |  | void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) { | 
| 720 |  |  | vertexT *vertex0, *vertex1; | 
| 721 |  |  | realT dist; | 
| 722 |  |  |  | 
| 723 |  |  | if (facet->toporient ^ qh_ORIENTclock) { | 
| 724 |  |  | vertex0= SETfirstt_(facet->vertices, vertexT); | 
| 725 |  |  | vertex1= SETsecondt_(facet->vertices, vertexT); | 
| 726 |  |  | }else { | 
| 727 |  |  | vertex1= SETfirstt_(facet->vertices, vertexT); | 
| 728 |  |  | vertex0= SETsecondt_(facet->vertices, vertexT); | 
| 729 |  |  | } | 
| 730 |  |  | zadd_(Zdistio, 2); | 
| 731 |  |  | qh_distplane(vertex0->point, facet, &dist); | 
| 732 |  |  | *mindist= dist; | 
| 733 |  |  | *point0= qh_projectpoint(vertex0->point, facet, dist); | 
| 734 |  |  | qh_distplane(vertex1->point, facet, &dist); | 
| 735 |  |  | minimize_(*mindist, dist); | 
| 736 |  |  | *point1= qh_projectpoint(vertex1->point, facet, dist); | 
| 737 |  |  | } /* facet2point */ | 
| 738 |  |  |  | 
| 739 |  |  |  | 
| 740 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 741 |  |  | >-------------------------------</a><a name="facetvertices">-</a> | 
| 742 |  |  |  | 
| 743 |  |  | qh_facetvertices( facetlist, facets, allfacets ) | 
| 744 |  |  | returns temporary set of vertices in a set and/or list of facets | 
| 745 |  |  | if allfacets, ignores qh_skipfacet() | 
| 746 |  |  |  | 
| 747 |  |  | returns: | 
| 748 |  |  | vertices with qh.vertex_visit | 
| 749 |  |  |  | 
| 750 |  |  | notes: | 
| 751 |  |  | optimized for allfacets of facet_list | 
| 752 |  |  |  | 
| 753 |  |  | design: | 
| 754 |  |  | if allfacets of facet_list | 
| 755 |  |  | create vertex set from vertex_list | 
| 756 |  |  | else | 
| 757 |  |  | for each selected facet in facets or facetlist | 
| 758 |  |  | append unvisited vertices to vertex set | 
| 759 |  |  | */ | 
| 760 |  |  | setT *qh_facetvertices (facetT *facetlist, setT *facets, boolT allfacets) { | 
| 761 |  |  | setT *vertices; | 
| 762 |  |  | facetT *facet, **facetp; | 
| 763 |  |  | vertexT *vertex, **vertexp; | 
| 764 |  |  |  | 
| 765 |  |  | qh vertex_visit++; | 
| 766 |  |  | if (facetlist == qh facet_list && allfacets && !facets) { | 
| 767 |  |  | vertices= qh_settemp (qh num_vertices); | 
| 768 |  |  | FORALLvertices { | 
| 769 |  |  | vertex->visitid= qh vertex_visit; | 
| 770 |  |  | qh_setappend (&vertices, vertex); | 
| 771 |  |  | } | 
| 772 |  |  | }else { | 
| 773 |  |  | vertices= qh_settemp (qh TEMPsize); | 
| 774 |  |  | FORALLfacet_(facetlist) { | 
| 775 |  |  | if (!allfacets && qh_skipfacet (facet)) | 
| 776 |  |  | continue; | 
| 777 |  |  | FOREACHvertex_(facet->vertices) { | 
| 778 |  |  | if (vertex->visitid != qh vertex_visit) { | 
| 779 |  |  | vertex->visitid= qh vertex_visit; | 
| 780 |  |  | qh_setappend (&vertices, vertex); | 
| 781 |  |  | } | 
| 782 |  |  | } | 
| 783 |  |  | } | 
| 784 |  |  | } | 
| 785 |  |  | FOREACHfacet_(facets) { | 
| 786 |  |  | if (!allfacets && qh_skipfacet (facet)) | 
| 787 |  |  | continue; | 
| 788 |  |  | FOREACHvertex_(facet->vertices) { | 
| 789 |  |  | if (vertex->visitid != qh vertex_visit) { | 
| 790 |  |  | vertex->visitid= qh vertex_visit; | 
| 791 |  |  | qh_setappend (&vertices, vertex); | 
| 792 |  |  | } | 
| 793 |  |  | } | 
| 794 |  |  | } | 
| 795 |  |  | return vertices; | 
| 796 |  |  | } /* facetvertices */ | 
| 797 |  |  |  | 
| 798 |  |  | /*-<a                             href="qh-geom.htm#TOC" | 
| 799 |  |  | >-------------------------------</a><a name="geomplanes">-</a> | 
| 800 |  |  |  | 
| 801 |  |  | qh_geomplanes( facet, outerplane, innerplane ) | 
| 802 |  |  | return outer and inner planes for Geomview | 
| 803 |  |  | qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax) | 
| 804 |  |  |  | 
| 805 |  |  | notes: | 
| 806 |  |  | assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon | 
| 807 |  |  | */ | 
| 808 |  |  | void qh_geomplanes (facetT *facet, realT *outerplane, realT *innerplane) { | 
| 809 |  |  | realT radius; | 
| 810 |  |  |  | 
| 811 |  |  | if (qh MERGING || qh JOGGLEmax < REALmax/2) { | 
| 812 |  |  | qh_outerinner (facet, outerplane, innerplane); | 
| 813 |  |  | radius= qh PRINTradius; | 
| 814 |  |  | if (qh JOGGLEmax < REALmax/2) | 
| 815 |  |  | radius -= qh JOGGLEmax * sqrt (qh hull_dim);  /* already accounted for in qh_outerinner() */ | 
| 816 |  |  | *outerplane += radius; | 
| 817 |  |  | *innerplane -= radius; | 
| 818 |  |  | if (qh PRINTcoplanar || qh PRINTspheres) { | 
| 819 |  |  | *outerplane += qh MAXabs_coord * qh_GEOMepsilon; | 
| 820 |  |  | *innerplane -= qh MAXabs_coord * qh_GEOMepsilon; | 
| 821 |  |  | } | 
| 822 |  |  | }else | 
| 823 |  |  | *innerplane= *outerplane= 0; | 
| 824 |  |  | } /* geomplanes */ | 
| 825 |  |  |  | 
| 826 |  |  |  | 
| 827 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 828 |  |  | >-------------------------------</a><a name="markkeep">-</a> | 
| 829 |  |  |  | 
| 830 |  |  | qh_markkeep( facetlist ) | 
| 831 |  |  | mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea | 
| 832 |  |  | ignores visible facets (not part of convex hull) | 
| 833 |  |  |  | 
| 834 |  |  | returns: | 
| 835 |  |  | may clear facet->good | 
| 836 |  |  | recomputes qh.num_good | 
| 837 |  |  |  | 
| 838 |  |  | design: | 
| 839 |  |  | get set of good facets | 
| 840 |  |  | if qh.KEEParea | 
| 841 |  |  | sort facets by area | 
| 842 |  |  | clear facet->good for all but n largest facets | 
| 843 |  |  | if qh.KEEPmerge | 
| 844 |  |  | sort facets by merge count | 
| 845 |  |  | clear facet->good for all but n most merged facets | 
| 846 |  |  | if qh.KEEPminarea | 
| 847 |  |  | clear facet->good if area too small | 
| 848 |  |  | update qh.num_good | 
| 849 |  |  | */ | 
| 850 |  |  | void qh_markkeep (facetT *facetlist) { | 
| 851 |  |  | facetT *facet, **facetp; | 
| 852 |  |  | setT *facets= qh_settemp (qh num_facets); | 
| 853 |  |  | int size, count; | 
| 854 |  |  |  | 
| 855 |  |  | trace2((qh ferr, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n", qh KEEParea, qh KEEPmerge, qh KEEPminArea)); | 
| 856 |  |  | FORALLfacet_(facetlist) { | 
| 857 |  |  | if (!facet->visible && facet->good) | 
| 858 |  |  | qh_setappend (&facets, facet); | 
| 859 |  |  | } | 
| 860 |  |  | size= qh_setsize (facets); | 
| 861 |  |  | if (qh KEEParea) { | 
| 862 |  |  | qsort (SETaddr_(facets, facetT), size, | 
| 863 |  |  | sizeof (facetT *), qh_compare_facetarea); | 
| 864 |  |  | if ((count= size - qh KEEParea) > 0) { | 
| 865 |  |  | FOREACHfacet_(facets) { | 
| 866 |  |  | facet->good= False; | 
| 867 |  |  | if (--count == 0) | 
| 868 |  |  | break; | 
| 869 |  |  | } | 
| 870 |  |  | } | 
| 871 |  |  | } | 
| 872 |  |  | if (qh KEEPmerge) { | 
| 873 |  |  | qsort (SETaddr_(facets, facetT), size, | 
| 874 |  |  | sizeof (facetT *), qh_compare_facetmerge); | 
| 875 |  |  | if ((count= size - qh KEEPmerge) > 0) { | 
| 876 |  |  | FOREACHfacet_(facets) { | 
| 877 |  |  | facet->good= False; | 
| 878 |  |  | if (--count == 0) | 
| 879 |  |  | break; | 
| 880 |  |  | } | 
| 881 |  |  | } | 
| 882 |  |  | } | 
| 883 |  |  | if (qh KEEPminArea < REALmax/2) { | 
| 884 |  |  | FOREACHfacet_(facets) { | 
| 885 |  |  | if (!facet->isarea || facet->f.area < qh KEEPminArea) | 
| 886 |  |  | facet->good= False; | 
| 887 |  |  | } | 
| 888 |  |  | } | 
| 889 |  |  | qh_settempfree (&facets); | 
| 890 |  |  | count= 0; | 
| 891 |  |  | FORALLfacet_(facetlist) { | 
| 892 |  |  | if (facet->good) | 
| 893 |  |  | count++; | 
| 894 |  |  | } | 
| 895 |  |  | qh num_good= count; | 
| 896 |  |  | } /* markkeep */ | 
| 897 |  |  |  | 
| 898 |  |  |  | 
| 899 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 900 |  |  | >-------------------------------</a><a name="markvoronoi">-</a> | 
| 901 |  |  |  | 
| 902 |  |  | qh_markvoronoi( facetlist, facets, printall, islower, numcenters ) | 
| 903 |  |  | mark voronoi vertices for printing by site pairs | 
| 904 |  |  |  | 
| 905 |  |  | returns: | 
| 906 |  |  | temporary set of vertices indexed by pointid | 
| 907 |  |  | islower set if printing lower hull (i.e., at least one facet is lower hull) | 
| 908 |  |  | numcenters= total number of Voronoi vertices | 
| 909 |  |  | bumps qh.printoutnum for vertex-at-infinity | 
| 910 |  |  | clears all facet->seen and sets facet->seen2 | 
| 911 |  |  |  | 
| 912 |  |  | if selected | 
| 913 |  |  | facet->visitid= Voronoi vertex id | 
| 914 |  |  | else if upper hull (or 'Qu' and lower hull) | 
| 915 |  |  | facet->visitid= 0 | 
| 916 |  |  | else | 
| 917 |  |  | facet->visitid >= qh num_facets | 
| 918 |  |  |  | 
| 919 |  |  | notes: | 
| 920 |  |  | ignores qh.ATinfinity, if defined | 
| 921 |  |  | */ | 
| 922 |  |  | setT *qh_markvoronoi (facetT *facetlist, setT *facets, boolT printall, boolT *islowerp, int *numcentersp) { | 
| 923 |  |  | int numcenters=0; | 
| 924 |  |  | facetT *facet, **facetp; | 
| 925 |  |  | setT *vertices; | 
| 926 |  |  | boolT islower= False; | 
| 927 |  |  |  | 
| 928 |  |  | qh printoutnum++; | 
| 929 |  |  | qh_clearcenters (qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */ | 
| 930 |  |  | qh_vertexneighbors(); | 
| 931 |  |  | vertices= qh_pointvertex(); | 
| 932 |  |  | if (qh ATinfinity) | 
| 933 |  |  | SETelem_(vertices, qh num_points-1)= NULL; | 
| 934 |  |  | qh visit_id++; | 
| 935 |  |  | maximize_(qh visit_id, (unsigned) qh num_facets); | 
| 936 |  |  | FORALLfacet_(facetlist) { | 
| 937 |  |  | if (printall || !qh_skipfacet (facet)) { | 
| 938 |  |  | if (!facet->upperdelaunay) { | 
| 939 |  |  | islower= True; | 
| 940 |  |  | break; | 
| 941 |  |  | } | 
| 942 |  |  | } | 
| 943 |  |  | } | 
| 944 |  |  | FOREACHfacet_(facets) { | 
| 945 |  |  | if (printall || !qh_skipfacet (facet)) { | 
| 946 |  |  | if (!facet->upperdelaunay) { | 
| 947 |  |  | islower= True; | 
| 948 |  |  | break; | 
| 949 |  |  | } | 
| 950 |  |  | } | 
| 951 |  |  | } | 
| 952 |  |  | FORALLfacets { | 
| 953 |  |  | if (facet->normal && (facet->upperdelaunay == islower)) | 
| 954 |  |  | facet->visitid= 0;  /* facetlist or facets may overwrite */ | 
| 955 |  |  | else | 
| 956 |  |  | facet->visitid= qh visit_id; | 
| 957 |  |  | facet->seen= False; | 
| 958 |  |  | facet->seen2= True; | 
| 959 |  |  | } | 
| 960 |  |  | numcenters++;  /* qh_INFINITE */ | 
| 961 |  |  | FORALLfacet_(facetlist) { | 
| 962 |  |  | if (printall || !qh_skipfacet (facet)) | 
| 963 |  |  | facet->visitid= numcenters++; | 
| 964 |  |  | } | 
| 965 |  |  | FOREACHfacet_(facets) { | 
| 966 |  |  | if (printall || !qh_skipfacet (facet)) | 
| 967 |  |  | facet->visitid= numcenters++; | 
| 968 |  |  | } | 
| 969 |  |  | *islowerp= islower; | 
| 970 |  |  | *numcentersp= numcenters; | 
| 971 |  |  | trace2((qh ferr, "qh_markvoronoi: islower %d numcenters %d\n", islower, numcenters)); | 
| 972 |  |  | return vertices; | 
| 973 |  |  | } /* markvoronoi */ | 
| 974 |  |  |  | 
| 975 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 976 |  |  | >-------------------------------</a><a name="order_vertexneighbors">-</a> | 
| 977 |  |  |  | 
| 978 |  |  | qh_order_vertexneighbors( vertex ) | 
| 979 |  |  | order facet neighbors of a 2-d or 3-d vertex by adjacency | 
| 980 |  |  |  | 
| 981 |  |  | notes: | 
| 982 |  |  | does not orient the neighbors | 
| 983 |  |  |  | 
| 984 |  |  | design: | 
| 985 |  |  | initialize a new neighbor set with the first facet in vertex->neighbors | 
| 986 |  |  | while vertex->neighbors non-empty | 
| 987 |  |  | select next neighbor in the previous facet's neighbor set | 
| 988 |  |  | set vertex->neighbors to the new neighbor set | 
| 989 |  |  | */ | 
| 990 |  |  | void qh_order_vertexneighbors(vertexT *vertex) { | 
| 991 |  |  | setT *newset; | 
| 992 |  |  | facetT *facet, *neighbor, **neighborp; | 
| 993 |  |  |  | 
| 994 |  |  | trace4((qh ferr, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id)); | 
| 995 |  |  | newset= qh_settemp (qh_setsize (vertex->neighbors)); | 
| 996 |  |  | facet= (facetT*)qh_setdellast (vertex->neighbors); | 
| 997 |  |  | qh_setappend (&newset, facet); | 
| 998 |  |  | while (qh_setsize (vertex->neighbors)) { | 
| 999 |  |  | FOREACHneighbor_(vertex) { | 
| 1000 |  |  | if (qh_setin (facet->neighbors, neighbor)) { | 
| 1001 |  |  | qh_setdel(vertex->neighbors, neighbor); | 
| 1002 |  |  | qh_setappend (&newset, neighbor); | 
| 1003 |  |  | facet= neighbor; | 
| 1004 |  |  | break; | 
| 1005 |  |  | } | 
| 1006 |  |  | } | 
| 1007 |  |  | if (!neighbor) { | 
| 1008 |  |  | fprintf (qh ferr, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n", | 
| 1009 |  |  | vertex->id, facet->id); | 
| 1010 |  |  | qh_errexit (qh_ERRqhull, facet, NULL); | 
| 1011 |  |  | } | 
| 1012 |  |  | } | 
| 1013 |  |  | qh_setfree (&vertex->neighbors); | 
| 1014 |  |  | qh_settemppop (); | 
| 1015 |  |  | vertex->neighbors= newset; | 
| 1016 |  |  | } /* order_vertexneighbors */ | 
| 1017 |  |  |  | 
| 1018 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1019 |  |  | >-------------------------------</a><a name="printafacet">-</a> | 
| 1020 |  |  |  | 
| 1021 |  |  | qh_printafacet( fp, format, facet, printall ) | 
| 1022 |  |  | print facet to fp in given output format (see qh.PRINTout) | 
| 1023 |  |  |  | 
| 1024 |  |  | returns: | 
| 1025 |  |  | nop if !printall and qh_skipfacet() | 
| 1026 |  |  | nop if visible facet and NEWfacets and format != PRINTfacets | 
| 1027 |  |  | must match qh_countfacets | 
| 1028 |  |  |  | 
| 1029 |  |  | notes | 
| 1030 |  |  | preserves qh.visit_id | 
| 1031 |  |  | facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge | 
| 1032 |  |  |  | 
| 1033 |  |  | see | 
| 1034 |  |  | qh_printbegin() and qh_printend() | 
| 1035 |  |  |  | 
| 1036 |  |  | design: | 
| 1037 |  |  | test for printing facet | 
| 1038 |  |  | call appropriate routine for format | 
| 1039 |  |  | or output results directly | 
| 1040 |  |  | */ | 
| 1041 |  |  | void qh_printafacet(FILE *fp, int format, facetT *facet, boolT printall) { | 
| 1042 |  |  | realT color[4], offset, dist, outerplane, innerplane; | 
| 1043 |  |  | boolT zerodiv; | 
| 1044 |  |  | coordT *point, *normp, *coordp, **pointp, *feasiblep; | 
| 1045 |  |  | int k; | 
| 1046 |  |  | vertexT *vertex, **vertexp; | 
| 1047 |  |  | facetT *neighbor, **neighborp; | 
| 1048 |  |  |  | 
| 1049 |  |  | if (!printall && qh_skipfacet (facet)) | 
| 1050 |  |  | return; | 
| 1051 |  |  | if (facet->visible && qh NEWfacets && format != qh_PRINTfacets) | 
| 1052 |  |  | return; | 
| 1053 |  |  | qh printoutnum++; | 
| 1054 |  |  | switch (format) { | 
| 1055 |  |  | case qh_PRINTarea: | 
| 1056 |  |  | if (facet->isarea) { | 
| 1057 |  |  | fprintf (fp, qh_REAL_1, facet->f.area); | 
| 1058 |  |  | fprintf (fp, "\n"); | 
| 1059 |  |  | }else | 
| 1060 |  |  | fprintf (fp, "0\n"); | 
| 1061 |  |  | break; | 
| 1062 |  |  | case qh_PRINTcoplanars: | 
| 1063 |  |  | fprintf (fp, "%d", qh_setsize (facet->coplanarset)); | 
| 1064 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 1065 |  |  | fprintf (fp, " %d", qh_pointid (point)); | 
| 1066 |  |  | fprintf (fp, "\n"); | 
| 1067 |  |  | break; | 
| 1068 |  |  | case qh_PRINTcentrums: | 
| 1069 |  |  | qh_printcenter (fp, format, NULL, facet); | 
| 1070 |  |  | break; | 
| 1071 |  |  | case qh_PRINTfacets: | 
| 1072 |  |  | qh_printfacet (fp, facet); | 
| 1073 |  |  | break; | 
| 1074 |  |  | case qh_PRINTfacets_xridge: | 
| 1075 |  |  | qh_printfacetheader (fp, facet); | 
| 1076 |  |  | break; | 
| 1077 |  |  | case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */ | 
| 1078 |  |  | if (!facet->normal) | 
| 1079 |  |  | break; | 
| 1080 |  |  | for (k= qh hull_dim; k--; ) { | 
| 1081 |  |  | color[k]= (facet->normal[k]+1.0)/2.0; | 
| 1082 |  |  | maximize_(color[k], -1.0); | 
| 1083 |  |  | minimize_(color[k], +1.0); | 
| 1084 |  |  | } | 
| 1085 |  |  | qh_projectdim3 (color, color); | 
| 1086 |  |  | if (qh PRINTdim != qh hull_dim) | 
| 1087 |  |  | qh_normalize2 (color, 3, True, NULL, NULL); | 
| 1088 |  |  | if (qh hull_dim <= 2) | 
| 1089 |  |  | qh_printfacet2geom (fp, facet, color); | 
| 1090 |  |  | else if (qh hull_dim == 3) { | 
| 1091 |  |  | if (facet->simplicial) | 
| 1092 |  |  | qh_printfacet3geom_simplicial (fp, facet, color); | 
| 1093 |  |  | else | 
| 1094 |  |  | qh_printfacet3geom_nonsimplicial (fp, facet, color); | 
| 1095 |  |  | }else { | 
| 1096 |  |  | if (facet->simplicial) | 
| 1097 |  |  | qh_printfacet4geom_simplicial (fp, facet, color); | 
| 1098 |  |  | else | 
| 1099 |  |  | qh_printfacet4geom_nonsimplicial (fp, facet, color); | 
| 1100 |  |  | } | 
| 1101 |  |  | break; | 
| 1102 |  |  | case qh_PRINTids: | 
| 1103 |  |  | fprintf (fp, "%d\n", facet->id); | 
| 1104 |  |  | break; | 
| 1105 |  |  | case qh_PRINTincidences: | 
| 1106 |  |  | case qh_PRINToff: | 
| 1107 |  |  | case qh_PRINTtriangles: | 
| 1108 |  |  | if (qh hull_dim == 3 && format != qh_PRINTtriangles) | 
| 1109 |  |  | qh_printfacet3vertex (fp, facet, format); | 
| 1110 |  |  | else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff) | 
| 1111 |  |  | qh_printfacetNvertex_simplicial (fp, facet, format); | 
| 1112 |  |  | else | 
| 1113 |  |  | qh_printfacetNvertex_nonsimplicial (fp, facet, qh printoutvar++, format); | 
| 1114 |  |  | break; | 
| 1115 |  |  | case qh_PRINTinner: | 
| 1116 |  |  | qh_outerinner (facet, NULL, &innerplane); | 
| 1117 |  |  | offset= facet->offset - innerplane; | 
| 1118 |  |  | goto LABELprintnorm; | 
| 1119 |  |  | break; /* prevent warning */ | 
| 1120 |  |  | case qh_PRINTmerges: | 
| 1121 |  |  | fprintf (fp, "%d\n", facet->nummerge); | 
| 1122 |  |  | break; | 
| 1123 |  |  | case qh_PRINTnormals: | 
| 1124 |  |  | offset= facet->offset; | 
| 1125 |  |  | goto LABELprintnorm; | 
| 1126 |  |  | break; /* prevent warning */ | 
| 1127 |  |  | case qh_PRINTouter: | 
| 1128 |  |  | qh_outerinner (facet, &outerplane, NULL); | 
| 1129 |  |  | offset= facet->offset - outerplane; | 
| 1130 |  |  | LABELprintnorm: | 
| 1131 |  |  | if (!facet->normal) { | 
| 1132 |  |  | fprintf (fp, "no normal for facet f%d\n", facet->id); | 
| 1133 |  |  | break; | 
| 1134 |  |  | } | 
| 1135 |  |  | if (qh CDDoutput) { | 
| 1136 |  |  | fprintf (fp, qh_REAL_1, -offset); | 
| 1137 |  |  | for (k=0; k < qh hull_dim; k++) | 
| 1138 |  |  | fprintf (fp, qh_REAL_1, -facet->normal[k]); | 
| 1139 |  |  | }else { | 
| 1140 |  |  | for (k=0; k < qh hull_dim; k++) | 
| 1141 |  |  | fprintf (fp, qh_REAL_1, facet->normal[k]); | 
| 1142 |  |  | fprintf (fp, qh_REAL_1, offset); | 
| 1143 |  |  | } | 
| 1144 |  |  | fprintf (fp, "\n"); | 
| 1145 |  |  | break; | 
| 1146 |  |  | case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */ | 
| 1147 |  |  | case qh_PRINTmaple: | 
| 1148 |  |  | if (qh hull_dim == 2) | 
| 1149 |  |  | qh_printfacet2math (fp, facet, format, qh printoutvar++); | 
| 1150 |  |  | else | 
| 1151 |  |  | qh_printfacet3math (fp, facet, format, qh printoutvar++); | 
| 1152 |  |  | break; | 
| 1153 |  |  | case qh_PRINTneighbors: | 
| 1154 |  |  | fprintf (fp, "%d", qh_setsize (facet->neighbors)); | 
| 1155 |  |  | FOREACHneighbor_(facet) | 
| 1156 |  |  | fprintf (fp, " %d", | 
| 1157 |  |  | neighbor->visitid ? neighbor->visitid - 1: - neighbor->id); | 
| 1158 |  |  | fprintf (fp, "\n"); | 
| 1159 |  |  | break; | 
| 1160 |  |  | case qh_PRINTpointintersect: | 
| 1161 |  |  | if (!qh feasible_point) { | 
| 1162 |  |  | fprintf (fp, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n"); | 
| 1163 |  |  | qh_errexit( qh_ERRinput, NULL, NULL); | 
| 1164 |  |  | } | 
| 1165 |  |  | if (facet->offset > 0) | 
| 1166 |  |  | goto LABELprintinfinite; | 
| 1167 |  |  | point= coordp= (coordT*)qh_memalloc (qh normal_size); | 
| 1168 |  |  | normp= facet->normal; | 
| 1169 |  |  | feasiblep= qh feasible_point; | 
| 1170 |  |  | if (facet->offset < -qh MINdenom) { | 
| 1171 |  |  | for (k= qh hull_dim; k--; ) | 
| 1172 |  |  | *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++); | 
| 1173 |  |  | }else { | 
| 1174 |  |  | for (k= qh hull_dim; k--; ) { | 
| 1175 |  |  | *(coordp++)= qh_divzero (*(normp++), facet->offset, qh MINdenom_1, | 
| 1176 |  |  | &zerodiv) + *(feasiblep++); | 
| 1177 |  |  | if (zerodiv) { | 
| 1178 |  |  | qh_memfree (point, qh normal_size); | 
| 1179 |  |  | goto LABELprintinfinite; | 
| 1180 |  |  | } | 
| 1181 |  |  | } | 
| 1182 |  |  | } | 
| 1183 |  |  | qh_printpoint (fp, NULL, point); | 
| 1184 |  |  | qh_memfree (point, qh normal_size); | 
| 1185 |  |  | break; | 
| 1186 |  |  | LABELprintinfinite: | 
| 1187 |  |  | for (k= qh hull_dim; k--; ) | 
| 1188 |  |  | fprintf (fp, qh_REAL_1, qh_INFINITE); | 
| 1189 |  |  | fprintf (fp, "\n"); | 
| 1190 |  |  | break; | 
| 1191 |  |  | case qh_PRINTpointnearest: | 
| 1192 |  |  | FOREACHpoint_(facet->coplanarset) { | 
| 1193 |  |  | int id, id2; | 
| 1194 |  |  | vertex= qh_nearvertex (facet, point, &dist); | 
| 1195 |  |  | id= qh_pointid (vertex->point); | 
| 1196 |  |  | id2= qh_pointid (point); | 
| 1197 |  |  | fprintf (fp, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist); | 
| 1198 |  |  | } | 
| 1199 |  |  | break; | 
| 1200 |  |  | case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */ | 
| 1201 |  |  | if (qh CDDoutput) | 
| 1202 |  |  | fprintf (fp, "1 "); | 
| 1203 |  |  | qh_printcenter (fp, format, NULL, facet); | 
| 1204 |  |  | break; | 
| 1205 |  |  | case qh_PRINTvertices: | 
| 1206 |  |  | fprintf (fp, "%d", qh_setsize (facet->vertices)); | 
| 1207 |  |  | FOREACHvertex_(facet->vertices) | 
| 1208 |  |  | fprintf (fp, " %d", qh_pointid (vertex->point)); | 
| 1209 |  |  | fprintf (fp, "\n"); | 
| 1210 |  |  | break; | 
| 1211 |  |  | } | 
| 1212 |  |  | } /* printafacet */ | 
| 1213 |  |  |  | 
| 1214 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1215 |  |  | >-------------------------------</a><a name="printbegin">-</a> | 
| 1216 |  |  |  | 
| 1217 |  |  | qh_printbegin(  ) | 
| 1218 |  |  | prints header for all output formats | 
| 1219 |  |  |  | 
| 1220 |  |  | returns: | 
| 1221 |  |  | checks for valid format | 
| 1222 |  |  |  | 
| 1223 |  |  | notes: | 
| 1224 |  |  | uses qh.visit_id for 3/4off | 
| 1225 |  |  | changes qh.interior_point if printing centrums | 
| 1226 |  |  | qh_countfacets clears facet->visitid for non-good facets | 
| 1227 |  |  |  | 
| 1228 |  |  | see | 
| 1229 |  |  | qh_printend() and qh_printafacet() | 
| 1230 |  |  |  | 
| 1231 |  |  | design: | 
| 1232 |  |  | count facets and related statistics | 
| 1233 |  |  | print header for format | 
| 1234 |  |  | */ | 
| 1235 |  |  | void qh_printbegin (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) { | 
| 1236 |  |  | int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars; | 
| 1237 |  |  | int i, num; | 
| 1238 |  |  | facetT *facet, **facetp; | 
| 1239 |  |  | vertexT *vertex, **vertexp; | 
| 1240 |  |  | setT *vertices; | 
| 1241 |  |  | pointT *point, **pointp, *pointtemp; | 
| 1242 |  |  |  | 
| 1243 |  |  | qh printoutnum= 0; | 
| 1244 |  |  | qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, | 
| 1245 |  |  | &totneighbors, &numridges, &numcoplanars, &numtricoplanars); | 
| 1246 |  |  | switch (format) { | 
| 1247 |  |  | case qh_PRINTnone: | 
| 1248 |  |  | break; | 
| 1249 |  |  | case qh_PRINTarea: | 
| 1250 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1251 |  |  | break; | 
| 1252 |  |  | case qh_PRINTcoplanars: | 
| 1253 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1254 |  |  | break; | 
| 1255 |  |  | case qh_PRINTcentrums: | 
| 1256 |  |  | if (qh CENTERtype == qh_ASnone) | 
| 1257 |  |  | qh_clearcenters (qh_AScentrum); | 
| 1258 |  |  | fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets); | 
| 1259 |  |  | break; | 
| 1260 |  |  | case qh_PRINTfacets: | 
| 1261 |  |  | case qh_PRINTfacets_xridge: | 
| 1262 |  |  | if (facetlist) | 
| 1263 |  |  | qh_printvertexlist (fp, "Vertices and facets:\n", facetlist, facets, printall); | 
| 1264 |  |  | break; | 
| 1265 |  |  | case qh_PRINTgeom: | 
| 1266 |  |  | if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */ | 
| 1267 |  |  | goto LABELnoformat; | 
| 1268 |  |  | if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */ | 
| 1269 |  |  | goto LABELnoformat; | 
| 1270 |  |  | if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections)) | 
| 1271 |  |  | fprintf (qh ferr, "qhull warning: output for ridges and intersections not implemented in 2-d\n"); | 
| 1272 |  |  | if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter || | 
| 1273 |  |  | (qh PRINTdim == 4 && qh PRINTcentrums))) | 
| 1274 |  |  | fprintf (qh ferr, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n"); | 
| 1275 |  |  | if (qh PRINTdim == 4 && (qh PRINTspheres)) | 
| 1276 |  |  | fprintf (qh ferr, "qhull warning: output for vertices not implemented in 4-d\n"); | 
| 1277 |  |  | if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes) | 
| 1278 |  |  | fprintf (qh ferr, "qhull warning: 'Gnh' generates no output in 4-d\n"); | 
| 1279 |  |  | if (qh PRINTdim == 2) { | 
| 1280 |  |  | fprintf(fp, "{appearance {linewidth 3} LIST # %s | %s\n", | 
| 1281 |  |  | qh rbox_command, qh qhull_command); | 
| 1282 |  |  | }else if (qh PRINTdim == 3) { | 
| 1283 |  |  | fprintf(fp, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n", | 
| 1284 |  |  | qh rbox_command, qh qhull_command); | 
| 1285 |  |  | }else if (qh PRINTdim == 4) { | 
| 1286 |  |  | qh visit_id++; | 
| 1287 |  |  | num= 0; | 
| 1288 |  |  | FORALLfacet_(facetlist)    /* get number of ridges to be printed */ | 
| 1289 |  |  | qh_printend4geom (NULL, facet, &num, printall); | 
| 1290 |  |  | FOREACHfacet_(facets) | 
| 1291 |  |  | qh_printend4geom (NULL, facet, &num, printall); | 
| 1292 |  |  | qh ridgeoutnum= num; | 
| 1293 |  |  | qh printoutvar= 0;  /* counts number of ridges in output */ | 
| 1294 |  |  | fprintf (fp, "LIST # %s | %s\n", qh rbox_command, qh qhull_command); | 
| 1295 |  |  | } | 
| 1296 |  |  | if (qh PRINTdots) { | 
| 1297 |  |  | qh printoutnum++; | 
| 1298 |  |  | num= qh num_points + qh_setsize (qh other_points); | 
| 1299 |  |  | if (qh DELAUNAY && qh ATinfinity) | 
| 1300 |  |  | num--; | 
| 1301 |  |  | if (qh PRINTdim == 4) | 
| 1302 |  |  | fprintf (fp, "4VECT %d %d 1\n", num, num); | 
| 1303 |  |  | else | 
| 1304 |  |  | fprintf (fp, "VECT %d %d 1\n", num, num); | 
| 1305 |  |  | for (i= num; i--; ) { | 
| 1306 |  |  | if (i % 20 == 0) | 
| 1307 |  |  | fprintf (fp, "\n"); | 
| 1308 |  |  | fprintf (fp, "1 "); | 
| 1309 |  |  | } | 
| 1310 |  |  | fprintf (fp, "# 1 point per line\n1 "); | 
| 1311 |  |  | for (i= num-1; i--; ) { | 
| 1312 |  |  | if (i % 20 == 0) | 
| 1313 |  |  | fprintf (fp, "\n"); | 
| 1314 |  |  | fprintf (fp, "0 "); | 
| 1315 |  |  | } | 
| 1316 |  |  | fprintf (fp, "# 1 color for all\n"); | 
| 1317 |  |  | FORALLpoints { | 
| 1318 |  |  | if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) { | 
| 1319 |  |  | if (qh PRINTdim == 4) | 
| 1320 |  |  | qh_printpoint (fp, NULL, point); | 
| 1321 |  |  | else | 
| 1322 |  |  | qh_printpoint3 (fp, point); | 
| 1323 |  |  | } | 
| 1324 |  |  | } | 
| 1325 |  |  | FOREACHpoint_(qh other_points) { | 
| 1326 |  |  | if (qh PRINTdim == 4) | 
| 1327 |  |  | qh_printpoint (fp, NULL, point); | 
| 1328 |  |  | else | 
| 1329 |  |  | qh_printpoint3 (fp, point); | 
| 1330 |  |  | } | 
| 1331 |  |  | fprintf (fp, "0 1 1 1  # color of points\n"); | 
| 1332 |  |  | } | 
| 1333 |  |  | if (qh PRINTdim == 4  && !qh PRINTnoplanes) | 
| 1334 |  |  | /* 4dview loads up multiple 4OFF objects slowly */ | 
| 1335 |  |  | fprintf(fp, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum); | 
| 1336 |  |  | qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */ | 
| 1337 |  |  | if (qh PREmerge) { | 
| 1338 |  |  | maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround); | 
| 1339 |  |  | }else if (qh POSTmerge) | 
| 1340 |  |  | maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround); | 
| 1341 |  |  | qh PRINTradius= qh PRINTcradius; | 
| 1342 |  |  | if (qh PRINTspheres + qh PRINTcoplanar) | 
| 1343 |  |  | maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius); | 
| 1344 |  |  | if (qh premerge_cos < REALmax/2) { | 
| 1345 |  |  | maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord); | 
| 1346 |  |  | }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) { | 
| 1347 |  |  | maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord); | 
| 1348 |  |  | } | 
| 1349 |  |  | maximize_(qh PRINTradius, qh MINvisible); | 
| 1350 |  |  | if (qh JOGGLEmax < REALmax/2) | 
| 1351 |  |  | qh PRINTradius += qh JOGGLEmax * sqrt (qh hull_dim); | 
| 1352 |  |  | if (qh PRINTdim != 4 && | 
| 1353 |  |  | (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) { | 
| 1354 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 1355 |  |  | if (qh PRINTspheres && qh PRINTdim <= 3) | 
| 1356 |  |  | qh_printspheres (fp, vertices, qh PRINTradius); | 
| 1357 |  |  | if (qh PRINTcoplanar || qh PRINTcentrums) { | 
| 1358 |  |  | qh firstcentrum= True; | 
| 1359 |  |  | if (qh PRINTcoplanar&& !qh PRINTspheres) { | 
| 1360 |  |  | FOREACHvertex_(vertices) | 
| 1361 |  |  | qh_printpointvect2 (fp, vertex->point, NULL, | 
| 1362 |  |  | qh interior_point, qh PRINTradius); | 
| 1363 |  |  | } | 
| 1364 |  |  | FORALLfacet_(facetlist) { | 
| 1365 |  |  | if (!printall && qh_skipfacet(facet)) | 
| 1366 |  |  | continue; | 
| 1367 |  |  | if (!facet->normal) | 
| 1368 |  |  | continue; | 
| 1369 |  |  | if (qh PRINTcentrums && qh PRINTdim <= 3) | 
| 1370 |  |  | qh_printcentrum (fp, facet, qh PRINTcradius); | 
| 1371 |  |  | if (!qh PRINTcoplanar) | 
| 1372 |  |  | continue; | 
| 1373 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 1374 |  |  | qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); | 
| 1375 |  |  | FOREACHpoint_(facet->outsideset) | 
| 1376 |  |  | qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); | 
| 1377 |  |  | } | 
| 1378 |  |  | FOREACHfacet_(facets) { | 
| 1379 |  |  | if (!printall && qh_skipfacet(facet)) | 
| 1380 |  |  | continue; | 
| 1381 |  |  | if (!facet->normal) | 
| 1382 |  |  | continue; | 
| 1383 |  |  | if (qh PRINTcentrums && qh PRINTdim <= 3) | 
| 1384 |  |  | qh_printcentrum (fp, facet, qh PRINTcradius); | 
| 1385 |  |  | if (!qh PRINTcoplanar) | 
| 1386 |  |  | continue; | 
| 1387 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 1388 |  |  | qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); | 
| 1389 |  |  | FOREACHpoint_(facet->outsideset) | 
| 1390 |  |  | qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius); | 
| 1391 |  |  | } | 
| 1392 |  |  | } | 
| 1393 |  |  | qh_settempfree (&vertices); | 
| 1394 |  |  | } | 
| 1395 |  |  | qh visit_id++; /* for printing hyperplane intersections */ | 
| 1396 |  |  | break; | 
| 1397 |  |  | case qh_PRINTids: | 
| 1398 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1399 |  |  | break; | 
| 1400 |  |  | case qh_PRINTincidences: | 
| 1401 |  |  | if (qh VORONOI && qh PRINTprecision) | 
| 1402 |  |  | fprintf (qh ferr, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n"); | 
| 1403 |  |  | qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */ | 
| 1404 |  |  | if (qh hull_dim <= 3) | 
| 1405 |  |  | fprintf(fp, "%d\n", numfacets); | 
| 1406 |  |  | else | 
| 1407 |  |  | fprintf(fp, "%d\n", numsimplicial+numridges); | 
| 1408 |  |  | break; | 
| 1409 |  |  | case qh_PRINTinner: | 
| 1410 |  |  | case qh_PRINTnormals: | 
| 1411 |  |  | case qh_PRINTouter: | 
| 1412 |  |  | if (qh CDDoutput) | 
| 1413 |  |  | fprintf (fp, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command, | 
| 1414 |  |  | qh qhull_command, numfacets, qh hull_dim+1); | 
| 1415 |  |  | else | 
| 1416 |  |  | fprintf (fp, "%d\n%d\n", qh hull_dim+1, numfacets); | 
| 1417 |  |  | break; | 
| 1418 |  |  | case qh_PRINTmathematica: | 
| 1419 |  |  | case qh_PRINTmaple: | 
| 1420 |  |  | if (qh hull_dim > 3)  /* qh_initbuffers also checks */ | 
| 1421 |  |  | goto LABELnoformat; | 
| 1422 |  |  | if (qh VORONOI) | 
| 1423 |  |  | fprintf (qh ferr, "qhull warning: output is the Delaunay triangulation\n"); | 
| 1424 |  |  | if (format == qh_PRINTmaple) { | 
| 1425 |  |  | if (qh hull_dim == 2) | 
| 1426 |  |  | fprintf(fp, "PLOT(CURVES(\n"); | 
| 1427 |  |  | else | 
| 1428 |  |  | fprintf(fp, "PLOT3D(POLYGONS(\n"); | 
| 1429 |  |  | }else | 
| 1430 |  |  | fprintf(fp, "{\n"); | 
| 1431 |  |  | qh printoutvar= 0;   /* counts number of facets for notfirst */ | 
| 1432 |  |  | break; | 
| 1433 |  |  | case qh_PRINTmerges: | 
| 1434 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1435 |  |  | break; | 
| 1436 |  |  | case qh_PRINTpointintersect: | 
| 1437 |  |  | fprintf (fp, "%d\n%d\n", qh hull_dim, numfacets); | 
| 1438 |  |  | break; | 
| 1439 |  |  | case qh_PRINTneighbors: | 
| 1440 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1441 |  |  | break; | 
| 1442 |  |  | case qh_PRINToff: | 
| 1443 |  |  | case qh_PRINTtriangles: | 
| 1444 |  |  | if (qh VORONOI) | 
| 1445 |  |  | goto LABELnoformat; | 
| 1446 |  |  | num = qh hull_dim; | 
| 1447 |  |  | if (format == qh_PRINToff || qh hull_dim == 2) | 
| 1448 |  |  | fprintf (fp, "%d\n%d %d %d\n", num, | 
| 1449 |  |  | qh num_points+qh_setsize (qh other_points), numfacets, totneighbors/2); | 
| 1450 |  |  | else { /* qh_PRINTtriangles */ | 
| 1451 |  |  | qh printoutvar= qh num_points+qh_setsize (qh other_points); /* first centrum */ | 
| 1452 |  |  | if (qh DELAUNAY) | 
| 1453 |  |  | num--;  /* drop last dimension */ | 
| 1454 |  |  | fprintf (fp, "%d\n%d %d %d\n", num, qh printoutvar | 
| 1455 |  |  | + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2); | 
| 1456 |  |  | } | 
| 1457 |  |  | FORALLpoints | 
| 1458 |  |  | qh_printpointid (qh fout, NULL, num, point, -1); | 
| 1459 |  |  | FOREACHpoint_(qh other_points) | 
| 1460 |  |  | qh_printpointid (qh fout, NULL, num, point, -1); | 
| 1461 |  |  | if (format == qh_PRINTtriangles && qh hull_dim > 2) { | 
| 1462 |  |  | FORALLfacets { | 
| 1463 |  |  | if (!facet->simplicial && facet->visitid) | 
| 1464 |  |  | qh_printcenter (qh fout, format, NULL, facet); | 
| 1465 |  |  | } | 
| 1466 |  |  | } | 
| 1467 |  |  | break; | 
| 1468 |  |  | case qh_PRINTpointnearest: | 
| 1469 |  |  | fprintf (fp, "%d\n", numcoplanars); | 
| 1470 |  |  | break; | 
| 1471 |  |  | case qh_PRINTpoints: | 
| 1472 |  |  | if (!qh VORONOI) | 
| 1473 |  |  | goto LABELnoformat; | 
| 1474 |  |  | if (qh CDDoutput) | 
| 1475 |  |  | fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command, | 
| 1476 |  |  | qh qhull_command, numfacets, qh hull_dim); | 
| 1477 |  |  | else | 
| 1478 |  |  | fprintf (fp, "%d\n%d\n", qh hull_dim-1, numfacets); | 
| 1479 |  |  | break; | 
| 1480 |  |  | case qh_PRINTvertices: | 
| 1481 |  |  | fprintf (fp, "%d\n", numfacets); | 
| 1482 |  |  | break; | 
| 1483 |  |  | case qh_PRINTsummary: | 
| 1484 |  |  | default: | 
| 1485 |  |  | LABELnoformat: | 
| 1486 |  |  | fprintf (qh ferr, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n", | 
| 1487 |  |  | qh hull_dim); | 
| 1488 |  |  | qh_errexit (qh_ERRqhull, NULL, NULL); | 
| 1489 |  |  | } | 
| 1490 |  |  | } /* printbegin */ | 
| 1491 |  |  |  | 
| 1492 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1493 |  |  | >-------------------------------</a><a name="printcenter">-</a> | 
| 1494 |  |  |  | 
| 1495 |  |  | qh_printcenter( fp, string, facet ) | 
| 1496 |  |  | print facet->center as centrum or Voronoi center | 
| 1497 |  |  | string may be NULL.  Don't include '%' codes. | 
| 1498 |  |  | nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum | 
| 1499 |  |  | if upper envelope of Delaunay triangulation and point at-infinity | 
| 1500 |  |  | prints qh_INFINITE instead; | 
| 1501 |  |  |  | 
| 1502 |  |  | notes: | 
| 1503 |  |  | defines facet->center if needed | 
| 1504 |  |  | if format=PRINTgeom, adds a 0 if would otherwise be 2-d | 
| 1505 |  |  | */ | 
| 1506 |  |  | void qh_printcenter (FILE *fp, int format, char *string, facetT *facet) { | 
| 1507 |  |  | int k, num; | 
| 1508 |  |  |  | 
| 1509 |  |  | if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum) | 
| 1510 |  |  | return; | 
| 1511 |  |  | if (string) | 
| 1512 |  |  | fprintf (fp, string, facet->id); | 
| 1513 |  |  | if (qh CENTERtype == qh_ASvoronoi) { | 
| 1514 |  |  | num= qh hull_dim-1; | 
| 1515 |  |  | if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) { | 
| 1516 |  |  | if (!facet->center) | 
| 1517 |  |  | facet->center= qh_facetcenter (facet->vertices); | 
| 1518 |  |  | for (k=0; k < num; k++) | 
| 1519 |  |  | fprintf (fp, qh_REAL_1, facet->center[k]); | 
| 1520 |  |  | }else { | 
| 1521 |  |  | for (k=0; k < num; k++) | 
| 1522 |  |  | fprintf (fp, qh_REAL_1, qh_INFINITE); | 
| 1523 |  |  | } | 
| 1524 |  |  | }else /* qh CENTERtype == qh_AScentrum */ { | 
| 1525 |  |  | num= qh hull_dim; | 
| 1526 |  |  | if (format == qh_PRINTtriangles && qh DELAUNAY) | 
| 1527 |  |  | num--; | 
| 1528 |  |  | if (!facet->center) | 
| 1529 |  |  | facet->center= qh_getcentrum (facet); | 
| 1530 |  |  | for (k=0; k < num; k++) | 
| 1531 |  |  | fprintf (fp, qh_REAL_1, facet->center[k]); | 
| 1532 |  |  | } | 
| 1533 |  |  | if (format == qh_PRINTgeom && num == 2) | 
| 1534 |  |  | fprintf (fp, " 0\n"); | 
| 1535 |  |  | else | 
| 1536 |  |  | fprintf (fp, "\n"); | 
| 1537 |  |  | } /* printcenter */ | 
| 1538 |  |  |  | 
| 1539 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1540 |  |  | >-------------------------------</a><a name="printcentrum">-</a> | 
| 1541 |  |  |  | 
| 1542 |  |  | qh_printcentrum( fp, facet, radius ) | 
| 1543 |  |  | print centrum for a facet in OOGL format | 
| 1544 |  |  | radius defines size of centrum | 
| 1545 |  |  | 2-d or 3-d only | 
| 1546 |  |  |  | 
| 1547 |  |  | returns: | 
| 1548 |  |  | defines facet->center if needed | 
| 1549 |  |  | */ | 
| 1550 |  |  | void qh_printcentrum (FILE *fp, facetT *facet, realT radius) { | 
| 1551 |  |  | pointT *centrum, *projpt; | 
| 1552 |  |  | boolT tempcentrum= False; | 
| 1553 |  |  | realT xaxis[4], yaxis[4], normal[4], dist; | 
| 1554 |  |  | realT green[3]={0, 1, 0}; | 
| 1555 |  |  | vertexT *apex; | 
| 1556 |  |  | int k; | 
| 1557 |  |  |  | 
| 1558 |  |  | if (qh CENTERtype == qh_AScentrum) { | 
| 1559 |  |  | if (!facet->center) | 
| 1560 |  |  | facet->center= qh_getcentrum (facet); | 
| 1561 |  |  | centrum= facet->center; | 
| 1562 |  |  | }else { | 
| 1563 |  |  | centrum= qh_getcentrum (facet); | 
| 1564 |  |  | tempcentrum= True; | 
| 1565 |  |  | } | 
| 1566 |  |  | fprintf (fp, "{appearance {-normal -edge normscale 0} "); | 
| 1567 |  |  | if (qh firstcentrum) { | 
| 1568 |  |  | qh firstcentrum= False; | 
| 1569 |  |  | fprintf (fp, "{INST geom { define centrum CQUAD  # f%d\n\ | 
| 1570 |  |  | -0.3 -0.3 0.0001     0 0 1 1\n\ | 
| 1571 |  |  | 0.3 -0.3 0.0001     0 0 1 1\n\ | 
| 1572 |  |  | 0.3  0.3 0.0001     0 0 1 1\n\ | 
| 1573 |  |  | -0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id); | 
| 1574 |  |  | }else | 
| 1575 |  |  | fprintf (fp, "{INST geom { : centrum } transform { # f%d\n", facet->id); | 
| 1576 |  |  | apex= SETfirstt_(facet->vertices, vertexT); | 
| 1577 |  |  | qh_distplane(apex->point, facet, &dist); | 
| 1578 |  |  | projpt= qh_projectpoint(apex->point, facet, dist); | 
| 1579 |  |  | for (k= qh hull_dim; k--; ) { | 
| 1580 |  |  | xaxis[k]= projpt[k] - centrum[k]; | 
| 1581 |  |  | normal[k]= facet->normal[k]; | 
| 1582 |  |  | } | 
| 1583 |  |  | if (qh hull_dim == 2) { | 
| 1584 |  |  | xaxis[2]= 0; | 
| 1585 |  |  | normal[2]= 0; | 
| 1586 |  |  | }else if (qh hull_dim == 4) { | 
| 1587 |  |  | qh_projectdim3 (xaxis, xaxis); | 
| 1588 |  |  | qh_projectdim3 (normal, normal); | 
| 1589 |  |  | qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL); | 
| 1590 |  |  | } | 
| 1591 |  |  | qh_crossproduct (3, xaxis, normal, yaxis); | 
| 1592 |  |  | fprintf (fp, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]); | 
| 1593 |  |  | fprintf (fp, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]); | 
| 1594 |  |  | fprintf (fp, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]); | 
| 1595 |  |  | qh_printpoint3 (fp, centrum); | 
| 1596 |  |  | fprintf (fp, "1 }}}\n"); | 
| 1597 |  |  | qh_memfree (projpt, qh normal_size); | 
| 1598 |  |  | qh_printpointvect (fp, centrum, facet->normal, NULL, radius, green); | 
| 1599 |  |  | if (tempcentrum) | 
| 1600 |  |  | qh_memfree (centrum, qh normal_size); | 
| 1601 |  |  | } /* printcentrum */ | 
| 1602 |  |  |  | 
| 1603 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1604 |  |  | >-------------------------------</a><a name="printend">-</a> | 
| 1605 |  |  |  | 
| 1606 |  |  | qh_printend( fp, format ) | 
| 1607 |  |  | prints trailer for all output formats | 
| 1608 |  |  |  | 
| 1609 |  |  | see: | 
| 1610 |  |  | qh_printbegin() and qh_printafacet() | 
| 1611 |  |  |  | 
| 1612 |  |  | */ | 
| 1613 |  |  | void qh_printend (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) { | 
| 1614 |  |  | int num; | 
| 1615 |  |  | facetT *facet, **facetp; | 
| 1616 |  |  |  | 
| 1617 |  |  | if (!qh printoutnum) | 
| 1618 |  |  | fprintf (qh ferr, "qhull warning: no facets printed\n"); | 
| 1619 |  |  | switch (format) { | 
| 1620 |  |  | case qh_PRINTgeom: | 
| 1621 |  |  | if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) { | 
| 1622 |  |  | qh visit_id++; | 
| 1623 |  |  | num= 0; | 
| 1624 |  |  | FORALLfacet_(facetlist) | 
| 1625 |  |  | qh_printend4geom (fp, facet,&num, printall); | 
| 1626 |  |  | FOREACHfacet_(facets) | 
| 1627 |  |  | qh_printend4geom (fp, facet, &num, printall); | 
| 1628 |  |  | if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) { | 
| 1629 |  |  | fprintf (qh ferr, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num); | 
| 1630 |  |  | qh_errexit (qh_ERRqhull, NULL, NULL); | 
| 1631 |  |  | } | 
| 1632 |  |  | }else | 
| 1633 |  |  | fprintf(fp, "}\n"); | 
| 1634 |  |  | break; | 
| 1635 |  |  | case qh_PRINTinner: | 
| 1636 |  |  | case qh_PRINTnormals: | 
| 1637 |  |  | case qh_PRINTouter: | 
| 1638 |  |  | if (qh CDDoutput) | 
| 1639 |  |  | fprintf (fp, "end\n"); | 
| 1640 |  |  | break; | 
| 1641 |  |  | case qh_PRINTmaple: | 
| 1642 |  |  | fprintf(fp, "));\n"); | 
| 1643 |  |  | break; | 
| 1644 |  |  | case qh_PRINTmathematica: | 
| 1645 |  |  | fprintf(fp, "}\n"); | 
| 1646 |  |  | break; | 
| 1647 |  |  | case qh_PRINTpoints: | 
| 1648 |  |  | if (qh CDDoutput) | 
| 1649 |  |  | fprintf (fp, "end\n"); | 
| 1650 |  |  | break; | 
| 1651 |  |  | } | 
| 1652 |  |  | } /* printend */ | 
| 1653 |  |  |  | 
| 1654 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1655 |  |  | >-------------------------------</a><a name="printend4geom">-</a> | 
| 1656 |  |  |  | 
| 1657 |  |  | qh_printend4geom( fp, facet, numridges, printall ) | 
| 1658 |  |  | helper function for qh_printbegin/printend | 
| 1659 |  |  |  | 
| 1660 |  |  | returns: | 
| 1661 |  |  | number of printed ridges | 
| 1662 |  |  |  | 
| 1663 |  |  | notes: | 
| 1664 |  |  | just counts printed ridges if fp=NULL | 
| 1665 |  |  | uses facet->visitid | 
| 1666 |  |  | must agree with qh_printfacet4geom... | 
| 1667 |  |  |  | 
| 1668 |  |  | design: | 
| 1669 |  |  | computes color for facet from its normal | 
| 1670 |  |  | prints each ridge of facet | 
| 1671 |  |  | */ | 
| 1672 |  |  | void qh_printend4geom (FILE *fp, facetT *facet, int *nump, boolT printall) { | 
| 1673 |  |  | realT color[3]; | 
| 1674 |  |  | int i, num= *nump; | 
| 1675 |  |  | facetT *neighbor, **neighborp; | 
| 1676 |  |  | ridgeT *ridge, **ridgep; | 
| 1677 |  |  |  | 
| 1678 |  |  | if (!printall && qh_skipfacet(facet)) | 
| 1679 |  |  | return; | 
| 1680 |  |  | if (qh PRINTnoplanes || (facet->visible && qh NEWfacets)) | 
| 1681 |  |  | return; | 
| 1682 |  |  | if (!facet->normal) | 
| 1683 |  |  | return; | 
| 1684 |  |  | if (fp) { | 
| 1685 |  |  | for (i=0; i < 3; i++) { | 
| 1686 |  |  | color[i]= (facet->normal[i]+1.0)/2.0; | 
| 1687 |  |  | maximize_(color[i], -1.0); | 
| 1688 |  |  | minimize_(color[i], +1.0); | 
| 1689 |  |  | } | 
| 1690 |  |  | } | 
| 1691 |  |  | facet->visitid= qh visit_id; | 
| 1692 |  |  | if (facet->simplicial) { | 
| 1693 |  |  | FOREACHneighbor_(facet) { | 
| 1694 |  |  | if (neighbor->visitid != qh visit_id) { | 
| 1695 |  |  | if (fp) | 
| 1696 |  |  | fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n", | 
| 1697 |  |  | 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2], | 
| 1698 |  |  | facet->id, neighbor->id); | 
| 1699 |  |  | num++; | 
| 1700 |  |  | } | 
| 1701 |  |  | } | 
| 1702 |  |  | }else { | 
| 1703 |  |  | FOREACHridge_(facet->ridges) { | 
| 1704 |  |  | neighbor= otherfacet_(ridge, facet); | 
| 1705 |  |  | if (neighbor->visitid != qh visit_id) { | 
| 1706 |  |  | if (fp) | 
| 1707 |  |  | fprintf (fp, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n", | 
| 1708 |  |  | 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2], | 
| 1709 |  |  | ridge->id, facet->id, neighbor->id); | 
| 1710 |  |  | num++; | 
| 1711 |  |  | } | 
| 1712 |  |  | } | 
| 1713 |  |  | } | 
| 1714 |  |  | *nump= num; | 
| 1715 |  |  | } /* printend4geom */ | 
| 1716 |  |  |  | 
| 1717 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1718 |  |  | >-------------------------------</a><a name="printextremes">-</a> | 
| 1719 |  |  |  | 
| 1720 |  |  | qh_printextremes( fp, facetlist, facets, printall ) | 
| 1721 |  |  | print extreme points for convex hulls or halfspace intersections | 
| 1722 |  |  |  | 
| 1723 |  |  | notes: | 
| 1724 |  |  | #points, followed by ids, one per line | 
| 1725 |  |  |  | 
| 1726 |  |  | sorted by id | 
| 1727 |  |  | same order as qh_printpoints_out if no coplanar/interior points | 
| 1728 |  |  | */ | 
| 1729 |  |  | void qh_printextremes (FILE *fp, facetT *facetlist, setT *facets, int printall) { | 
| 1730 |  |  | setT *vertices, *points; | 
| 1731 |  |  | pointT *point; | 
| 1732 |  |  | vertexT *vertex, **vertexp; | 
| 1733 |  |  | int id; | 
| 1734 |  |  | int numpoints=0, point_i, point_n; | 
| 1735 |  |  | int allpoints= qh num_points + qh_setsize (qh other_points); | 
| 1736 |  |  |  | 
| 1737 |  |  | points= qh_settemp (allpoints); | 
| 1738 |  |  | qh_setzero (points, 0, allpoints); | 
| 1739 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 1740 |  |  | FOREACHvertex_(vertices) { | 
| 1741 |  |  | id= qh_pointid (vertex->point); | 
| 1742 |  |  | if (id >= 0) { | 
| 1743 |  |  | SETelem_(points, id)= vertex->point; | 
| 1744 |  |  | numpoints++; | 
| 1745 |  |  | } | 
| 1746 |  |  | } | 
| 1747 |  |  | qh_settempfree (&vertices); | 
| 1748 |  |  | fprintf (fp, "%d\n", numpoints); | 
| 1749 |  |  | FOREACHpoint_i_(points) { | 
| 1750 |  |  | if (point) | 
| 1751 |  |  | fprintf (fp, "%d\n", point_i); | 
| 1752 |  |  | } | 
| 1753 |  |  | qh_settempfree (&points); | 
| 1754 |  |  | } /* printextremes */ | 
| 1755 |  |  |  | 
| 1756 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1757 |  |  | >-------------------------------</a><a name="printextremes_2d">-</a> | 
| 1758 |  |  |  | 
| 1759 |  |  | qh_printextremes_2d( fp, facetlist, facets, printall ) | 
| 1760 |  |  | prints point ids for facets in qh_ORIENTclock order | 
| 1761 |  |  |  | 
| 1762 |  |  | notes: | 
| 1763 |  |  | #points, followed by ids, one per line | 
| 1764 |  |  | if facetlist/facets are disjoint than the output includes skips | 
| 1765 |  |  | errors if facets form a loop | 
| 1766 |  |  | does not print coplanar points | 
| 1767 |  |  | */ | 
| 1768 |  |  | void qh_printextremes_2d (FILE *fp, facetT *facetlist, setT *facets, int printall) { | 
| 1769 |  |  | int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars; | 
| 1770 |  |  | setT *vertices; | 
| 1771 |  |  | facetT *facet, *startfacet, *nextfacet; | 
| 1772 |  |  | vertexT *vertexA, *vertexB; | 
| 1773 |  |  |  | 
| 1774 |  |  | qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, | 
| 1775 |  |  | &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */ | 
| 1776 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 1777 |  |  | fprintf(fp, "%d\n", qh_setsize (vertices)); | 
| 1778 |  |  | qh_settempfree (&vertices); | 
| 1779 |  |  | if (!numfacets) | 
| 1780 |  |  | return; | 
| 1781 |  |  | facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT); | 
| 1782 |  |  | qh vertex_visit++; | 
| 1783 |  |  | qh visit_id++; | 
| 1784 |  |  | do { | 
| 1785 |  |  | if (facet->toporient ^ qh_ORIENTclock) { | 
| 1786 |  |  | vertexA= SETfirstt_(facet->vertices, vertexT); | 
| 1787 |  |  | vertexB= SETsecondt_(facet->vertices, vertexT); | 
| 1788 |  |  | nextfacet= SETfirstt_(facet->neighbors, facetT); | 
| 1789 |  |  | }else { | 
| 1790 |  |  | vertexA= SETsecondt_(facet->vertices, vertexT); | 
| 1791 |  |  | vertexB= SETfirstt_(facet->vertices, vertexT); | 
| 1792 |  |  | nextfacet= SETsecondt_(facet->neighbors, facetT); | 
| 1793 |  |  | } | 
| 1794 |  |  | if (facet->visitid == qh visit_id) { | 
| 1795 |  |  | fprintf(qh ferr, "qh_printextremes_2d: loop in facet list.  facet %d nextfacet %d\n", | 
| 1796 |  |  | facet->id, nextfacet->id); | 
| 1797 |  |  | qh_errexit2 (qh_ERRqhull, facet, nextfacet); | 
| 1798 |  |  | } | 
| 1799 |  |  | if (facet->visitid) { | 
| 1800 |  |  | if (vertexA->visitid != qh vertex_visit) { | 
| 1801 |  |  | vertexA->visitid= qh vertex_visit; | 
| 1802 |  |  | fprintf(fp, "%d\n", qh_pointid (vertexA->point)); | 
| 1803 |  |  | } | 
| 1804 |  |  | if (vertexB->visitid != qh vertex_visit) { | 
| 1805 |  |  | vertexB->visitid= qh vertex_visit; | 
| 1806 |  |  | fprintf(fp, "%d\n", qh_pointid (vertexB->point)); | 
| 1807 |  |  | } | 
| 1808 |  |  | } | 
| 1809 |  |  | facet->visitid= qh visit_id; | 
| 1810 |  |  | facet= nextfacet; | 
| 1811 |  |  | }while (facet && facet != startfacet); | 
| 1812 |  |  | } /* printextremes_2d */ | 
| 1813 |  |  |  | 
| 1814 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1815 |  |  | >-------------------------------</a><a name="printextremes_d">-</a> | 
| 1816 |  |  |  | 
| 1817 |  |  | qh_printextremes_d( fp, facetlist, facets, printall ) | 
| 1818 |  |  | print extreme points of input sites for Delaunay triangulations | 
| 1819 |  |  |  | 
| 1820 |  |  | notes: | 
| 1821 |  |  | #points, followed by ids, one per line | 
| 1822 |  |  |  | 
| 1823 |  |  | unordered | 
| 1824 |  |  | */ | 
| 1825 |  |  | void qh_printextremes_d (FILE *fp, facetT *facetlist, setT *facets, int printall) { | 
| 1826 |  |  | setT *vertices; | 
| 1827 |  |  | vertexT *vertex, **vertexp; | 
| 1828 |  |  | boolT upperseen, lowerseen; | 
| 1829 |  |  | facetT *neighbor, **neighborp; | 
| 1830 |  |  | int numpoints=0; | 
| 1831 |  |  |  | 
| 1832 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 1833 |  |  | qh_vertexneighbors(); | 
| 1834 |  |  | FOREACHvertex_(vertices) { | 
| 1835 |  |  | upperseen= lowerseen= False; | 
| 1836 |  |  | FOREACHneighbor_(vertex) { | 
| 1837 |  |  | if (neighbor->upperdelaunay) | 
| 1838 |  |  | upperseen= True; | 
| 1839 |  |  | else | 
| 1840 |  |  | lowerseen= True; | 
| 1841 |  |  | } | 
| 1842 |  |  | if (upperseen && lowerseen) { | 
| 1843 |  |  | vertex->seen= True; | 
| 1844 |  |  | numpoints++; | 
| 1845 |  |  | }else | 
| 1846 |  |  | vertex->seen= False; | 
| 1847 |  |  | } | 
| 1848 |  |  | fprintf (fp, "%d\n", numpoints); | 
| 1849 |  |  | FOREACHvertex_(vertices) { | 
| 1850 |  |  | if (vertex->seen) | 
| 1851 |  |  | fprintf (fp, "%d\n", qh_pointid (vertex->point)); | 
| 1852 |  |  | } | 
| 1853 |  |  | qh_settempfree (&vertices); | 
| 1854 |  |  | } /* printextremes_d */ | 
| 1855 |  |  |  | 
| 1856 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1857 |  |  | >-------------------------------</a><a name="printfacet">-</a> | 
| 1858 |  |  |  | 
| 1859 |  |  | qh_printfacet( fp, facet ) | 
| 1860 |  |  | prints all fields of a facet to fp | 
| 1861 |  |  |  | 
| 1862 |  |  | notes: | 
| 1863 |  |  | ridges printed in neighbor order | 
| 1864 |  |  | */ | 
| 1865 |  |  | void qh_printfacet(FILE *fp, facetT *facet) { | 
| 1866 |  |  |  | 
| 1867 |  |  | qh_printfacetheader (fp, facet); | 
| 1868 |  |  | if (facet->ridges) | 
| 1869 |  |  | qh_printfacetridges (fp, facet); | 
| 1870 |  |  | } /* printfacet */ | 
| 1871 |  |  |  | 
| 1872 |  |  |  | 
| 1873 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1874 |  |  | >-------------------------------</a><a name="printfacet2geom">-</a> | 
| 1875 |  |  |  | 
| 1876 |  |  | qh_printfacet2geom( fp, facet, color ) | 
| 1877 |  |  | print facet as part of a 2-d VECT for Geomview | 
| 1878 |  |  |  | 
| 1879 |  |  | notes: | 
| 1880 |  |  | assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon | 
| 1881 |  |  | mindist is calculated within io.c.  maxoutside is calculated elsewhere | 
| 1882 |  |  | so a DISTround error may have occured. | 
| 1883 |  |  | */ | 
| 1884 |  |  | void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) { | 
| 1885 |  |  | pointT *point0, *point1; | 
| 1886 |  |  | realT mindist, innerplane, outerplane; | 
| 1887 |  |  | int k; | 
| 1888 |  |  |  | 
| 1889 |  |  | qh_facet2point (facet, &point0, &point1, &mindist); | 
| 1890 |  |  | qh_geomplanes (facet, &outerplane, &innerplane); | 
| 1891 |  |  | if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner)) | 
| 1892 |  |  | qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color); | 
| 1893 |  |  | if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter && | 
| 1894 |  |  | outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) { | 
| 1895 |  |  | for(k= 3; k--; ) | 
| 1896 |  |  | color[k]= 1.0 - color[k]; | 
| 1897 |  |  | qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color); | 
| 1898 |  |  | } | 
| 1899 |  |  | qh_memfree (point1, qh normal_size); | 
| 1900 |  |  | qh_memfree (point0, qh normal_size); | 
| 1901 |  |  | } /* printfacet2geom */ | 
| 1902 |  |  |  | 
| 1903 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1904 |  |  | >-------------------------------</a><a name="printfacet2geom_points">-</a> | 
| 1905 |  |  |  | 
| 1906 |  |  | qh_printfacet2geom_points( fp, point1, point2, facet, offset, color ) | 
| 1907 |  |  | prints a 2-d facet as a VECT with 2 points at some offset. | 
| 1908 |  |  | The points are on the facet's plane. | 
| 1909 |  |  | */ | 
| 1910 |  |  | void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2, | 
| 1911 |  |  | facetT *facet, realT offset, realT color[3]) { | 
| 1912 |  |  | pointT *p1= point1, *p2= point2; | 
| 1913 |  |  |  | 
| 1914 |  |  | fprintf(fp, "VECT 1 2 1 2 1 # f%d\n", facet->id); | 
| 1915 |  |  | if (offset != 0.0) { | 
| 1916 |  |  | p1= qh_projectpoint (p1, facet, -offset); | 
| 1917 |  |  | p2= qh_projectpoint (p2, facet, -offset); | 
| 1918 |  |  | } | 
| 1919 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n", | 
| 1920 |  |  | p1[0], p1[1], 0.0, p2[0], p2[1], 0.0); | 
| 1921 |  |  | if (offset != 0.0) { | 
| 1922 |  |  | qh_memfree (p1, qh normal_size); | 
| 1923 |  |  | qh_memfree (p2, qh normal_size); | 
| 1924 |  |  | } | 
| 1925 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]); | 
| 1926 |  |  | } /* printfacet2geom_points */ | 
| 1927 |  |  |  | 
| 1928 |  |  |  | 
| 1929 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1930 |  |  | >-------------------------------</a><a name="printfacet2math">-</a> | 
| 1931 |  |  |  | 
| 1932 |  |  | qh_printfacet2math( fp, facet, format, notfirst ) | 
| 1933 |  |  | print 2-d Maple or Mathematica output for a facet | 
| 1934 |  |  | may be non-simplicial | 
| 1935 |  |  |  | 
| 1936 |  |  | notes: | 
| 1937 |  |  | please use %16.8f since Mathematica 2.2 does not handle exponential format | 
| 1938 |  |  | see qh_printfacet3math | 
| 1939 |  |  | */ | 
| 1940 |  |  | void qh_printfacet2math(FILE *fp, facetT *facet, int format, int notfirst) { | 
| 1941 |  |  | pointT *point0, *point1; | 
| 1942 |  |  | realT mindist; | 
| 1943 |  |  | char *pointfmt; | 
| 1944 |  |  |  | 
| 1945 |  |  | qh_facet2point (facet, &point0, &point1, &mindist); | 
| 1946 |  |  | if (notfirst) | 
| 1947 |  |  | fprintf(fp, ","); | 
| 1948 |  |  | if (format == qh_PRINTmaple) | 
| 1949 |  |  | pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n"; | 
| 1950 |  |  | else | 
| 1951 |  |  | pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n"; | 
| 1952 |  |  | fprintf(fp, pointfmt, point0[0], point0[1], point1[0], point1[1]); | 
| 1953 |  |  | qh_memfree (point1, qh normal_size); | 
| 1954 |  |  | qh_memfree (point0, qh normal_size); | 
| 1955 |  |  | } /* printfacet2math */ | 
| 1956 |  |  |  | 
| 1957 |  |  |  | 
| 1958 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 1959 |  |  | >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a> | 
| 1960 |  |  |  | 
| 1961 |  |  | qh_printfacet3geom_nonsimplicial( fp, facet, color ) | 
| 1962 |  |  | print Geomview OFF for a 3-d nonsimplicial facet. | 
| 1963 |  |  | if DOintersections, prints ridges to unvisited neighbors (qh visit_id) | 
| 1964 |  |  |  | 
| 1965 |  |  | notes | 
| 1966 |  |  | uses facet->visitid for intersections and ridges | 
| 1967 |  |  | */ | 
| 1968 |  |  | void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) { | 
| 1969 |  |  | ridgeT *ridge, **ridgep; | 
| 1970 |  |  | setT *projectedpoints, *vertices; | 
| 1971 |  |  | vertexT *vertex, **vertexp, *vertexA, *vertexB; | 
| 1972 |  |  | pointT *projpt, *point, **pointp; | 
| 1973 |  |  | facetT *neighbor; | 
| 1974 |  |  | realT dist, outerplane, innerplane; | 
| 1975 |  |  | int cntvertices, k; | 
| 1976 |  |  | realT black[3]={0, 0, 0}, green[3]={0, 1, 0}; | 
| 1977 |  |  |  | 
| 1978 |  |  | qh_geomplanes (facet, &outerplane, &innerplane); | 
| 1979 |  |  | vertices= qh_facet3vertex (facet); /* oriented */ | 
| 1980 |  |  | cntvertices= qh_setsize(vertices); | 
| 1981 |  |  | projectedpoints= qh_settemp(cntvertices); | 
| 1982 |  |  | FOREACHvertex_(vertices) { | 
| 1983 |  |  | zinc_(Zdistio); | 
| 1984 |  |  | qh_distplane(vertex->point, facet, &dist); | 
| 1985 |  |  | projpt= qh_projectpoint(vertex->point, facet, dist); | 
| 1986 |  |  | qh_setappend (&projectedpoints, projpt); | 
| 1987 |  |  | } | 
| 1988 |  |  | if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner)) | 
| 1989 |  |  | qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color); | 
| 1990 |  |  | if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter && | 
| 1991 |  |  | outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) { | 
| 1992 |  |  | for (k=3; k--; ) | 
| 1993 |  |  | color[k]= 1.0 - color[k]; | 
| 1994 |  |  | qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color); | 
| 1995 |  |  | } | 
| 1996 |  |  | FOREACHpoint_(projectedpoints) | 
| 1997 |  |  | qh_memfree (point, qh normal_size); | 
| 1998 |  |  | qh_settempfree(&projectedpoints); | 
| 1999 |  |  | qh_settempfree(&vertices); | 
| 2000 |  |  | if ((qh DOintersections || qh PRINTridges) | 
| 2001 |  |  | && (!facet->visible || !qh NEWfacets)) { | 
| 2002 |  |  | facet->visitid= qh visit_id; | 
| 2003 |  |  | FOREACHridge_(facet->ridges) { | 
| 2004 |  |  | neighbor= otherfacet_(ridge, facet); | 
| 2005 |  |  | if (neighbor->visitid != qh visit_id) { | 
| 2006 |  |  | if (qh DOintersections) | 
| 2007 |  |  | qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black); | 
| 2008 |  |  | if (qh PRINTridges) { | 
| 2009 |  |  | vertexA= SETfirstt_(ridge->vertices, vertexT); | 
| 2010 |  |  | vertexB= SETsecondt_(ridge->vertices, vertexT); | 
| 2011 |  |  | qh_printline3geom (fp, vertexA->point, vertexB->point, green); | 
| 2012 |  |  | } | 
| 2013 |  |  | } | 
| 2014 |  |  | } | 
| 2015 |  |  | } | 
| 2016 |  |  | } /* printfacet3geom_nonsimplicial */ | 
| 2017 |  |  |  | 
| 2018 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2019 |  |  | >-------------------------------</a><a name="printfacet3geom_points">-</a> | 
| 2020 |  |  |  | 
| 2021 |  |  | qh_printfacet3geom_points( fp, points, facet, offset ) | 
| 2022 |  |  | prints a 3-d facet as OFF Geomview object. | 
| 2023 |  |  | offset is relative to the facet's hyperplane | 
| 2024 |  |  | Facet is determined as a list of points | 
| 2025 |  |  | */ | 
| 2026 |  |  | void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) { | 
| 2027 |  |  | int k, n= qh_setsize(points), i; | 
| 2028 |  |  | pointT *point, **pointp; | 
| 2029 |  |  | setT *printpoints; | 
| 2030 |  |  |  | 
| 2031 |  |  | fprintf(fp, "{ OFF %d 1 1 # f%d\n", n, facet->id); | 
| 2032 |  |  | if (offset != 0.0) { | 
| 2033 |  |  | printpoints= qh_settemp (n); | 
| 2034 |  |  | FOREACHpoint_(points) | 
| 2035 |  |  | qh_setappend (&printpoints, qh_projectpoint(point, facet, -offset)); | 
| 2036 |  |  | }else | 
| 2037 |  |  | printpoints= points; | 
| 2038 |  |  | FOREACHpoint_(printpoints) { | 
| 2039 |  |  | for (k=0; k < qh hull_dim; k++) { | 
| 2040 |  |  | if (k == qh DROPdim) | 
| 2041 |  |  | fprintf(fp, "0 "); | 
| 2042 |  |  | else | 
| 2043 |  |  | fprintf(fp, "%8.4g ", point[k]); | 
| 2044 |  |  | } | 
| 2045 |  |  | if (printpoints != points) | 
| 2046 |  |  | qh_memfree (point, qh normal_size); | 
| 2047 |  |  | fprintf (fp, "\n"); | 
| 2048 |  |  | } | 
| 2049 |  |  | if (printpoints != points) | 
| 2050 |  |  | qh_settempfree (&printpoints); | 
| 2051 |  |  | fprintf(fp, "%d ", n); | 
| 2052 |  |  | for(i= 0; i < n; i++) | 
| 2053 |  |  | fprintf(fp, "%d ", i); | 
| 2054 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]); | 
| 2055 |  |  | } /* printfacet3geom_points */ | 
| 2056 |  |  |  | 
| 2057 |  |  |  | 
| 2058 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2059 |  |  | >-------------------------------</a><a name="printfacet3geom_simplicial">-</a> | 
| 2060 |  |  |  | 
| 2061 |  |  | qh_printfacet3geom_simplicial(  ) | 
| 2062 |  |  | print Geomview OFF for a 3-d simplicial facet. | 
| 2063 |  |  |  | 
| 2064 |  |  | notes: | 
| 2065 |  |  | may flip color | 
| 2066 |  |  | uses facet->visitid for intersections and ridges | 
| 2067 |  |  |  | 
| 2068 |  |  | assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon | 
| 2069 |  |  | innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere | 
| 2070 |  |  | so a DISTround error may have occured. | 
| 2071 |  |  | */ | 
| 2072 |  |  | void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) { | 
| 2073 |  |  | setT *points, *vertices; | 
| 2074 |  |  | vertexT *vertex, **vertexp, *vertexA, *vertexB; | 
| 2075 |  |  | facetT *neighbor, **neighborp; | 
| 2076 |  |  | realT outerplane, innerplane; | 
| 2077 |  |  | realT black[3]={0, 0, 0}, green[3]={0, 1, 0}; | 
| 2078 |  |  | int k; | 
| 2079 |  |  |  | 
| 2080 |  |  | qh_geomplanes (facet, &outerplane, &innerplane); | 
| 2081 |  |  | vertices= qh_facet3vertex (facet); | 
| 2082 |  |  | points= qh_settemp (qh TEMPsize); | 
| 2083 |  |  | FOREACHvertex_(vertices) | 
| 2084 |  |  | qh_setappend(&points, vertex->point); | 
| 2085 |  |  | if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner)) | 
| 2086 |  |  | qh_printfacet3geom_points(fp, points, facet, outerplane, color); | 
| 2087 |  |  | if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter && | 
| 2088 |  |  | outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) { | 
| 2089 |  |  | for (k= 3; k--; ) | 
| 2090 |  |  | color[k]= 1.0 - color[k]; | 
| 2091 |  |  | qh_printfacet3geom_points(fp, points, facet, innerplane, color); | 
| 2092 |  |  | } | 
| 2093 |  |  | qh_settempfree(&points); | 
| 2094 |  |  | qh_settempfree(&vertices); | 
| 2095 |  |  | if ((qh DOintersections || qh PRINTridges) | 
| 2096 |  |  | && (!facet->visible || !qh NEWfacets)) { | 
| 2097 |  |  | facet->visitid= qh visit_id; | 
| 2098 |  |  | FOREACHneighbor_(facet) { | 
| 2099 |  |  | if (neighbor->visitid != qh visit_id) { | 
| 2100 |  |  | vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim, | 
| 2101 |  |  | SETindex_(facet->neighbors, neighbor), 0); | 
| 2102 |  |  | if (qh DOintersections) | 
| 2103 |  |  | qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black); | 
| 2104 |  |  | if (qh PRINTridges) { | 
| 2105 |  |  | vertexA= SETfirstt_(vertices, vertexT); | 
| 2106 |  |  | vertexB= SETsecondt_(vertices, vertexT); | 
| 2107 |  |  | qh_printline3geom (fp, vertexA->point, vertexB->point, green); | 
| 2108 |  |  | } | 
| 2109 |  |  | qh_setfree(&vertices); | 
| 2110 |  |  | } | 
| 2111 |  |  | } | 
| 2112 |  |  | } | 
| 2113 |  |  | } /* printfacet3geom_simplicial */ | 
| 2114 |  |  |  | 
| 2115 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2116 |  |  | >-------------------------------</a><a name="printfacet3math">-</a> | 
| 2117 |  |  |  | 
| 2118 |  |  | qh_printfacet3math( fp, facet, notfirst ) | 
| 2119 |  |  | print 3-d Maple or Mathematica output for a facet | 
| 2120 |  |  |  | 
| 2121 |  |  | notes: | 
| 2122 |  |  | may be non-simplicial | 
| 2123 |  |  | please use %16.8f since Mathematica 2.2 does not handle exponential format | 
| 2124 |  |  | see qh_printfacet2math | 
| 2125 |  |  | */ | 
| 2126 |  |  | void qh_printfacet3math (FILE *fp, facetT *facet, int format, int notfirst) { | 
| 2127 |  |  | vertexT *vertex, **vertexp; | 
| 2128 |  |  | setT *points, *vertices; | 
| 2129 |  |  | pointT *point, **pointp; | 
| 2130 |  |  | boolT firstpoint= True; | 
| 2131 |  |  | realT dist; | 
| 2132 |  |  | char *pointfmt, *endfmt; | 
| 2133 |  |  |  | 
| 2134 |  |  | if (notfirst) | 
| 2135 |  |  | fprintf(fp, ",\n"); | 
| 2136 |  |  | vertices= qh_facet3vertex (facet); | 
| 2137 |  |  | points= qh_settemp (qh_setsize (vertices)); | 
| 2138 |  |  | FOREACHvertex_(vertices) { | 
| 2139 |  |  | zinc_(Zdistio); | 
| 2140 |  |  | qh_distplane(vertex->point, facet, &dist); | 
| 2141 |  |  | point= qh_projectpoint(vertex->point, facet, dist); | 
| 2142 |  |  | qh_setappend (&points, point); | 
| 2143 |  |  | } | 
| 2144 |  |  | if (format == qh_PRINTmaple) { | 
| 2145 |  |  | fprintf(fp, "["); | 
| 2146 |  |  | pointfmt= "[%16.8f, %16.8f, %16.8f]"; | 
| 2147 |  |  | endfmt= "]"; | 
| 2148 |  |  | }else { | 
| 2149 |  |  | fprintf(fp, "Polygon[{"); | 
| 2150 |  |  | pointfmt= "{%16.8f, %16.8f, %16.8f}"; | 
| 2151 |  |  | endfmt= "}]"; | 
| 2152 |  |  | } | 
| 2153 |  |  | FOREACHpoint_(points) { | 
| 2154 |  |  | if (firstpoint) | 
| 2155 |  |  | firstpoint= False; | 
| 2156 |  |  | else | 
| 2157 |  |  | fprintf(fp, ",\n"); | 
| 2158 |  |  | fprintf(fp, pointfmt, point[0], point[1], point[2]); | 
| 2159 |  |  | } | 
| 2160 |  |  | FOREACHpoint_(points) | 
| 2161 |  |  | qh_memfree (point, qh normal_size); | 
| 2162 |  |  | qh_settempfree(&points); | 
| 2163 |  |  | qh_settempfree(&vertices); | 
| 2164 |  |  | fprintf(fp, endfmt); | 
| 2165 |  |  | } /* printfacet3math */ | 
| 2166 |  |  |  | 
| 2167 |  |  |  | 
| 2168 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2169 |  |  | >-------------------------------</a><a name="printfacet3vertex">-</a> | 
| 2170 |  |  |  | 
| 2171 |  |  | qh_printfacet3vertex( fp, facet, format ) | 
| 2172 |  |  | print vertices in a 3-d facet as point ids | 
| 2173 |  |  |  | 
| 2174 |  |  | notes: | 
| 2175 |  |  | prints number of vertices first if format == qh_PRINToff | 
| 2176 |  |  | the facet may be non-simplicial | 
| 2177 |  |  | */ | 
| 2178 |  |  | void qh_printfacet3vertex(FILE *fp, facetT *facet, int format) { | 
| 2179 |  |  | vertexT *vertex, **vertexp; | 
| 2180 |  |  | setT *vertices; | 
| 2181 |  |  |  | 
| 2182 |  |  | vertices= qh_facet3vertex (facet); | 
| 2183 |  |  | if (format == qh_PRINToff) | 
| 2184 |  |  | fprintf (fp, "%d ", qh_setsize (vertices)); | 
| 2185 |  |  | FOREACHvertex_(vertices) | 
| 2186 |  |  | fprintf (fp, "%d ", qh_pointid(vertex->point)); | 
| 2187 |  |  | fprintf (fp, "\n"); | 
| 2188 |  |  | qh_settempfree(&vertices); | 
| 2189 |  |  | } /* printfacet3vertex */ | 
| 2190 |  |  |  | 
| 2191 |  |  |  | 
| 2192 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2193 |  |  | >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a> | 
| 2194 |  |  |  | 
| 2195 |  |  | qh_printfacet4geom_nonsimplicial(  ) | 
| 2196 |  |  | print Geomview 4OFF file for a 4d nonsimplicial facet | 
| 2197 |  |  | prints all ridges to unvisited neighbors (qh.visit_id) | 
| 2198 |  |  | if qh.DROPdim | 
| 2199 |  |  | prints in OFF format | 
| 2200 |  |  |  | 
| 2201 |  |  | notes: | 
| 2202 |  |  | must agree with printend4geom() | 
| 2203 |  |  | */ | 
| 2204 |  |  | void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) { | 
| 2205 |  |  | facetT *neighbor; | 
| 2206 |  |  | ridgeT *ridge, **ridgep; | 
| 2207 |  |  | vertexT *vertex, **vertexp; | 
| 2208 |  |  | pointT *point; | 
| 2209 |  |  | int k; | 
| 2210 |  |  | realT dist; | 
| 2211 |  |  |  | 
| 2212 |  |  | facet->visitid= qh visit_id; | 
| 2213 |  |  | if (qh PRINTnoplanes || (facet->visible && qh NEWfacets)) | 
| 2214 |  |  | return; | 
| 2215 |  |  | FOREACHridge_(facet->ridges) { | 
| 2216 |  |  | neighbor= otherfacet_(ridge, facet); | 
| 2217 |  |  | if (neighbor->visitid == qh visit_id) | 
| 2218 |  |  | continue; | 
| 2219 |  |  | if (qh PRINTtransparent && !neighbor->good) | 
| 2220 |  |  | continue; | 
| 2221 |  |  | if (qh DOintersections) | 
| 2222 |  |  | qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color); | 
| 2223 |  |  | else { | 
| 2224 |  |  | if (qh DROPdim >= 0) | 
| 2225 |  |  | fprintf(fp, "OFF 3 1 1 # f%d\n", facet->id); | 
| 2226 |  |  | else { | 
| 2227 |  |  | qh printoutvar++; | 
| 2228 |  |  | fprintf (fp, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id); | 
| 2229 |  |  | } | 
| 2230 |  |  | FOREACHvertex_(ridge->vertices) { | 
| 2231 |  |  | zinc_(Zdistio); | 
| 2232 |  |  | qh_distplane(vertex->point,facet, &dist); | 
| 2233 |  |  | point=qh_projectpoint(vertex->point,facet, dist); | 
| 2234 |  |  | for(k= 0; k < qh hull_dim; k++) { | 
| 2235 |  |  | if (k != qh DROPdim) | 
| 2236 |  |  | fprintf(fp, "%8.4g ", point[k]); | 
| 2237 |  |  | } | 
| 2238 |  |  | fprintf (fp, "\n"); | 
| 2239 |  |  | qh_memfree (point, qh normal_size); | 
| 2240 |  |  | } | 
| 2241 |  |  | if (qh DROPdim >= 0) | 
| 2242 |  |  | fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]); | 
| 2243 |  |  | } | 
| 2244 |  |  | } | 
| 2245 |  |  | } /* printfacet4geom_nonsimplicial */ | 
| 2246 |  |  |  | 
| 2247 |  |  |  | 
| 2248 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2249 |  |  | >-------------------------------</a><a name="printfacet4geom_simplicial">-</a> | 
| 2250 |  |  |  | 
| 2251 |  |  | qh_printfacet4geom_simplicial( fp, facet, color ) | 
| 2252 |  |  | print Geomview 4OFF file for a 4d simplicial facet | 
| 2253 |  |  | prints triangles for unvisited neighbors (qh.visit_id) | 
| 2254 |  |  |  | 
| 2255 |  |  | notes: | 
| 2256 |  |  | must agree with printend4geom() | 
| 2257 |  |  | */ | 
| 2258 |  |  | void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) { | 
| 2259 |  |  | setT *vertices; | 
| 2260 |  |  | facetT *neighbor, **neighborp; | 
| 2261 |  |  | vertexT *vertex, **vertexp; | 
| 2262 |  |  | int k; | 
| 2263 |  |  |  | 
| 2264 |  |  | facet->visitid= qh visit_id; | 
| 2265 |  |  | if (qh PRINTnoplanes || (facet->visible && qh NEWfacets)) | 
| 2266 |  |  | return; | 
| 2267 |  |  | FOREACHneighbor_(facet) { | 
| 2268 |  |  | if (neighbor->visitid == qh visit_id) | 
| 2269 |  |  | continue; | 
| 2270 |  |  | if (qh PRINTtransparent && !neighbor->good) | 
| 2271 |  |  | continue; | 
| 2272 |  |  | vertices= qh_setnew_delnthsorted (facet->vertices, qh hull_dim, | 
| 2273 |  |  | SETindex_(facet->neighbors, neighbor), 0); | 
| 2274 |  |  | if (qh DOintersections) | 
| 2275 |  |  | qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color); | 
| 2276 |  |  | else { | 
| 2277 |  |  | if (qh DROPdim >= 0) | 
| 2278 |  |  | fprintf(fp, "OFF 3 1 1 # ridge between f%d f%d\n", | 
| 2279 |  |  | facet->id, neighbor->id); | 
| 2280 |  |  | else { | 
| 2281 |  |  | qh printoutvar++; | 
| 2282 |  |  | fprintf (fp, "# ridge between f%d f%d\n", facet->id, neighbor->id); | 
| 2283 |  |  | } | 
| 2284 |  |  | FOREACHvertex_(vertices) { | 
| 2285 |  |  | for(k= 0; k < qh hull_dim; k++) { | 
| 2286 |  |  | if (k != qh DROPdim) | 
| 2287 |  |  | fprintf(fp, "%8.4g ", vertex->point[k]); | 
| 2288 |  |  | } | 
| 2289 |  |  | fprintf (fp, "\n"); | 
| 2290 |  |  | } | 
| 2291 |  |  | if (qh DROPdim >= 0) | 
| 2292 |  |  | fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]); | 
| 2293 |  |  | } | 
| 2294 |  |  | qh_setfree(&vertices); | 
| 2295 |  |  | } | 
| 2296 |  |  | } /* printfacet4geom_simplicial */ | 
| 2297 |  |  |  | 
| 2298 |  |  |  | 
| 2299 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2300 |  |  | >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a> | 
| 2301 |  |  |  | 
| 2302 |  |  | qh_printfacetNvertex_nonsimplicial( fp, facet, id, format ) | 
| 2303 |  |  | print vertices for an N-d non-simplicial facet | 
| 2304 |  |  | triangulates each ridge to the id | 
| 2305 |  |  | */ | 
| 2306 |  |  | void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, int format) { | 
| 2307 |  |  | vertexT *vertex, **vertexp; | 
| 2308 |  |  | ridgeT *ridge, **ridgep; | 
| 2309 |  |  |  | 
| 2310 |  |  | if (facet->visible && qh NEWfacets) | 
| 2311 |  |  | return; | 
| 2312 |  |  | FOREACHridge_(facet->ridges) { | 
| 2313 |  |  | if (format == qh_PRINTtriangles) | 
| 2314 |  |  | fprintf(fp, "%d ", qh hull_dim); | 
| 2315 |  |  | fprintf(fp, "%d ", id); | 
| 2316 |  |  | if ((ridge->top == facet) ^ qh_ORIENTclock) { | 
| 2317 |  |  | FOREACHvertex_(ridge->vertices) | 
| 2318 |  |  | fprintf(fp, "%d ", qh_pointid(vertex->point)); | 
| 2319 |  |  | }else { | 
| 2320 |  |  | FOREACHvertexreverse12_(ridge->vertices) | 
| 2321 |  |  | fprintf(fp, "%d ", qh_pointid(vertex->point)); | 
| 2322 |  |  | } | 
| 2323 |  |  | fprintf(fp, "\n"); | 
| 2324 |  |  | } | 
| 2325 |  |  | } /* printfacetNvertex_nonsimplicial */ | 
| 2326 |  |  |  | 
| 2327 |  |  |  | 
| 2328 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2329 |  |  | >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a> | 
| 2330 |  |  |  | 
| 2331 |  |  | qh_printfacetNvertex_simplicial( fp, facet, format ) | 
| 2332 |  |  | print vertices for an N-d simplicial facet | 
| 2333 |  |  | prints vertices for non-simplicial facets | 
| 2334 |  |  | 2-d facets (orientation preserved by qh_mergefacet2d) | 
| 2335 |  |  | PRINToff ('o') for 4-d and higher | 
| 2336 |  |  | */ | 
| 2337 |  |  | void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, int format) { | 
| 2338 |  |  | vertexT *vertex, **vertexp; | 
| 2339 |  |  |  | 
| 2340 |  |  | if (format == qh_PRINToff || format == qh_PRINTtriangles) | 
| 2341 |  |  | fprintf (fp, "%d ", qh_setsize (facet->vertices)); | 
| 2342 |  |  | if ((facet->toporient ^ qh_ORIENTclock) | 
| 2343 |  |  | || (qh hull_dim > 2 && !facet->simplicial)) { | 
| 2344 |  |  | FOREACHvertex_(facet->vertices) | 
| 2345 |  |  | fprintf(fp, "%d ", qh_pointid(vertex->point)); | 
| 2346 |  |  | }else { | 
| 2347 |  |  | FOREACHvertexreverse12_(facet->vertices) | 
| 2348 |  |  | fprintf(fp, "%d ", qh_pointid(vertex->point)); | 
| 2349 |  |  | } | 
| 2350 |  |  | fprintf(fp, "\n"); | 
| 2351 |  |  | } /* printfacetNvertex_simplicial */ | 
| 2352 |  |  |  | 
| 2353 |  |  |  | 
| 2354 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2355 |  |  | >-------------------------------</a><a name="printfacetheader">-</a> | 
| 2356 |  |  |  | 
| 2357 |  |  | qh_printfacetheader( fp, facet ) | 
| 2358 |  |  | prints header fields of a facet to fp | 
| 2359 |  |  |  | 
| 2360 |  |  | notes: | 
| 2361 |  |  | for 'f' output and debugging | 
| 2362 |  |  | */ | 
| 2363 |  |  | void qh_printfacetheader(FILE *fp, facetT *facet) { | 
| 2364 |  |  | pointT *point, **pointp, *furthest; | 
| 2365 |  |  | facetT *neighbor, **neighborp; | 
| 2366 |  |  | realT dist; | 
| 2367 |  |  |  | 
| 2368 |  |  | if (facet == qh_MERGEridge) { | 
| 2369 |  |  | fprintf (fp, " MERGEridge\n"); | 
| 2370 |  |  | return; | 
| 2371 |  |  | }else if (facet == qh_DUPLICATEridge) { | 
| 2372 |  |  | fprintf (fp, " DUPLICATEridge\n"); | 
| 2373 |  |  | return; | 
| 2374 |  |  | }else if (!facet) { | 
| 2375 |  |  | fprintf (fp, " NULLfacet\n"); | 
| 2376 |  |  | return; | 
| 2377 |  |  | } | 
| 2378 |  |  | qh old_randomdist= qh RANDOMdist; | 
| 2379 |  |  | qh RANDOMdist= False; | 
| 2380 |  |  | fprintf(fp, "- f%d\n", facet->id); | 
| 2381 |  |  | fprintf(fp, "    - flags:"); | 
| 2382 |  |  | if (facet->toporient) | 
| 2383 |  |  | fprintf(fp, " top"); | 
| 2384 |  |  | else | 
| 2385 |  |  | fprintf(fp, " bottom"); | 
| 2386 |  |  | if (facet->simplicial) | 
| 2387 |  |  | fprintf(fp, " simplicial"); | 
| 2388 |  |  | if (facet->tricoplanar) | 
| 2389 |  |  | fprintf(fp, " tricoplanar"); | 
| 2390 |  |  | if (facet->upperdelaunay) | 
| 2391 |  |  | fprintf(fp, " upperDelaunay"); | 
| 2392 |  |  | if (facet->visible) | 
| 2393 |  |  | fprintf(fp, " visible"); | 
| 2394 |  |  | if (facet->newfacet) | 
| 2395 |  |  | fprintf(fp, " new"); | 
| 2396 |  |  | if (facet->tested) | 
| 2397 |  |  | fprintf(fp, " tested"); | 
| 2398 |  |  | if (!facet->good) | 
| 2399 |  |  | fprintf(fp, " notG"); | 
| 2400 |  |  | if (facet->seen) | 
| 2401 |  |  | fprintf(fp, " seen"); | 
| 2402 |  |  | if (facet->coplanar) | 
| 2403 |  |  | fprintf(fp, " coplanar"); | 
| 2404 |  |  | if (facet->mergehorizon) | 
| 2405 |  |  | fprintf(fp, " mergehorizon"); | 
| 2406 |  |  | if (facet->keepcentrum) | 
| 2407 |  |  | fprintf(fp, " keepcentrum"); | 
| 2408 |  |  | if (facet->dupridge) | 
| 2409 |  |  | fprintf(fp, " dupridge"); | 
| 2410 |  |  | if (facet->mergeridge && !facet->mergeridge2) | 
| 2411 |  |  | fprintf(fp, " mergeridge1"); | 
| 2412 |  |  | if (facet->mergeridge2) | 
| 2413 |  |  | fprintf(fp, " mergeridge2"); | 
| 2414 |  |  | if (facet->newmerge) | 
| 2415 |  |  | fprintf(fp, " newmerge"); | 
| 2416 |  |  | if (facet->flipped) | 
| 2417 |  |  | fprintf(fp, " flipped"); | 
| 2418 |  |  | if (facet->notfurthest) | 
| 2419 |  |  | fprintf(fp, " notfurthest"); | 
| 2420 |  |  | if (facet->degenerate) | 
| 2421 |  |  | fprintf(fp, " degenerate"); | 
| 2422 |  |  | if (facet->redundant) | 
| 2423 |  |  | fprintf(fp, " redundant"); | 
| 2424 |  |  | fprintf(fp, "\n"); | 
| 2425 |  |  | if (facet->isarea) | 
| 2426 |  |  | fprintf(fp, "    - area: %2.2g\n", facet->f.area); | 
| 2427 |  |  | else if (qh NEWfacets && facet->visible && facet->f.replace) | 
| 2428 |  |  | fprintf(fp, "    - replacement: f%d\n", facet->f.replace->id); | 
| 2429 |  |  | else if (facet->newfacet) { | 
| 2430 |  |  | if (facet->f.samecycle && facet->f.samecycle != facet) | 
| 2431 |  |  | fprintf(fp, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id); | 
| 2432 |  |  | }else if (facet->tricoplanar /* !isarea */) { | 
| 2433 |  |  | if (facet->f.triowner) | 
| 2434 |  |  | fprintf(fp, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id); | 
| 2435 |  |  | }else if (facet->f.newcycle) | 
| 2436 |  |  | fprintf(fp, "    - was horizon to f%d\n", facet->f.newcycle->id); | 
| 2437 |  |  | if (facet->nummerge) | 
| 2438 |  |  | fprintf(fp, "    - merges: %d\n", facet->nummerge); | 
| 2439 |  |  | qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1); | 
| 2440 |  |  | fprintf(fp, "    - offset: %10.7g\n", facet->offset); | 
| 2441 |  |  | if (qh CENTERtype == qh_ASvoronoi || facet->center) | 
| 2442 |  |  | qh_printcenter (fp, qh_PRINTfacets, "    - center: ", facet); | 
| 2443 |  |  | #if qh_MAXoutside | 
| 2444 |  |  | if (facet->maxoutside > qh DISTround) | 
| 2445 |  |  | fprintf(fp, "    - maxoutside: %10.7g\n", facet->maxoutside); | 
| 2446 |  |  | #endif | 
| 2447 |  |  | if (!SETempty_(facet->outsideset)) { | 
| 2448 |  |  | furthest= (pointT*)qh_setlast(facet->outsideset); | 
| 2449 |  |  | if (qh_setsize (facet->outsideset) < 6) { | 
| 2450 |  |  | fprintf(fp, "    - outside set (furthest p%d):\n", qh_pointid(furthest)); | 
| 2451 |  |  | FOREACHpoint_(facet->outsideset) | 
| 2452 |  |  | qh_printpoint(fp, "     ", point); | 
| 2453 |  |  | }else if (qh_setsize (facet->outsideset) < 21) { | 
| 2454 |  |  | qh_printpoints(fp, "    - outside set:", facet->outsideset); | 
| 2455 |  |  | }else { | 
| 2456 |  |  | fprintf(fp, "    - outside set:  %d points.", qh_setsize(facet->outsideset)); | 
| 2457 |  |  | qh_printpoint(fp, "  Furthest", furthest); | 
| 2458 |  |  | } | 
| 2459 |  |  | #if !qh_COMPUTEfurthest | 
| 2460 |  |  | fprintf(fp, "    - furthest distance= %2.2g\n", facet->furthestdist); | 
| 2461 |  |  | #endif | 
| 2462 |  |  | } | 
| 2463 |  |  | if (!SETempty_(facet->coplanarset)) { | 
| 2464 |  |  | furthest= (pointT*)qh_setlast(facet->coplanarset); | 
| 2465 |  |  | if (qh_setsize (facet->coplanarset) < 6) { | 
| 2466 |  |  | fprintf(fp, "    - coplanar set (furthest p%d):\n", qh_pointid(furthest)); | 
| 2467 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 2468 |  |  | qh_printpoint(fp, "     ", point); | 
| 2469 |  |  | }else if (qh_setsize (facet->coplanarset) < 21) { | 
| 2470 |  |  | qh_printpoints(fp, "    - coplanar set:", facet->coplanarset); | 
| 2471 |  |  | }else { | 
| 2472 |  |  | fprintf(fp, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset)); | 
| 2473 |  |  | qh_printpoint(fp, "  Furthest", furthest); | 
| 2474 |  |  | } | 
| 2475 |  |  | zinc_(Zdistio); | 
| 2476 |  |  | qh_distplane (furthest, facet, &dist); | 
| 2477 |  |  | fprintf(fp, "      furthest distance= %2.2g\n", dist); | 
| 2478 |  |  | } | 
| 2479 |  |  | qh_printvertices (fp, "    - vertices:", facet->vertices); | 
| 2480 |  |  | fprintf(fp, "    - neighboring facets: "); | 
| 2481 |  |  | FOREACHneighbor_(facet) { | 
| 2482 |  |  | if (neighbor == qh_MERGEridge) | 
| 2483 |  |  | fprintf(fp, " MERGE"); | 
| 2484 |  |  | else if (neighbor == qh_DUPLICATEridge) | 
| 2485 |  |  | fprintf(fp, " DUP"); | 
| 2486 |  |  | else | 
| 2487 |  |  | fprintf(fp, " f%d", neighbor->id); | 
| 2488 |  |  | } | 
| 2489 |  |  | fprintf(fp, "\n"); | 
| 2490 |  |  | qh RANDOMdist= qh old_randomdist; | 
| 2491 |  |  | } /* printfacetheader */ | 
| 2492 |  |  |  | 
| 2493 |  |  |  | 
| 2494 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2495 |  |  | >-------------------------------</a><a name="printfacetridges">-</a> | 
| 2496 |  |  |  | 
| 2497 |  |  | qh_printfacetridges( fp, facet ) | 
| 2498 |  |  | prints ridges of a facet to fp | 
| 2499 |  |  |  | 
| 2500 |  |  | notes: | 
| 2501 |  |  | ridges printed in neighbor order | 
| 2502 |  |  | assumes the ridges exist | 
| 2503 |  |  | for 'f' output | 
| 2504 |  |  | */ | 
| 2505 |  |  | void qh_printfacetridges(FILE *fp, facetT *facet) { | 
| 2506 |  |  | facetT *neighbor, **neighborp; | 
| 2507 |  |  | ridgeT *ridge, **ridgep; | 
| 2508 |  |  | int numridges= 0; | 
| 2509 |  |  |  | 
| 2510 |  |  |  | 
| 2511 |  |  | if (facet->visible && qh NEWfacets) { | 
| 2512 |  |  | fprintf(fp, "    - ridges (ids may be garbage):"); | 
| 2513 |  |  | FOREACHridge_(facet->ridges) | 
| 2514 |  |  | fprintf(fp, " r%d", ridge->id); | 
| 2515 |  |  | fprintf(fp, "\n"); | 
| 2516 |  |  | }else { | 
| 2517 |  |  | fprintf(fp, "    - ridges:\n"); | 
| 2518 |  |  | FOREACHridge_(facet->ridges) | 
| 2519 |  |  | ridge->seen= False; | 
| 2520 |  |  | if (qh hull_dim == 3) { | 
| 2521 |  |  | ridge= SETfirstt_(facet->ridges, ridgeT); | 
| 2522 |  |  | while (ridge && !ridge->seen) { | 
| 2523 |  |  | ridge->seen= True; | 
| 2524 |  |  | qh_printridge(fp, ridge); | 
| 2525 |  |  | numridges++; | 
| 2526 |  |  | ridge= qh_nextridge3d (ridge, facet, NULL); | 
| 2527 |  |  | } | 
| 2528 |  |  | }else { | 
| 2529 |  |  | FOREACHneighbor_(facet) { | 
| 2530 |  |  | FOREACHridge_(facet->ridges) { | 
| 2531 |  |  | if (otherfacet_(ridge,facet) == neighbor) { | 
| 2532 |  |  | ridge->seen= True; | 
| 2533 |  |  | qh_printridge(fp, ridge); | 
| 2534 |  |  | numridges++; | 
| 2535 |  |  | } | 
| 2536 |  |  | } | 
| 2537 |  |  | } | 
| 2538 |  |  | } | 
| 2539 |  |  | if (numridges != qh_setsize (facet->ridges)) { | 
| 2540 |  |  | fprintf (fp, "     - all ridges:"); | 
| 2541 |  |  | FOREACHridge_(facet->ridges) | 
| 2542 |  |  | fprintf (fp, " r%d", ridge->id); | 
| 2543 |  |  | fprintf (fp, "\n"); | 
| 2544 |  |  | } | 
| 2545 |  |  | FOREACHridge_(facet->ridges) { | 
| 2546 |  |  | if (!ridge->seen) | 
| 2547 |  |  | qh_printridge(fp, ridge); | 
| 2548 |  |  | } | 
| 2549 |  |  | } | 
| 2550 |  |  | } /* printfacetridges */ | 
| 2551 |  |  |  | 
| 2552 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2553 |  |  | >-------------------------------</a><a name="printfacets">-</a> | 
| 2554 |  |  |  | 
| 2555 |  |  | qh_printfacets( fp, format, facetlist, facets, printall ) | 
| 2556 |  |  | prints facetlist and/or facet set in output format | 
| 2557 |  |  |  | 
| 2558 |  |  | notes: | 
| 2559 |  |  | also used for specialized formats ('FO' and summary) | 
| 2560 |  |  | turns off 'Rn' option since want actual numbers | 
| 2561 |  |  | */ | 
| 2562 |  |  | void qh_printfacets(FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) { | 
| 2563 |  |  | int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars; | 
| 2564 |  |  | facetT *facet, **facetp; | 
| 2565 |  |  | setT *vertices; | 
| 2566 |  |  | coordT *center; | 
| 2567 |  |  | realT outerplane, innerplane; | 
| 2568 |  |  |  | 
| 2569 |  |  | qh old_randomdist= qh RANDOMdist; | 
| 2570 |  |  | qh RANDOMdist= False; | 
| 2571 |  |  | if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff)) | 
| 2572 |  |  | fprintf (qh ferr, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n"); | 
| 2573 |  |  | if (format == qh_PRINTnone) | 
| 2574 |  |  | ; /* print nothing */ | 
| 2575 |  |  | else if (format == qh_PRINTaverage) { | 
| 2576 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 2577 |  |  | center= qh_getcenter (vertices); | 
| 2578 |  |  | fprintf (fp, "%d 1\n", qh hull_dim); | 
| 2579 |  |  | qh_printpointid (fp, NULL, qh hull_dim, center, -1); | 
| 2580 |  |  | qh_memfree (center, qh normal_size); | 
| 2581 |  |  | qh_settempfree (&vertices); | 
| 2582 |  |  | }else if (format == qh_PRINTextremes) { | 
| 2583 |  |  | if (qh DELAUNAY) | 
| 2584 |  |  | qh_printextremes_d (fp, facetlist, facets, printall); | 
| 2585 |  |  | else if (qh hull_dim == 2) | 
| 2586 |  |  | qh_printextremes_2d (fp, facetlist, facets, printall); | 
| 2587 |  |  | else | 
| 2588 |  |  | qh_printextremes (fp, facetlist, facets, printall); | 
| 2589 |  |  | }else if (format == qh_PRINToptions) | 
| 2590 |  |  | fprintf(fp, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options); | 
| 2591 |  |  | else if (format == qh_PRINTpoints && !qh VORONOI) | 
| 2592 |  |  | qh_printpoints_out (fp, facetlist, facets, printall); | 
| 2593 |  |  | else if (format == qh_PRINTqhull) | 
| 2594 |  |  | fprintf (fp, "%s | %s\n", qh rbox_command, qh qhull_command); | 
| 2595 |  |  | else if (format == qh_PRINTsize) { | 
| 2596 |  |  | fprintf (fp, "0\n2 "); | 
| 2597 |  |  | fprintf (fp, qh_REAL_1, qh totarea); | 
| 2598 |  |  | fprintf (fp, qh_REAL_1, qh totvol); | 
| 2599 |  |  | fprintf (fp, "\n"); | 
| 2600 |  |  | }else if (format == qh_PRINTsummary) { | 
| 2601 |  |  | qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, | 
| 2602 |  |  | &totneighbors, &numridges, &numcoplanars, &numtricoplanars); | 
| 2603 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 2604 |  |  | fprintf (fp, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim, | 
| 2605 |  |  | qh num_points + qh_setsize (qh other_points), | 
| 2606 |  |  | qh num_vertices, qh num_facets - qh num_visible, | 
| 2607 |  |  | qh_setsize (vertices), numfacets, numcoplanars, | 
| 2608 |  |  | numfacets - numsimplicial, zzval_(Zdelvertextot), | 
| 2609 |  |  | numtricoplanars); | 
| 2610 |  |  | qh_settempfree (&vertices); | 
| 2611 |  |  | qh_outerinner (NULL, &outerplane, &innerplane); | 
| 2612 |  |  | fprintf (fp, qh_REAL_2n, outerplane, innerplane); | 
| 2613 |  |  | }else if (format == qh_PRINTvneighbors) | 
| 2614 |  |  | qh_printvneighbors (fp, facetlist, facets, printall); | 
| 2615 |  |  | else if (qh VORONOI && format == qh_PRINToff) | 
| 2616 |  |  | qh_printvoronoi (fp, format, facetlist, facets, printall); | 
| 2617 |  |  | else if (qh VORONOI && format == qh_PRINTgeom) { | 
| 2618 |  |  | qh_printbegin (fp, format, facetlist, facets, printall); | 
| 2619 |  |  | qh_printvoronoi (fp, format, facetlist, facets, printall); | 
| 2620 |  |  | qh_printend (fp, format, facetlist, facets, printall); | 
| 2621 |  |  | }else if (qh VORONOI | 
| 2622 |  |  | && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter)) | 
| 2623 |  |  | qh_printvdiagram (fp, format, facetlist, facets, printall); | 
| 2624 |  |  | else { | 
| 2625 |  |  | qh_printbegin (fp, format, facetlist, facets, printall); | 
| 2626 |  |  | FORALLfacet_(facetlist) | 
| 2627 |  |  | qh_printafacet (fp, format, facet, printall); | 
| 2628 |  |  | FOREACHfacet_(facets) | 
| 2629 |  |  | qh_printafacet (fp, format, facet, printall); | 
| 2630 |  |  | qh_printend (fp, format, facetlist, facets, printall); | 
| 2631 |  |  | } | 
| 2632 |  |  | qh RANDOMdist= qh old_randomdist; | 
| 2633 |  |  | } /* printfacets */ | 
| 2634 |  |  |  | 
| 2635 |  |  |  | 
| 2636 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2637 |  |  | >-------------------------------</a><a name="printhelp_degenerate">-</a> | 
| 2638 |  |  |  | 
| 2639 |  |  | qh_printhelp_degenerate( fp ) | 
| 2640 |  |  | prints descriptive message for precision error | 
| 2641 |  |  |  | 
| 2642 |  |  | notes: | 
| 2643 |  |  | no message if qh_QUICKhelp | 
| 2644 |  |  | */ | 
| 2645 |  |  | void qh_printhelp_degenerate(FILE *fp) { | 
| 2646 |  |  |  | 
| 2647 |  |  | if (qh MERGEexact || qh PREmerge || qh JOGGLEmax < REALmax/2) | 
| 2648 |  |  | fprintf(fp, "\n\ | 
| 2649 |  |  | A Qhull error has occurred.  Qhull should have corrected the above\n\ | 
| 2650 |  |  | precision error.  Please send the input and all of the output to\n\ | 
| 2651 |  |  | qhull_bug@qhull.org\n"); | 
| 2652 |  |  | else if (!qh_QUICKhelp) { | 
| 2653 |  |  | fprintf(fp, "\n\ | 
| 2654 |  |  | Precision problems were detected during construction of the convex hull.\n\ | 
| 2655 |  |  | This occurs because convex hull algorithms assume that calculations are\n\ | 
| 2656 |  |  | exact, but floating-point arithmetic has roundoff errors.\n\ | 
| 2657 |  |  | \n\ | 
| 2658 |  |  | To correct for precision problems, do not use 'Q0'.  By default, Qhull\n\ | 
| 2659 |  |  | selects 'C-0' or 'Qx' and merges non-convex facets.  With option 'QJ',\n\ | 
| 2660 |  |  | Qhull joggles the input to prevent precision problems.  See \"Imprecision\n\ | 
| 2661 |  |  | in Qhull\" (qh-impre.htm).\n\ | 
| 2662 |  |  | \n\ | 
| 2663 |  |  | If you use 'Q0', the output may include\n\ | 
| 2664 |  |  | coplanar ridges, concave ridges, and flipped facets.  In 4-d and higher,\n\ | 
| 2665 |  |  | Qhull may produce a ridge with four neighbors or two facets with the same \n\ | 
| 2666 |  |  | vertices.  Qhull reports these events when they occur.  It stops when a\n\ | 
| 2667 |  |  | concave ridge, flipped facet, or duplicate facet occurs.\n"); | 
| 2668 |  |  | #if REALfloat | 
| 2669 |  |  | fprintf (fp, "\ | 
| 2670 |  |  | \n\ | 
| 2671 |  |  | Qhull is currently using single precision arithmetic.  The following\n\ | 
| 2672 |  |  | will probably remove the precision problems:\n\ | 
| 2673 |  |  | - recompile qhull for double precision (#define REALfloat 0 in user.h).\n"); | 
| 2674 |  |  | #endif | 
| 2675 |  |  | if (qh DELAUNAY && !qh SCALElast && qh MAXabs_coord > 1e4) | 
| 2676 |  |  | fprintf( fp, "\ | 
| 2677 |  |  | \n\ | 
| 2678 |  |  | When computing the Delaunay triangulation of coordinates > 1.0,\n\ | 
| 2679 |  |  | - please use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n"); | 
| 2680 |  |  | if (qh DELAUNAY && !qh ATinfinity) | 
| 2681 |  |  | fprintf( fp, "\ | 
| 2682 |  |  | When computing the Delaunay triangulation:\n\ | 
| 2683 |  |  | - please use 'Qz' to add a point at-infinity.  This reduces precision problems.\n"); | 
| 2684 |  |  |  | 
| 2685 |  |  | fprintf(fp, "\ | 
| 2686 |  |  | \n\ | 
| 2687 |  |  | If you need triangular output:\n\ | 
| 2688 |  |  | - please use option 'Qt' to triangulate the output\n\ | 
| 2689 |  |  | - please use option 'QJ' to joggle the input points and remove precision errors\n\ | 
| 2690 |  |  | - please use option 'Ft'.  It triangulates non-simplicial facets with added points.\n\ | 
| 2691 |  |  | \n\ | 
| 2692 |  |  | If you must use 'Q0',\n\ | 
| 2693 |  |  | try one or more of the following options.  They can not guarantee an output.\n\ | 
| 2694 |  |  | - please use 'QbB' to scale the input to a cube.\n\ | 
| 2695 |  |  | - please use 'Po' to produce output and prevent partitioning for flipped facets\n\ | 
| 2696 |  |  | - please use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\ | 
| 2697 |  |  | - please use 'En' to specify a maximum roundoff error less than %2.2g.\n\ | 
| 2698 |  |  | - options 'Qf', 'Qbb', and 'QR0' may also help\n", | 
| 2699 |  |  | qh DISTround); | 
| 2700 |  |  | fprintf(fp, "\ | 
| 2701 |  |  | \n\ | 
| 2702 |  |  | To guarantee simplicial output:\n\ | 
| 2703 |  |  | - please use option 'Qt' to triangulate the output\n\ | 
| 2704 |  |  | - please use option 'QJ' to joggle the input points and remove precision errors\n\ | 
| 2705 |  |  | - please use option 'Ft' to triangulate the output by adding points\n\ | 
| 2706 |  |  | - please use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\ | 
| 2707 |  |  | "); | 
| 2708 |  |  | } | 
| 2709 |  |  | } /* printhelp_degenerate */ | 
| 2710 |  |  |  | 
| 2711 |  |  |  | 
| 2712 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2713 |  |  | >-------------------------------</a><a name="printhelp_singular">-</a> | 
| 2714 |  |  |  | 
| 2715 |  |  | qh_printhelp_singular( fp ) | 
| 2716 |  |  | prints descriptive message for singular input | 
| 2717 |  |  | */ | 
| 2718 |  |  | void qh_printhelp_singular(FILE *fp) { | 
| 2719 |  |  | facetT *facet; | 
| 2720 |  |  | vertexT *vertex, **vertexp; | 
| 2721 |  |  | realT min, max, *coord, dist; | 
| 2722 |  |  | int i,k; | 
| 2723 |  |  |  | 
| 2724 |  |  | fprintf(fp, "\n\ | 
| 2725 |  |  | The input to qhull appears to be less than %d dimensional, or a\n\ | 
| 2726 |  |  | computation has overflowed.\n\n\ | 
| 2727 |  |  | Qhull could not construct a clearly convex simplex from points:\n", | 
| 2728 |  |  | qh hull_dim); | 
| 2729 |  |  | qh_printvertexlist (fp, "", qh facet_list, NULL, qh_ALL); | 
| 2730 |  |  | if (!qh_QUICKhelp) | 
| 2731 |  |  | fprintf(fp, "\n\ | 
| 2732 |  |  | The center point is coplanar with a facet, or a vertex is coplanar\n\ | 
| 2733 |  |  | with a neighboring facet.  The maximum round off error for\n\ | 
| 2734 |  |  | computing distances is %2.2g.  The center point, facets and distances\n\ | 
| 2735 |  |  | to the center point are as follows:\n\n", qh DISTround); | 
| 2736 |  |  | qh_printpointid (fp, "center point", qh hull_dim, qh interior_point, -1); | 
| 2737 |  |  | fprintf (fp, "\n"); | 
| 2738 |  |  | FORALLfacets { | 
| 2739 |  |  | fprintf (fp, "facet"); | 
| 2740 |  |  | FOREACHvertex_(facet->vertices) | 
| 2741 |  |  | fprintf (fp, " p%d", qh_pointid(vertex->point)); | 
| 2742 |  |  | zinc_(Zdistio); | 
| 2743 |  |  | qh_distplane(qh interior_point, facet, &dist); | 
| 2744 |  |  | fprintf (fp, " distance= %4.2g\n", dist); | 
| 2745 |  |  | } | 
| 2746 |  |  | if (!qh_QUICKhelp) { | 
| 2747 |  |  | if (qh HALFspace) | 
| 2748 |  |  | fprintf (fp, "\n\ | 
| 2749 |  |  | These points are the dual of the given halfspaces.  They indicate that\n\ | 
| 2750 |  |  | the intersection is degenerate.\n"); | 
| 2751 |  |  | fprintf (fp,"\n\ | 
| 2752 |  |  | These points either have a maximum or minimum x-coordinate, or\n\ | 
| 2753 |  |  | they maximize the determinant for k coordinates.  Trial points\n\ | 
| 2754 |  |  | are first selected from points that maximize a coordinate.\n"); | 
| 2755 |  |  | if (qh hull_dim >= qh_INITIALmax) | 
| 2756 |  |  | fprintf (fp, "\n\ | 
| 2757 |  |  | Because of the high dimension, the min x-coordinate and max-coordinate\n\ | 
| 2758 |  |  | points are used if the determinant is non-zero.  Option 'Qs' will\n\ | 
| 2759 |  |  | do a better, though much slower, job.  Instead of 'Qs', you can change\n\ | 
| 2760 |  |  | the points by randomly rotating the input with 'QR0'.\n"); | 
| 2761 |  |  | } | 
| 2762 |  |  | fprintf (fp, "\nThe min and max coordinates for each dimension are:\n"); | 
| 2763 |  |  | for (k=0; k < qh hull_dim; k++) { | 
| 2764 |  |  | min= REALmax; | 
| 2765 |  |  | max= -REALmin; | 
| 2766 |  |  | for (i=qh num_points, coord= qh first_point+k; i--; coord += qh hull_dim) { | 
| 2767 |  |  | maximize_(max, *coord); | 
| 2768 |  |  | minimize_(min, *coord); | 
| 2769 |  |  | } | 
| 2770 |  |  | fprintf (fp, "  %d:  %8.4g  %8.4g  difference= %4.4g\n", k, min, max, max-min); | 
| 2771 |  |  | } | 
| 2772 |  |  | if (!qh_QUICKhelp) { | 
| 2773 |  |  | fprintf (fp, "\n\ | 
| 2774 |  |  | If the input should be full dimensional, you have several options that\n\ | 
| 2775 |  |  | may determine an initial simplex:\n\ | 
| 2776 |  |  | - use 'QJ'  to joggle the input and make it full dimensional\n\ | 
| 2777 |  |  | - use 'QbB' to scale the points to the unit cube\n\ | 
| 2778 |  |  | - use 'QR0' to randomly rotate the input for different maximum points\n\ | 
| 2779 |  |  | - use 'Qs'  to search all points for the initial simplex\n\ | 
| 2780 |  |  | - use 'En'  to specify a maximum roundoff error less than %2.2g.\n\ | 
| 2781 |  |  | - trace execution with 'T3' to see the determinant for each point.\n", | 
| 2782 |  |  | qh DISTround); | 
| 2783 |  |  | #if REALfloat | 
| 2784 |  |  | fprintf (fp, "\ | 
| 2785 |  |  | - recompile qhull for double precision (#define REALfloat 0 in qhull.h).\n"); | 
| 2786 |  |  | #endif | 
| 2787 |  |  | fprintf (fp, "\n\ | 
| 2788 |  |  | If the input is lower dimensional:\n\ | 
| 2789 |  |  | - use 'QJ' to joggle the input and make it full dimensional\n\ | 
| 2790 |  |  | - use 'Qbk:0Bk:0' to delete coordinate k from the input.  You should\n\ | 
| 2791 |  |  | pick the coordinate with the least range.  The hull will have the\n\ | 
| 2792 |  |  | correct topology.\n\ | 
| 2793 |  |  | - determine the flat containing the points, rotate the points\n\ | 
| 2794 |  |  | into a coordinate plane, and delete the other coordinates.\n\ | 
| 2795 |  |  | - add one or more points to make the input full dimensional.\n\ | 
| 2796 |  |  | "); | 
| 2797 |  |  | if (qh DELAUNAY && !qh ATinfinity) | 
| 2798 |  |  | fprintf (fp, "\n\n\ | 
| 2799 |  |  | This is a Delaunay triangulation and the input is co-circular or co-spherical:\n\ | 
| 2800 |  |  | - use 'Qz' to add a point \"at infinity\" (i.e., above the paraboloid)\n\ | 
| 2801 |  |  | - or use 'QJ' to joggle the input and avoid co-circular data\n"); | 
| 2802 |  |  | } | 
| 2803 |  |  | } /* printhelp_singular */ | 
| 2804 |  |  |  | 
| 2805 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2806 |  |  | >-------------------------------</a><a name="printhyperplaneintersection">-</a> | 
| 2807 |  |  |  | 
| 2808 |  |  | qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color ) | 
| 2809 |  |  | print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d | 
| 2810 |  |  | */ | 
| 2811 |  |  | void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2, | 
| 2812 |  |  | setT *vertices, realT color[3]) { | 
| 2813 |  |  | realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4]; | 
| 2814 |  |  | vertexT *vertex, **vertexp; | 
| 2815 |  |  | int i, k; | 
| 2816 |  |  | boolT nearzero1, nearzero2; | 
| 2817 |  |  |  | 
| 2818 |  |  | costheta= qh_getangle(facet1->normal, facet2->normal); | 
| 2819 |  |  | denominator= 1 - costheta * costheta; | 
| 2820 |  |  | i= qh_setsize(vertices); | 
| 2821 |  |  | if (qh hull_dim == 3) | 
| 2822 |  |  | fprintf(fp, "VECT 1 %d 1 %d 1 ", i, i); | 
| 2823 |  |  | else if (qh hull_dim == 4 && qh DROPdim >= 0) | 
| 2824 |  |  | fprintf(fp, "OFF 3 1 1 "); | 
| 2825 |  |  | else | 
| 2826 |  |  | qh printoutvar++; | 
| 2827 |  |  | fprintf (fp, "# intersect f%d f%d\n", facet1->id, facet2->id); | 
| 2828 |  |  | mindenom= 1 / (10.0 * qh MAXabs_coord); | 
| 2829 |  |  | FOREACHvertex_(vertices) { | 
| 2830 |  |  | zadd_(Zdistio, 2); | 
| 2831 |  |  | qh_distplane(vertex->point, facet1, &dist1); | 
| 2832 |  |  | qh_distplane(vertex->point, facet2, &dist2); | 
| 2833 |  |  | s= qh_divzero (-dist1 + costheta * dist2, denominator,mindenom,&nearzero1); | 
| 2834 |  |  | t= qh_divzero (-dist2 + costheta * dist1, denominator,mindenom,&nearzero2); | 
| 2835 |  |  | if (nearzero1 || nearzero2) | 
| 2836 |  |  | s= t= 0.0; | 
| 2837 |  |  | for(k= qh hull_dim; k--; ) | 
| 2838 |  |  | p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t; | 
| 2839 |  |  | if (qh PRINTdim <= 3) { | 
| 2840 |  |  | qh_projectdim3 (p, p); | 
| 2841 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]); | 
| 2842 |  |  | }else | 
| 2843 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]); | 
| 2844 |  |  | if (nearzero1+nearzero2) | 
| 2845 |  |  | fprintf (fp, "p%d (coplanar facets)\n", qh_pointid (vertex->point)); | 
| 2846 |  |  | else | 
| 2847 |  |  | fprintf (fp, "projected p%d\n", qh_pointid (vertex->point)); | 
| 2848 |  |  | } | 
| 2849 |  |  | if (qh hull_dim == 3) | 
| 2850 |  |  | fprintf(fp, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]); | 
| 2851 |  |  | else if (qh hull_dim == 4 && qh DROPdim >= 0) | 
| 2852 |  |  | fprintf(fp, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]); | 
| 2853 |  |  | } /* printhyperplaneintersection */ | 
| 2854 |  |  |  | 
| 2855 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2856 |  |  | >-------------------------------</a><a name="printline3geom">-</a> | 
| 2857 |  |  |  | 
| 2858 |  |  | qh_printline3geom( fp, pointA, pointB, color ) | 
| 2859 |  |  | prints a line as a VECT | 
| 2860 |  |  | prints 0's for qh.DROPdim | 
| 2861 |  |  |  | 
| 2862 |  |  | notes: | 
| 2863 |  |  | if pointA == pointB, | 
| 2864 |  |  | it's a 1 point VECT | 
| 2865 |  |  | */ | 
| 2866 |  |  | void qh_printline3geom (FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) { | 
| 2867 |  |  | int k; | 
| 2868 |  |  | realT pA[4], pB[4]; | 
| 2869 |  |  |  | 
| 2870 |  |  | qh_projectdim3(pointA, pA); | 
| 2871 |  |  | qh_projectdim3(pointB, pB); | 
| 2872 |  |  | if ((fabs(pA[0] - pB[0]) > 1e-3) || | 
| 2873 |  |  | (fabs(pA[1] - pB[1]) > 1e-3) || | 
| 2874 |  |  | (fabs(pA[2] - pB[2]) > 1e-3)) { | 
| 2875 |  |  | fprintf (fp, "VECT 1 2 1 2 1\n"); | 
| 2876 |  |  | for (k= 0; k < 3; k++) | 
| 2877 |  |  | fprintf (fp, "%8.4g ", pB[k]); | 
| 2878 |  |  | fprintf (fp, " # p%d\n", qh_pointid (pointB)); | 
| 2879 |  |  | }else | 
| 2880 |  |  | fprintf (fp, "VECT 1 1 1 1 1\n"); | 
| 2881 |  |  | for (k=0; k < 3; k++) | 
| 2882 |  |  | fprintf (fp, "%8.4g ", pA[k]); | 
| 2883 |  |  | fprintf (fp, " # p%d\n", qh_pointid (pointA)); | 
| 2884 |  |  | fprintf (fp, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]); | 
| 2885 |  |  | } | 
| 2886 |  |  |  | 
| 2887 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2888 |  |  | >-------------------------------</a><a name="printneighborhood">-</a> | 
| 2889 |  |  |  | 
| 2890 |  |  | qh_printneighborhood( fp, format, facetA, facetB, printall ) | 
| 2891 |  |  | print neighborhood of one or two facets | 
| 2892 |  |  |  | 
| 2893 |  |  | notes: | 
| 2894 |  |  | calls qh_findgood_all() | 
| 2895 |  |  | bumps qh.visit_id | 
| 2896 |  |  | */ | 
| 2897 |  |  | void qh_printneighborhood (FILE *fp, int format, facetT *facetA, facetT *facetB, boolT printall) { | 
| 2898 |  |  | facetT *neighbor, **neighborp, *facet; | 
| 2899 |  |  | setT *facets; | 
| 2900 |  |  |  | 
| 2901 |  |  | if (format == qh_PRINTnone) | 
| 2902 |  |  | return; | 
| 2903 |  |  | qh_findgood_all (qh facet_list); | 
| 2904 |  |  | if (facetA == facetB) | 
| 2905 |  |  | facetB= NULL; | 
| 2906 |  |  | facets= qh_settemp (2*(qh_setsize (facetA->neighbors)+1)); | 
| 2907 |  |  | qh visit_id++; | 
| 2908 |  |  | for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) { | 
| 2909 |  |  | if (facet->visitid != qh visit_id) { | 
| 2910 |  |  | facet->visitid= qh visit_id; | 
| 2911 |  |  | qh_setappend (&facets, facet); | 
| 2912 |  |  | } | 
| 2913 |  |  | FOREACHneighbor_(facet) { | 
| 2914 |  |  | if (neighbor->visitid == qh visit_id) | 
| 2915 |  |  | continue; | 
| 2916 |  |  | neighbor->visitid= qh visit_id; | 
| 2917 |  |  | if (printall || !qh_skipfacet (neighbor)) | 
| 2918 |  |  | qh_setappend (&facets, neighbor); | 
| 2919 |  |  | } | 
| 2920 |  |  | } | 
| 2921 |  |  | qh_printfacets (fp, format, NULL, facets, printall); | 
| 2922 |  |  | qh_settempfree (&facets); | 
| 2923 |  |  | } /* printneighborhood */ | 
| 2924 |  |  |  | 
| 2925 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2926 |  |  | >-------------------------------</a><a name="printpoint">-</a> | 
| 2927 |  |  |  | 
| 2928 |  |  | qh_printpoint( fp, string, point ) | 
| 2929 |  |  | qh_printpointid( fp, string, dim, point, id ) | 
| 2930 |  |  | prints the coordinates of a point | 
| 2931 |  |  |  | 
| 2932 |  |  | returns: | 
| 2933 |  |  | if string is defined | 
| 2934 |  |  | prints 'string p%d' (skips p%d if id=-1) | 
| 2935 |  |  |  | 
| 2936 |  |  | notes: | 
| 2937 |  |  | nop if point is NULL | 
| 2938 |  |  | prints id unless it is undefined (-1) | 
| 2939 |  |  | */ | 
| 2940 |  |  | void qh_printpoint(FILE *fp, char *string, pointT *point) { | 
| 2941 |  |  | int id= qh_pointid( point); | 
| 2942 |  |  |  | 
| 2943 |  |  | qh_printpointid( fp, string, qh hull_dim, point, id); | 
| 2944 |  |  | } /* printpoint */ | 
| 2945 |  |  |  | 
| 2946 |  |  | void qh_printpointid(FILE *fp, char *string, int dim, pointT *point, int id) { | 
| 2947 |  |  | int k; | 
| 2948 |  |  | realT r; /*bug fix*/ | 
| 2949 |  |  |  | 
| 2950 |  |  | if (!point) | 
| 2951 |  |  | return; | 
| 2952 |  |  | if (string) { | 
| 2953 |  |  | fputs (string, fp); | 
| 2954 |  |  | if (id != -1) | 
| 2955 |  |  | fprintf(fp, " p%d: ", id); | 
| 2956 |  |  | } | 
| 2957 |  |  | for(k= dim; k--; ) { | 
| 2958 |  |  | r= *point++; | 
| 2959 |  |  | if (string) | 
| 2960 |  |  | fprintf(fp, " %8.4g", r); | 
| 2961 |  |  | else | 
| 2962 |  |  | fprintf(fp, qh_REAL_1, r); | 
| 2963 |  |  | } | 
| 2964 |  |  | fprintf(fp, "\n"); | 
| 2965 |  |  | } /* printpointid */ | 
| 2966 |  |  |  | 
| 2967 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2968 |  |  | >-------------------------------</a><a name="printpoint3">-</a> | 
| 2969 |  |  |  | 
| 2970 |  |  | qh_printpoint3( fp, point ) | 
| 2971 |  |  | prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates | 
| 2972 |  |  | */ | 
| 2973 |  |  | void qh_printpoint3 (FILE *fp, pointT *point) { | 
| 2974 |  |  | int k; | 
| 2975 |  |  | realT p[4]; | 
| 2976 |  |  |  | 
| 2977 |  |  | qh_projectdim3 (point, p); | 
| 2978 |  |  | for (k=0; k < 3; k++) | 
| 2979 |  |  | fprintf (fp, "%8.4g ", p[k]); | 
| 2980 |  |  | fprintf (fp, " # p%d\n", qh_pointid (point)); | 
| 2981 |  |  | } /* printpoint3 */ | 
| 2982 |  |  |  | 
| 2983 |  |  | /*---------------------------------------- | 
| 2984 |  |  | -printpoints- print pointids for a set of points starting at index | 
| 2985 |  |  | see geom.c | 
| 2986 |  |  | */ | 
| 2987 |  |  |  | 
| 2988 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 2989 |  |  | >-------------------------------</a><a name="printpoints_out">-</a> | 
| 2990 |  |  |  | 
| 2991 |  |  | qh_printpoints_out( fp, facetlist, facets, printall ) | 
| 2992 |  |  | prints vertices, coplanar/inside points, for facets by their point coordinates | 
| 2993 |  |  | allows qh.CDDoutput | 
| 2994 |  |  |  | 
| 2995 |  |  | notes: | 
| 2996 |  |  | same format as qhull input | 
| 2997 |  |  | if no coplanar/interior points, | 
| 2998 |  |  | same order as qh_printextremes | 
| 2999 |  |  | */ | 
| 3000 |  |  | void qh_printpoints_out (FILE *fp, facetT *facetlist, setT *facets, int printall) { | 
| 3001 |  |  | int allpoints= qh num_points + qh_setsize (qh other_points); | 
| 3002 |  |  | int numpoints=0, point_i, point_n; | 
| 3003 |  |  | setT *vertices, *points; | 
| 3004 |  |  | facetT *facet, **facetp; | 
| 3005 |  |  | pointT *point, **pointp; | 
| 3006 |  |  | vertexT *vertex, **vertexp; | 
| 3007 |  |  | int id; | 
| 3008 |  |  |  | 
| 3009 |  |  | points= qh_settemp (allpoints); | 
| 3010 |  |  | qh_setzero (points, 0, allpoints); | 
| 3011 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 3012 |  |  | FOREACHvertex_(vertices) { | 
| 3013 |  |  | id= qh_pointid (vertex->point); | 
| 3014 |  |  | if (id >= 0) | 
| 3015 |  |  | SETelem_(points, id)= vertex->point; | 
| 3016 |  |  | } | 
| 3017 |  |  | if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) { | 
| 3018 |  |  | FORALLfacet_(facetlist) { | 
| 3019 |  |  | if (!printall && qh_skipfacet(facet)) | 
| 3020 |  |  | continue; | 
| 3021 |  |  | FOREACHpoint_(facet->coplanarset) { | 
| 3022 |  |  | id= qh_pointid (point); | 
| 3023 |  |  | if (id >= 0) | 
| 3024 |  |  | SETelem_(points, id)= point; | 
| 3025 |  |  | } | 
| 3026 |  |  | } | 
| 3027 |  |  | FOREACHfacet_(facets) { | 
| 3028 |  |  | if (!printall && qh_skipfacet(facet)) | 
| 3029 |  |  | continue; | 
| 3030 |  |  | FOREACHpoint_(facet->coplanarset) { | 
| 3031 |  |  | id= qh_pointid (point); | 
| 3032 |  |  | if (id >= 0) | 
| 3033 |  |  | SETelem_(points, id)= point; | 
| 3034 |  |  | } | 
| 3035 |  |  | } | 
| 3036 |  |  | } | 
| 3037 |  |  | qh_settempfree (&vertices); | 
| 3038 |  |  | FOREACHpoint_i_(points) { | 
| 3039 |  |  | if (point) | 
| 3040 |  |  | numpoints++; | 
| 3041 |  |  | } | 
| 3042 |  |  | if (qh CDDoutput) | 
| 3043 |  |  | fprintf (fp, "%s | %s\nbegin\n%d %d real\n", qh rbox_command, | 
| 3044 |  |  | qh qhull_command, numpoints, qh hull_dim + 1); | 
| 3045 |  |  | else | 
| 3046 |  |  | fprintf (fp, "%d\n%d\n", qh hull_dim, numpoints); | 
| 3047 |  |  | FOREACHpoint_i_(points) { | 
| 3048 |  |  | if (point) { | 
| 3049 |  |  | if (qh CDDoutput) | 
| 3050 |  |  | fprintf (fp, "1 "); | 
| 3051 |  |  | qh_printpoint (fp, NULL, point); | 
| 3052 |  |  | } | 
| 3053 |  |  | } | 
| 3054 |  |  | if (qh CDDoutput) | 
| 3055 |  |  | fprintf (fp, "end\n"); | 
| 3056 |  |  | qh_settempfree (&points); | 
| 3057 |  |  | } /* printpoints_out */ | 
| 3058 |  |  |  | 
| 3059 |  |  |  | 
| 3060 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3061 |  |  | >-------------------------------</a><a name="printpointvect">-</a> | 
| 3062 |  |  |  | 
| 3063 |  |  | qh_printpointvect( fp, point, normal, center, radius, color ) | 
| 3064 |  |  | prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point | 
| 3065 |  |  | */ | 
| 3066 |  |  | void qh_printpointvect (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) { | 
| 3067 |  |  | realT diff[4], pointA[4]; | 
| 3068 |  |  | int k; | 
| 3069 |  |  |  | 
| 3070 |  |  | for (k= qh hull_dim; k--; ) { | 
| 3071 |  |  | if (center) | 
| 3072 |  |  | diff[k]= point[k]-center[k]; | 
| 3073 |  |  | else if (normal) | 
| 3074 |  |  | diff[k]= normal[k]; | 
| 3075 |  |  | else | 
| 3076 |  |  | diff[k]= 0; | 
| 3077 |  |  | } | 
| 3078 |  |  | if (center) | 
| 3079 |  |  | qh_normalize2 (diff, qh hull_dim, True, NULL, NULL); | 
| 3080 |  |  | for (k= qh hull_dim; k--; ) | 
| 3081 |  |  | pointA[k]= point[k]+diff[k] * radius; | 
| 3082 |  |  | qh_printline3geom (fp, point, pointA, color); | 
| 3083 |  |  | } /* printpointvect */ | 
| 3084 |  |  |  | 
| 3085 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3086 |  |  | >-------------------------------</a><a name="printpointvect2">-</a> | 
| 3087 |  |  |  | 
| 3088 |  |  | qh_printpointvect2( fp, point, normal, center, radius ) | 
| 3089 |  |  | prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point | 
| 3090 |  |  | */ | 
| 3091 |  |  | void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) { | 
| 3092 |  |  | realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0}; | 
| 3093 |  |  |  | 
| 3094 |  |  | qh_printpointvect (fp, point, normal, center, radius, red); | 
| 3095 |  |  | qh_printpointvect (fp, point, normal, center, -radius, yellow); | 
| 3096 |  |  | } /* printpointvect2 */ | 
| 3097 |  |  |  | 
| 3098 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3099 |  |  | >-------------------------------</a><a name="printridge">-</a> | 
| 3100 |  |  |  | 
| 3101 |  |  | qh_printridge( fp, ridge ) | 
| 3102 |  |  | prints the information in a ridge | 
| 3103 |  |  |  | 
| 3104 |  |  | notes: | 
| 3105 |  |  | for qh_printfacetridges() | 
| 3106 |  |  | */ | 
| 3107 |  |  | void qh_printridge(FILE *fp, ridgeT *ridge) { | 
| 3108 |  |  |  | 
| 3109 |  |  | fprintf(fp, "     - r%d", ridge->id); | 
| 3110 |  |  | if (ridge->tested) | 
| 3111 |  |  | fprintf (fp, " tested"); | 
| 3112 |  |  | if (ridge->nonconvex) | 
| 3113 |  |  | fprintf (fp, " nonconvex"); | 
| 3114 |  |  | fprintf (fp, "\n"); | 
| 3115 |  |  | qh_printvertices (fp, "           vertices:", ridge->vertices); | 
| 3116 |  |  | if (ridge->top && ridge->bottom) | 
| 3117 |  |  | fprintf(fp, "           between f%d and f%d\n", | 
| 3118 |  |  | ridge->top->id, ridge->bottom->id); | 
| 3119 |  |  | } /* printridge */ | 
| 3120 |  |  |  | 
| 3121 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3122 |  |  | >-------------------------------</a><a name="printspheres">-</a> | 
| 3123 |  |  |  | 
| 3124 |  |  | qh_printspheres( fp, vertices, radius ) | 
| 3125 |  |  | prints 3-d vertices as OFF spheres | 
| 3126 |  |  |  | 
| 3127 |  |  | notes: | 
| 3128 |  |  | inflated octahedron from Stuart Levy earth/mksphere2 | 
| 3129 |  |  | */ | 
| 3130 |  |  | void qh_printspheres(FILE *fp, setT *vertices, realT radius) { | 
| 3131 |  |  | vertexT *vertex, **vertexp; | 
| 3132 |  |  |  | 
| 3133 |  |  | qh printoutnum++; | 
| 3134 |  |  | fprintf (fp, "{appearance {-edge -normal normscale 0} {\n\ | 
| 3135 |  |  | INST geom {define vsphere OFF\n\ | 
| 3136 |  |  | 18 32 48\n\ | 
| 3137 |  |  | \n\ | 
| 3138 |  |  | 0 0 1\n\ | 
| 3139 |  |  | 1 0 0\n\ | 
| 3140 |  |  | 0 1 0\n\ | 
| 3141 |  |  | -1 0 0\n\ | 
| 3142 |  |  | 0 -1 0\n\ | 
| 3143 |  |  | 0 0 -1\n\ | 
| 3144 |  |  | 0.707107 0 0.707107\n\ | 
| 3145 |  |  | 0 -0.707107 0.707107\n\ | 
| 3146 |  |  | 0.707107 -0.707107 0\n\ | 
| 3147 |  |  | -0.707107 0 0.707107\n\ | 
| 3148 |  |  | -0.707107 -0.707107 0\n\ | 
| 3149 |  |  | 0 0.707107 0.707107\n\ | 
| 3150 |  |  | -0.707107 0.707107 0\n\ | 
| 3151 |  |  | 0.707107 0.707107 0\n\ | 
| 3152 |  |  | 0.707107 0 -0.707107\n\ | 
| 3153 |  |  | 0 0.707107 -0.707107\n\ | 
| 3154 |  |  | -0.707107 0 -0.707107\n\ | 
| 3155 |  |  | 0 -0.707107 -0.707107\n\ | 
| 3156 |  |  | \n\ | 
| 3157 |  |  | 3 0 6 11\n\ | 
| 3158 |  |  | 3 0 7 6 \n\ | 
| 3159 |  |  | 3 0 9 7 \n\ | 
| 3160 |  |  | 3 0 11 9\n\ | 
| 3161 |  |  | 3 1 6 8 \n\ | 
| 3162 |  |  | 3 1 8 14\n\ | 
| 3163 |  |  | 3 1 13 6\n\ | 
| 3164 |  |  | 3 1 14 13\n\ | 
| 3165 |  |  | 3 2 11 13\n\ | 
| 3166 |  |  | 3 2 12 11\n\ | 
| 3167 |  |  | 3 2 13 15\n\ | 
| 3168 |  |  | 3 2 15 12\n\ | 
| 3169 |  |  | 3 3 9 12\n\ | 
| 3170 |  |  | 3 3 10 9\n\ | 
| 3171 |  |  | 3 3 12 16\n\ | 
| 3172 |  |  | 3 3 16 10\n\ | 
| 3173 |  |  | 3 4 7 10\n\ | 
| 3174 |  |  | 3 4 8 7\n\ | 
| 3175 |  |  | 3 4 10 17\n\ | 
| 3176 |  |  | 3 4 17 8\n\ | 
| 3177 |  |  | 3 5 14 17\n\ | 
| 3178 |  |  | 3 5 15 14\n\ | 
| 3179 |  |  | 3 5 16 15\n\ | 
| 3180 |  |  | 3 5 17 16\n\ | 
| 3181 |  |  | 3 6 13 11\n\ | 
| 3182 |  |  | 3 7 8 6\n\ | 
| 3183 |  |  | 3 9 10 7\n\ | 
| 3184 |  |  | 3 11 12 9\n\ | 
| 3185 |  |  | 3 14 8 17\n\ | 
| 3186 |  |  | 3 15 13 14\n\ | 
| 3187 |  |  | 3 16 12 15\n\ | 
| 3188 |  |  | 3 17 10 16\n} transforms { TLIST\n"); | 
| 3189 |  |  | FOREACHvertex_(vertices) { | 
| 3190 |  |  | fprintf(fp, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n", | 
| 3191 |  |  | radius, vertex->id, radius, radius); | 
| 3192 |  |  | qh_printpoint3 (fp, vertex->point); | 
| 3193 |  |  | fprintf (fp, "1\n"); | 
| 3194 |  |  | } | 
| 3195 |  |  | fprintf (fp, "}}}\n"); | 
| 3196 |  |  | } /* printspheres */ | 
| 3197 |  |  |  | 
| 3198 |  |  |  | 
| 3199 |  |  | /*---------------------------------------------- | 
| 3200 |  |  | -printsummary- | 
| 3201 |  |  | see qhull.c | 
| 3202 |  |  | */ | 
| 3203 |  |  |  | 
| 3204 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3205 |  |  | >-------------------------------</a><a name="printvdiagram">-</a> | 
| 3206 |  |  |  | 
| 3207 |  |  | qh_printvdiagram( fp, format, facetlist, facets, printall ) | 
| 3208 |  |  | print voronoi diagram | 
| 3209 |  |  | # of pairs of input sites | 
| 3210 |  |  | #indices site1 site2 vertex1 ... | 
| 3211 |  |  |  | 
| 3212 |  |  | sites indexed by input point id | 
| 3213 |  |  | point 0 is the first input point | 
| 3214 |  |  | vertices indexed by 'o' and 'p' order | 
| 3215 |  |  | vertex 0 is the 'vertex-at-infinity' | 
| 3216 |  |  | vertex 1 is the first Voronoi vertex | 
| 3217 |  |  |  | 
| 3218 |  |  | see: | 
| 3219 |  |  | qh_printvoronoi() | 
| 3220 |  |  | qh_eachvoronoi_all() | 
| 3221 |  |  |  | 
| 3222 |  |  | notes: | 
| 3223 |  |  | if all facets are upperdelaunay, | 
| 3224 |  |  | prints upper hull (furthest-site Voronoi diagram) | 
| 3225 |  |  | */ | 
| 3226 |  |  | void qh_printvdiagram (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) { | 
| 3227 |  |  | setT *vertices; | 
| 3228 |  |  | int totcount, numcenters; | 
| 3229 |  |  | boolT islower; | 
| 3230 |  |  | qh_RIDGE innerouter= qh_RIDGEall; | 
| 3231 |  |  | printvridgeT printvridge= NULL; | 
| 3232 |  |  |  | 
| 3233 |  |  | if (format == qh_PRINTvertices) { | 
| 3234 |  |  | innerouter= qh_RIDGEall; | 
| 3235 |  |  | printvridge= qh_printvridge; | 
| 3236 |  |  | }else if (format == qh_PRINTinner) { | 
| 3237 |  |  | innerouter= qh_RIDGEinner; | 
| 3238 |  |  | printvridge= qh_printvnorm; | 
| 3239 |  |  | }else if (format == qh_PRINTouter) { | 
| 3240 |  |  | innerouter= qh_RIDGEouter; | 
| 3241 |  |  | printvridge= qh_printvnorm; | 
| 3242 |  |  | }else { | 
| 3243 |  |  | fprintf(qh ferr, "qh_printvdiagram: unknown print format %d.\n", format); | 
| 3244 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3245 |  |  | } | 
| 3246 |  |  | vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters); | 
| 3247 |  |  | totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False); | 
| 3248 |  |  | fprintf (fp, "%d\n", totcount); | 
| 3249 |  |  | totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/); | 
| 3250 |  |  | qh_settempfree (&vertices); | 
| 3251 |  |  | #if 0 | 
| 3252 |  |  | /* for testing qh_eachvoronoi_all */ | 
| 3253 |  |  | fprintf (fp, "\n"); | 
| 3254 |  |  | totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/); | 
| 3255 |  |  | fprintf (fp, "%d\n", totcount); | 
| 3256 |  |  | #endif | 
| 3257 |  |  | } /* printvdiagram */ | 
| 3258 |  |  |  | 
| 3259 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3260 |  |  | >-------------------------------</a><a name="printvdiagram2">-</a> | 
| 3261 |  |  |  | 
| 3262 |  |  | qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder ) | 
| 3263 |  |  | visit all pairs of input sites (vertices) for selected Voronoi vertices | 
| 3264 |  |  | vertices may include NULLs | 
| 3265 |  |  |  | 
| 3266 |  |  | innerouter: | 
| 3267 |  |  | qh_RIDGEall   print inner ridges (bounded) and outer ridges (unbounded) | 
| 3268 |  |  | qh_RIDGEinner print only inner ridges | 
| 3269 |  |  | qh_RIDGEouter print only outer ridges | 
| 3270 |  |  |  | 
| 3271 |  |  | inorder: | 
| 3272 |  |  | print 3-d Voronoi vertices in order | 
| 3273 |  |  |  | 
| 3274 |  |  | assumes: | 
| 3275 |  |  | qh_markvoronoi marked facet->visitid for Voronoi vertices | 
| 3276 |  |  | all facet->seen= False | 
| 3277 |  |  | all facet->seen2= True | 
| 3278 |  |  |  | 
| 3279 |  |  | returns: | 
| 3280 |  |  | total number of Voronoi ridges | 
| 3281 |  |  | if printvridge, | 
| 3282 |  |  | calls printvridge( fp, vertex, vertexA, centers) for each ridge | 
| 3283 |  |  | [see qh_eachvoronoi()] | 
| 3284 |  |  |  | 
| 3285 |  |  | see: | 
| 3286 |  |  | qh_eachvoronoi_all() | 
| 3287 |  |  | */ | 
| 3288 |  |  | int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) { | 
| 3289 |  |  | int totcount= 0; | 
| 3290 |  |  | int vertex_i, vertex_n; | 
| 3291 |  |  | vertexT *vertex; | 
| 3292 |  |  |  | 
| 3293 |  |  | FORALLvertices | 
| 3294 |  |  | vertex->seen= False; | 
| 3295 |  |  | FOREACHvertex_i_(vertices) { | 
| 3296 |  |  | if (vertex) { | 
| 3297 |  |  | if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex) | 
| 3298 |  |  | continue; | 
| 3299 |  |  | totcount += qh_eachvoronoi (fp, printvridge, vertex, !qh_ALL, innerouter, inorder); | 
| 3300 |  |  | } | 
| 3301 |  |  | } | 
| 3302 |  |  | return totcount; | 
| 3303 |  |  | } /* printvdiagram2 */ | 
| 3304 |  |  |  | 
| 3305 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3306 |  |  | >-------------------------------</a><a name="printvertex">-</a> | 
| 3307 |  |  |  | 
| 3308 |  |  | qh_printvertex( fp, vertex ) | 
| 3309 |  |  | prints the information in a vertex | 
| 3310 |  |  | */ | 
| 3311 |  |  | void qh_printvertex(FILE *fp, vertexT *vertex) { | 
| 3312 |  |  | pointT *point; | 
| 3313 |  |  | int k, count= 0; | 
| 3314 |  |  | facetT *neighbor, **neighborp; | 
| 3315 |  |  | realT r; /*bug fix*/ | 
| 3316 |  |  |  | 
| 3317 |  |  | if (!vertex) { | 
| 3318 |  |  | fprintf (fp, "  NULLvertex\n"); | 
| 3319 |  |  | return; | 
| 3320 |  |  | } | 
| 3321 |  |  | fprintf(fp, "- p%d (v%d):", qh_pointid(vertex->point), vertex->id); | 
| 3322 |  |  | point= vertex->point; | 
| 3323 |  |  | if (point) { | 
| 3324 |  |  | for(k= qh hull_dim; k--; ) { | 
| 3325 |  |  | r= *point++; | 
| 3326 |  |  | fprintf(fp, " %5.2g", r); | 
| 3327 |  |  | } | 
| 3328 |  |  | } | 
| 3329 |  |  | if (vertex->deleted) | 
| 3330 |  |  | fprintf(fp, " deleted"); | 
| 3331 |  |  | if (vertex->delridge) | 
| 3332 |  |  | fprintf (fp, " ridgedeleted"); | 
| 3333 |  |  | fprintf(fp, "\n"); | 
| 3334 |  |  | if (vertex->neighbors) { | 
| 3335 |  |  | fprintf(fp, "  neighbors:"); | 
| 3336 |  |  | FOREACHneighbor_(vertex) { | 
| 3337 |  |  | if (++count % 100 == 0) | 
| 3338 |  |  | fprintf (fp, "\n     "); | 
| 3339 |  |  | fprintf(fp, " f%d", neighbor->id); | 
| 3340 |  |  | } | 
| 3341 |  |  | fprintf(fp, "\n"); | 
| 3342 |  |  | } | 
| 3343 |  |  | } /* printvertex */ | 
| 3344 |  |  |  | 
| 3345 |  |  |  | 
| 3346 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3347 |  |  | >-------------------------------</a><a name="printvertexlist">-</a> | 
| 3348 |  |  |  | 
| 3349 |  |  | qh_printvertexlist( fp, string, facetlist, facets, printall ) | 
| 3350 |  |  | prints vertices used by a facetlist or facet set | 
| 3351 |  |  | tests qh_skipfacet() if !printall | 
| 3352 |  |  | */ | 
| 3353 |  |  | void qh_printvertexlist (FILE *fp, char* string, facetT *facetlist, | 
| 3354 |  |  | setT *facets, boolT printall) { | 
| 3355 |  |  | vertexT *vertex, **vertexp; | 
| 3356 |  |  | setT *vertices; | 
| 3357 |  |  |  | 
| 3358 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 3359 |  |  | fputs (string, fp); | 
| 3360 |  |  | FOREACHvertex_(vertices) | 
| 3361 |  |  | qh_printvertex(fp, vertex); | 
| 3362 |  |  | qh_settempfree (&vertices); | 
| 3363 |  |  | } /* printvertexlist */ | 
| 3364 |  |  |  | 
| 3365 |  |  |  | 
| 3366 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3367 |  |  | >-------------------------------</a><a name="printvertices">-</a> | 
| 3368 |  |  |  | 
| 3369 |  |  | qh_printvertices( fp, string, vertices ) | 
| 3370 |  |  | prints vertices in a set | 
| 3371 |  |  | */ | 
| 3372 |  |  | void qh_printvertices(FILE *fp, char* string, setT *vertices) { | 
| 3373 |  |  | vertexT *vertex, **vertexp; | 
| 3374 |  |  |  | 
| 3375 |  |  | fputs (string, fp); | 
| 3376 |  |  | FOREACHvertex_(vertices) | 
| 3377 |  |  | fprintf (fp, " p%d (v%d)", qh_pointid(vertex->point), vertex->id); | 
| 3378 |  |  | fprintf(fp, "\n"); | 
| 3379 |  |  | } /* printvertices */ | 
| 3380 |  |  |  | 
| 3381 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3382 |  |  | >-------------------------------</a><a name="printvneighbors">-</a> | 
| 3383 |  |  |  | 
| 3384 |  |  | qh_printvneighbors( fp, facetlist, facets, printall ) | 
| 3385 |  |  | print vertex neighbors of vertices in facetlist and facets ('FN') | 
| 3386 |  |  |  | 
| 3387 |  |  | notes: | 
| 3388 |  |  | qh_countfacets clears facet->visitid for non-printed facets | 
| 3389 |  |  |  | 
| 3390 |  |  | design: | 
| 3391 |  |  | collect facet count and related statistics | 
| 3392 |  |  | if necessary, build neighbor sets for each vertex | 
| 3393 |  |  | collect vertices in facetlist and facets | 
| 3394 |  |  | build a point array for point->vertex and point->coplanar facet | 
| 3395 |  |  | for each point | 
| 3396 |  |  | list vertex neighbors or coplanar facet | 
| 3397 |  |  | */ | 
| 3398 |  |  | void qh_printvneighbors (FILE *fp, facetT* facetlist, setT *facets, boolT printall) { | 
| 3399 |  |  | int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars; | 
| 3400 |  |  | setT *vertices, *vertex_points, *coplanar_points; | 
| 3401 |  |  | int numpoints= qh num_points + qh_setsize (qh other_points); | 
| 3402 |  |  | vertexT *vertex, **vertexp; | 
| 3403 |  |  | int vertex_i, vertex_n; | 
| 3404 |  |  | facetT *facet, **facetp, *neighbor, **neighborp; | 
| 3405 |  |  | pointT *point, **pointp; | 
| 3406 |  |  |  | 
| 3407 |  |  | qh_countfacets (facetlist, facets, printall, &numfacets, &numsimplicial, | 
| 3408 |  |  | &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */ | 
| 3409 |  |  | fprintf (fp, "%d\n", numpoints); | 
| 3410 |  |  | qh_vertexneighbors(); | 
| 3411 |  |  | vertices= qh_facetvertices (facetlist, facets, printall); | 
| 3412 |  |  | vertex_points= qh_settemp (numpoints); | 
| 3413 |  |  | coplanar_points= qh_settemp (numpoints); | 
| 3414 |  |  | qh_setzero (vertex_points, 0, numpoints); | 
| 3415 |  |  | qh_setzero (coplanar_points, 0, numpoints); | 
| 3416 |  |  | FOREACHvertex_(vertices) | 
| 3417 |  |  | qh_point_add (vertex_points, vertex->point, vertex); | 
| 3418 |  |  | FORALLfacet_(facetlist) { | 
| 3419 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 3420 |  |  | qh_point_add (coplanar_points, point, facet); | 
| 3421 |  |  | } | 
| 3422 |  |  | FOREACHfacet_(facets) { | 
| 3423 |  |  | FOREACHpoint_(facet->coplanarset) | 
| 3424 |  |  | qh_point_add (coplanar_points, point, facet); | 
| 3425 |  |  | } | 
| 3426 |  |  | FOREACHvertex_i_(vertex_points) { | 
| 3427 |  |  | if (vertex) { | 
| 3428 |  |  | numneighbors= qh_setsize (vertex->neighbors); | 
| 3429 |  |  | fprintf (fp, "%d", numneighbors); | 
| 3430 |  |  | if (qh hull_dim == 3) | 
| 3431 |  |  | qh_order_vertexneighbors (vertex); | 
| 3432 |  |  | else if (qh hull_dim >= 4) | 
| 3433 |  |  | qsort (SETaddr_(vertex->neighbors, facetT), numneighbors, | 
| 3434 |  |  | sizeof (facetT *), qh_compare_facetvisit); | 
| 3435 |  |  | FOREACHneighbor_(vertex) | 
| 3436 |  |  | fprintf (fp, " %d", | 
| 3437 |  |  | neighbor->visitid ? neighbor->visitid - 1 : - neighbor->id); | 
| 3438 |  |  | fprintf (fp, "\n"); | 
| 3439 |  |  | }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT))) | 
| 3440 |  |  | fprintf (fp, "1 %d\n", | 
| 3441 |  |  | facet->visitid ? facet->visitid - 1 : - facet->id); | 
| 3442 |  |  | else | 
| 3443 |  |  | fprintf (fp, "0\n"); | 
| 3444 |  |  | } | 
| 3445 |  |  | qh_settempfree (&coplanar_points); | 
| 3446 |  |  | qh_settempfree (&vertex_points); | 
| 3447 |  |  | qh_settempfree (&vertices); | 
| 3448 |  |  | } /* printvneighbors */ | 
| 3449 |  |  |  | 
| 3450 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3451 |  |  | >-------------------------------</a><a name="printvoronoi">-</a> | 
| 3452 |  |  |  | 
| 3453 |  |  | qh_printvoronoi( fp, format, facetlist, facets, printall ) | 
| 3454 |  |  | print voronoi diagram in 'o' or 'G' format | 
| 3455 |  |  | for 'o' format | 
| 3456 |  |  | prints voronoi centers for each facet and for infinity | 
| 3457 |  |  | for each vertex, lists ids of printed facets or infinity | 
| 3458 |  |  | assumes facetlist and facets are disjoint | 
| 3459 |  |  | for 'G' format | 
| 3460 |  |  | prints an OFF object | 
| 3461 |  |  | adds a 0 coordinate to center | 
| 3462 |  |  | prints infinity but does not list in vertices | 
| 3463 |  |  |  | 
| 3464 |  |  | see: | 
| 3465 |  |  | qh_printvdiagram() | 
| 3466 |  |  |  | 
| 3467 |  |  | notes: | 
| 3468 |  |  | if 'o', | 
| 3469 |  |  | prints a line for each point except "at-infinity" | 
| 3470 |  |  | if all facets are upperdelaunay, | 
| 3471 |  |  | reverses lower and upper hull | 
| 3472 |  |  | */ | 
| 3473 |  |  | void qh_printvoronoi (FILE *fp, int format, facetT *facetlist, setT *facets, boolT printall) { | 
| 3474 |  |  | int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n; | 
| 3475 |  |  | facetT *facet, **facetp, *neighbor, **neighborp; | 
| 3476 |  |  | setT *vertices; | 
| 3477 |  |  | vertexT *vertex; | 
| 3478 |  |  | boolT islower; | 
| 3479 |  |  | unsigned int numfacets= (unsigned int) qh num_facets; | 
| 3480 |  |  |  | 
| 3481 |  |  | vertices= qh_markvoronoi (facetlist, facets, printall, &islower, &numcenters); | 
| 3482 |  |  | FOREACHvertex_i_(vertices) { | 
| 3483 |  |  | if (vertex) { | 
| 3484 |  |  | numvertices++; | 
| 3485 |  |  | numneighbors = numinf = 0; | 
| 3486 |  |  | FOREACHneighbor_(vertex) { | 
| 3487 |  |  | if (neighbor->visitid == 0) | 
| 3488 |  |  | numinf= 1; | 
| 3489 |  |  | else if (neighbor->visitid < numfacets) | 
| 3490 |  |  | numneighbors++; | 
| 3491 |  |  | } | 
| 3492 |  |  | if (numinf && !numneighbors) { | 
| 3493 |  |  | SETelem_(vertices, vertex_i)= NULL; | 
| 3494 |  |  | numvertices--; | 
| 3495 |  |  | } | 
| 3496 |  |  | } | 
| 3497 |  |  | } | 
| 3498 |  |  | if (format == qh_PRINTgeom) | 
| 3499 |  |  | fprintf (fp, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n", | 
| 3500 |  |  | numcenters, numvertices); | 
| 3501 |  |  | else | 
| 3502 |  |  | fprintf (fp, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices)); | 
| 3503 |  |  | if (format == qh_PRINTgeom) { | 
| 3504 |  |  | for (k= qh hull_dim-1; k--; ) | 
| 3505 |  |  | fprintf (fp, qh_REAL_1, 0.0); | 
| 3506 |  |  | fprintf (fp, " 0 # infinity not used\n"); | 
| 3507 |  |  | }else { | 
| 3508 |  |  | for (k= qh hull_dim-1; k--; ) | 
| 3509 |  |  | fprintf (fp, qh_REAL_1, qh_INFINITE); | 
| 3510 |  |  | fprintf (fp, "\n"); | 
| 3511 |  |  | } | 
| 3512 |  |  | FORALLfacet_(facetlist) { | 
| 3513 |  |  | if (facet->visitid && facet->visitid < numfacets) { | 
| 3514 |  |  | if (format == qh_PRINTgeom) | 
| 3515 |  |  | fprintf (fp, "# %d f%d\n", vid++, facet->id); | 
| 3516 |  |  | qh_printcenter (fp, format, NULL, facet); | 
| 3517 |  |  | } | 
| 3518 |  |  | } | 
| 3519 |  |  | FOREACHfacet_(facets) { | 
| 3520 |  |  | if (facet->visitid && facet->visitid < numfacets) { | 
| 3521 |  |  | if (format == qh_PRINTgeom) | 
| 3522 |  |  | fprintf (fp, "# %d f%d\n", vid++, facet->id); | 
| 3523 |  |  | qh_printcenter (fp, format, NULL, facet); | 
| 3524 |  |  | } | 
| 3525 |  |  | } | 
| 3526 |  |  | FOREACHvertex_i_(vertices) { | 
| 3527 |  |  | numneighbors= 0; | 
| 3528 |  |  | numinf=0; | 
| 3529 |  |  | if (vertex) { | 
| 3530 |  |  | if (qh hull_dim == 3) | 
| 3531 |  |  | qh_order_vertexneighbors(vertex); | 
| 3532 |  |  | else if (qh hull_dim >= 4) | 
| 3533 |  |  | qsort (SETaddr_(vertex->neighbors, vertexT), | 
| 3534 |  |  | qh_setsize (vertex->neighbors), | 
| 3535 |  |  | sizeof (facetT *), qh_compare_facetvisit); | 
| 3536 |  |  | FOREACHneighbor_(vertex) { | 
| 3537 |  |  | if (neighbor->visitid == 0) | 
| 3538 |  |  | numinf= 1; | 
| 3539 |  |  | else if (neighbor->visitid < numfacets) | 
| 3540 |  |  | numneighbors++; | 
| 3541 |  |  | } | 
| 3542 |  |  | } | 
| 3543 |  |  | if (format == qh_PRINTgeom) { | 
| 3544 |  |  | if (vertex) { | 
| 3545 |  |  | fprintf (fp, "%d", numneighbors); | 
| 3546 |  |  | if (vertex) { | 
| 3547 |  |  | FOREACHneighbor_(vertex) { | 
| 3548 |  |  | if (neighbor->visitid && neighbor->visitid < numfacets) | 
| 3549 |  |  | fprintf (fp, " %d", neighbor->visitid); | 
| 3550 |  |  | } | 
| 3551 |  |  | } | 
| 3552 |  |  | fprintf (fp, " # p%d (v%d)\n", vertex_i, vertex->id); | 
| 3553 |  |  | }else | 
| 3554 |  |  | fprintf (fp, " # p%d is coplanar or isolated\n", vertex_i); | 
| 3555 |  |  | }else { | 
| 3556 |  |  | if (numinf) | 
| 3557 |  |  | numneighbors++; | 
| 3558 |  |  | fprintf (fp, "%d", numneighbors); | 
| 3559 |  |  | if (vertex) { | 
| 3560 |  |  | FOREACHneighbor_(vertex) { | 
| 3561 |  |  | if (neighbor->visitid == 0) { | 
| 3562 |  |  | if (numinf) { | 
| 3563 |  |  | numinf= 0; | 
| 3564 |  |  | fprintf (fp, " %d", neighbor->visitid); | 
| 3565 |  |  | } | 
| 3566 |  |  | }else if (neighbor->visitid < numfacets) | 
| 3567 |  |  | fprintf (fp, " %d", neighbor->visitid); | 
| 3568 |  |  | } | 
| 3569 |  |  | } | 
| 3570 |  |  | fprintf (fp, "\n"); | 
| 3571 |  |  | } | 
| 3572 |  |  | } | 
| 3573 |  |  | if (format == qh_PRINTgeom) | 
| 3574 |  |  | fprintf (fp, "}\n"); | 
| 3575 |  |  | qh_settempfree (&vertices); | 
| 3576 |  |  | } /* printvoronoi */ | 
| 3577 |  |  |  | 
| 3578 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3579 |  |  | >-------------------------------</a><a name="printvnorm">-</a> | 
| 3580 |  |  |  | 
| 3581 |  |  | qh_printvnorm( fp, vertex, vertexA, centers, unbounded ) | 
| 3582 |  |  | print one separating plane of the Voronoi diagram for a pair of input sites | 
| 3583 |  |  | unbounded==True if centers includes vertex-at-infinity | 
| 3584 |  |  |  | 
| 3585 |  |  | assumes: | 
| 3586 |  |  | qh_ASvoronoi and qh_vertexneighbors() already set | 
| 3587 |  |  |  | 
| 3588 |  |  | see: | 
| 3589 |  |  | qh_printvdiagram() | 
| 3590 |  |  | qh_eachvoronoi() | 
| 3591 |  |  | */ | 
| 3592 |  |  | void qh_printvnorm (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) { | 
| 3593 |  |  | pointT *normal; | 
| 3594 |  |  | realT offset; | 
| 3595 |  |  | int k; | 
| 3596 |  |  |  | 
| 3597 |  |  | normal= qh_detvnorm (vertex, vertexA, centers, &offset); | 
| 3598 |  |  | fprintf (fp, "%d %d %d ", | 
| 3599 |  |  | 2+qh hull_dim, qh_pointid (vertex->point), qh_pointid (vertexA->point)); | 
| 3600 |  |  | for (k= 0; k< qh hull_dim-1; k++) | 
| 3601 |  |  | fprintf (fp, qh_REAL_1, normal[k]); | 
| 3602 |  |  | fprintf (fp, qh_REAL_1, offset); | 
| 3603 |  |  | fprintf (fp, "\n"); | 
| 3604 |  |  | } /* printvnorm */ | 
| 3605 |  |  |  | 
| 3606 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3607 |  |  | >-------------------------------</a><a name="printvridge">-</a> | 
| 3608 |  |  |  | 
| 3609 |  |  | qh_printvridge( fp, vertex, vertexA, centers, unbounded ) | 
| 3610 |  |  | print one ridge of the Voronoi diagram for a pair of input sites | 
| 3611 |  |  | unbounded==True if centers includes vertex-at-infinity | 
| 3612 |  |  |  | 
| 3613 |  |  | see: | 
| 3614 |  |  | qh_printvdiagram() | 
| 3615 |  |  |  | 
| 3616 |  |  | notes: | 
| 3617 |  |  | the user may use a different function | 
| 3618 |  |  | */ | 
| 3619 |  |  | void qh_printvridge (FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) { | 
| 3620 |  |  | facetT *facet, **facetp; | 
| 3621 |  |  |  | 
| 3622 |  |  | fprintf (fp, "%d %d %d", qh_setsize (centers)+2, | 
| 3623 |  |  | qh_pointid (vertex->point), qh_pointid (vertexA->point)); | 
| 3624 |  |  | FOREACHfacet_(centers) | 
| 3625 |  |  | fprintf (fp, " %d", facet->visitid); | 
| 3626 |  |  | fprintf (fp, "\n"); | 
| 3627 |  |  | } /* printvridge */ | 
| 3628 |  |  |  | 
| 3629 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3630 |  |  | >-------------------------------</a><a name="projectdim3">-</a> | 
| 3631 |  |  |  | 
| 3632 |  |  | qh_projectdim3( source, destination ) | 
| 3633 |  |  | project 2-d 3-d or 4-d point to a 3-d point | 
| 3634 |  |  | uses qh.DROPdim and qh.hull_dim | 
| 3635 |  |  | source and destination may be the same | 
| 3636 |  |  |  | 
| 3637 |  |  | notes: | 
| 3638 |  |  | allocate 4 elements to destination just in case | 
| 3639 |  |  | */ | 
| 3640 |  |  | void qh_projectdim3 (pointT *source, pointT *destination) { | 
| 3641 |  |  | int i,k; | 
| 3642 |  |  |  | 
| 3643 |  |  | for (k= 0, i=0; k < qh hull_dim; k++) { | 
| 3644 |  |  | if (qh hull_dim == 4) { | 
| 3645 |  |  | if (k != qh DROPdim) | 
| 3646 |  |  | destination[i++]= source[k]; | 
| 3647 |  |  | }else if (k == qh DROPdim) | 
| 3648 |  |  | destination[i++]= 0; | 
| 3649 |  |  | else | 
| 3650 |  |  | destination[i++]= source[k]; | 
| 3651 |  |  | } | 
| 3652 |  |  | while (i < 3) | 
| 3653 |  |  | destination[i++]= 0.0; | 
| 3654 |  |  | } /* projectdim3 */ | 
| 3655 |  |  |  | 
| 3656 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3657 |  |  | >-------------------------------</a><a name="readfeasible">-</a> | 
| 3658 |  |  |  | 
| 3659 |  |  | qh_readfeasible( dim, remainder ) | 
| 3660 |  |  | read feasible point from remainder string and qh.fin | 
| 3661 |  |  |  | 
| 3662 |  |  | returns: | 
| 3663 |  |  | number of lines read from qh.fin | 
| 3664 |  |  | sets qh.FEASIBLEpoint with malloc'd coordinates | 
| 3665 |  |  |  | 
| 3666 |  |  | notes: | 
| 3667 |  |  | checks for qh.HALFspace | 
| 3668 |  |  | assumes dim > 1 | 
| 3669 |  |  |  | 
| 3670 |  |  | see: | 
| 3671 |  |  | qh_setfeasible | 
| 3672 |  |  | */ | 
| 3673 |  |  | int qh_readfeasible (int dim, char *remainder) { | 
| 3674 |  |  | boolT isfirst= True; | 
| 3675 |  |  | int linecount= 0, tokcount= 0; | 
| 3676 |  |  | char *s, *t, firstline[qh_MAXfirst+1]; | 
| 3677 |  |  | coordT *coords, value; | 
| 3678 |  |  |  | 
| 3679 |  |  | if (!qh HALFspace) { | 
| 3680 |  |  | fprintf  (qh ferr, "qhull input error: feasible point (dim 1 coords) is only valid for halfspace intersection\n"); | 
| 3681 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3682 |  |  | } | 
| 3683 |  |  | if (qh feasible_string) | 
| 3684 |  |  | fprintf  (qh ferr, "qhull input warning: feasible point (dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n"); | 
| 3685 |  |  | if (!(qh feasible_point= (coordT*)malloc (dim* sizeof(coordT)))) { | 
| 3686 |  |  | fprintf(qh ferr, "qhull error: insufficient memory for feasible point\n"); | 
| 3687 |  |  | qh_errexit(qh_ERRmem, NULL, NULL); | 
| 3688 |  |  | } | 
| 3689 |  |  | coords= qh feasible_point; | 
| 3690 |  |  | while ((s= (isfirst ?  remainder : fgets(firstline, qh_MAXfirst, qh fin)))) { | 
| 3691 |  |  | if (isfirst) | 
| 3692 |  |  | isfirst= False; | 
| 3693 |  |  | else | 
| 3694 |  |  | linecount++; | 
| 3695 |  |  | while (*s) { | 
| 3696 |  |  | while (isspace(*s)) | 
| 3697 |  |  | s++; | 
| 3698 |  |  | value= qh_strtod (s, &t); | 
| 3699 |  |  | if (s == t) | 
| 3700 |  |  | break; | 
| 3701 |  |  | s= t; | 
| 3702 |  |  | *(coords++)= value; | 
| 3703 |  |  | if (++tokcount == dim) { | 
| 3704 |  |  | while (isspace (*s)) | 
| 3705 |  |  | s++; | 
| 3706 |  |  | qh_strtod (s, &t); | 
| 3707 |  |  | if (s != t) { | 
| 3708 |  |  | fprintf (qh ferr, "qhull input error: coordinates for feasible point do not finish out the line: %s\n", | 
| 3709 |  |  | s); | 
| 3710 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3711 |  |  | } | 
| 3712 |  |  | return linecount; | 
| 3713 |  |  | } | 
| 3714 |  |  | } | 
| 3715 |  |  | } | 
| 3716 |  |  | fprintf (qh ferr, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n", | 
| 3717 |  |  | tokcount, dim); | 
| 3718 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3719 |  |  | return 0; | 
| 3720 |  |  | } /* readfeasible */ | 
| 3721 |  |  |  | 
| 3722 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 3723 |  |  | >-------------------------------</a><a name="readpoints">-</a> | 
| 3724 |  |  |  | 
| 3725 |  |  | qh_readpoints( numpoints, dimension, ismalloc ) | 
| 3726 |  |  | read points from qh.fin into qh.first_point, qh.num_points | 
| 3727 |  |  | qh.fin is lines of coordinates, one per vertex, first line number of points | 
| 3728 |  |  | if 'rbox D4', | 
| 3729 |  |  | gives message | 
| 3730 |  |  | if qh.ATinfinity, | 
| 3731 |  |  | adds point-at-infinity for Delaunay triangulations | 
| 3732 |  |  |  | 
| 3733 |  |  | returns: | 
| 3734 |  |  | number of points, array of point coordinates, dimension, ismalloc True | 
| 3735 |  |  | if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid | 
| 3736 |  |  | and clears qh.PROJECTdelaunay | 
| 3737 |  |  | if qh.HALFspace, reads optional feasible point, reads halfspaces, | 
| 3738 |  |  | converts to dual. | 
| 3739 |  |  |  | 
| 3740 |  |  | for feasible point in "cdd format" in 3-d: | 
| 3741 |  |  | 3 1 | 
| 3742 |  |  | coordinates | 
| 3743 |  |  | comments | 
| 3744 |  |  | begin | 
| 3745 |  |  | n 4 real/integer | 
| 3746 |  |  | ... | 
| 3747 |  |  | end | 
| 3748 |  |  |  | 
| 3749 |  |  | notes: | 
| 3750 |  |  | dimension will change in qh_initqhull_globals if qh.PROJECTinput | 
| 3751 |  |  | uses malloc() since qh_mem not initialized | 
| 3752 |  |  | FIXUP: this routine needs rewriting | 
| 3753 |  |  | */ | 
| 3754 |  |  | coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) { | 
| 3755 |  |  | coordT *points, *coords, *infinity= NULL; | 
| 3756 |  |  | realT paraboloid, maxboloid= -REALmax, value; | 
| 3757 |  |  | realT *coordp= NULL, *offsetp= NULL, *normalp= NULL; | 
| 3758 |  |  | char *s, *t, firstline[qh_MAXfirst+1]; | 
| 3759 |  |  | int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi; | 
| 3760 |  |  | int firsttext=0, firstshort=0, firstlong=0, firstpoint=0; | 
| 3761 |  |  | int tokcount= 0, linecount=0, maxcount, coordcount=0; | 
| 3762 |  |  | boolT islong, isfirst= True, wasbegin= False; | 
| 3763 |  |  | boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput; | 
| 3764 |  |  |  | 
| 3765 |  |  | if (qh CDDinput) { | 
| 3766 |  |  | while ((s= fgets(firstline, qh_MAXfirst, qh fin))) { | 
| 3767 |  |  | linecount++; | 
| 3768 |  |  | if (qh HALFspace && linecount == 1 && isdigit(*s)) { | 
| 3769 |  |  | dimfeasible= qh_strtol (s, &s); | 
| 3770 |  |  | while (isspace(*s)) | 
| 3771 |  |  | s++; | 
| 3772 |  |  | if (qh_strtol (s, &s) == 1) | 
| 3773 |  |  | linecount += qh_readfeasible (dimfeasible, s); | 
| 3774 |  |  | else | 
| 3775 |  |  | dimfeasible= 0; | 
| 3776 |  |  | }else if (!memcmp (firstline, "begin", 5) || !memcmp (firstline, "BEGIN", 5)) | 
| 3777 |  |  | break; | 
| 3778 |  |  | else if (!*qh rbox_command) | 
| 3779 |  |  | strncat(qh rbox_command, s, sizeof (qh rbox_command)-1); | 
| 3780 |  |  | } | 
| 3781 |  |  | if (!s) { | 
| 3782 |  |  | fprintf (qh ferr, "qhull input error: missing \"begin\" for cdd-formated input\n"); | 
| 3783 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3784 |  |  | } | 
| 3785 |  |  | } | 
| 3786 |  |  | while(!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) { | 
| 3787 |  |  | linecount++; | 
| 3788 |  |  | if (!memcmp (s, "begin", 5) || !memcmp (s, "BEGIN", 5)) | 
| 3789 |  |  | wasbegin= True; | 
| 3790 |  |  | while (*s) { | 
| 3791 |  |  | while (isspace(*s)) | 
| 3792 |  |  | s++; | 
| 3793 |  |  | if (!*s) | 
| 3794 |  |  | break; | 
| 3795 |  |  | if (!isdigit(*s)) { | 
| 3796 |  |  | if (!*qh rbox_command) { | 
| 3797 |  |  | strncat(qh rbox_command, s, sizeof (qh rbox_command)-1); | 
| 3798 |  |  | firsttext= linecount; | 
| 3799 |  |  | } | 
| 3800 |  |  | break; | 
| 3801 |  |  | } | 
| 3802 |  |  | if (!diminput) | 
| 3803 |  |  | diminput= qh_strtol (s, &s); | 
| 3804 |  |  | else { | 
| 3805 |  |  | numinput= qh_strtol (s, &s); | 
| 3806 |  |  | if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) { | 
| 3807 |  |  | linecount += qh_readfeasible (diminput, s); /* checks if ok */ | 
| 3808 |  |  | dimfeasible= diminput; | 
| 3809 |  |  | diminput= numinput= 0; | 
| 3810 |  |  | }else | 
| 3811 |  |  | break; | 
| 3812 |  |  | } | 
| 3813 |  |  | } | 
| 3814 |  |  | } | 
| 3815 |  |  | if (!s) { | 
| 3816 |  |  | fprintf(qh ferr, "qhull input error: short input file.  Did not find dimension and number of points\n"); | 
| 3817 |  |  | qh_errexit(qh_ERRinput, NULL, NULL); | 
| 3818 |  |  | } | 
| 3819 |  |  | if (diminput > numinput) { | 
| 3820 |  |  | tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */ | 
| 3821 |  |  | diminput= numinput; | 
| 3822 |  |  | numinput= tempi; | 
| 3823 |  |  | } | 
| 3824 |  |  | if (diminput < 2) { | 
| 3825 |  |  | fprintf(qh ferr,"qhull input error: dimension %d (first number) should be at least 2\n", | 
| 3826 |  |  | diminput); | 
| 3827 |  |  | qh_errexit(qh_ERRinput, NULL, NULL); | 
| 3828 |  |  | } | 
| 3829 |  |  | if (isdelaunay) { | 
| 3830 |  |  | qh PROJECTdelaunay= False; | 
| 3831 |  |  | if (qh CDDinput) | 
| 3832 |  |  | *dimension= diminput; | 
| 3833 |  |  | else | 
| 3834 |  |  | *dimension= diminput+1; | 
| 3835 |  |  | *numpoints= numinput; | 
| 3836 |  |  | if (qh ATinfinity) | 
| 3837 |  |  | (*numpoints)++; | 
| 3838 |  |  | }else if (qh HALFspace) { | 
| 3839 |  |  | *dimension= diminput - 1; | 
| 3840 |  |  | *numpoints= numinput; | 
| 3841 |  |  | if (diminput < 3) { | 
| 3842 |  |  | fprintf(qh ferr,"qhull input error: dimension %d (first number, includes offset) should be at least 3 for halfspaces\n", | 
| 3843 |  |  | diminput); | 
| 3844 |  |  | qh_errexit(qh_ERRinput, NULL, NULL); | 
| 3845 |  |  | } | 
| 3846 |  |  | if (dimfeasible) { | 
| 3847 |  |  | if (dimfeasible != *dimension) { | 
| 3848 |  |  | fprintf(qh ferr,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n", | 
| 3849 |  |  | dimfeasible, diminput); | 
| 3850 |  |  | qh_errexit(qh_ERRinput, NULL, NULL); | 
| 3851 |  |  | } | 
| 3852 |  |  | }else | 
| 3853 |  |  | qh_setfeasible (*dimension); | 
| 3854 |  |  | }else { | 
| 3855 |  |  | if (qh CDDinput) | 
| 3856 |  |  | *dimension= diminput-1; | 
| 3857 |  |  | else | 
| 3858 |  |  | *dimension= diminput; | 
| 3859 |  |  | *numpoints= numinput; | 
| 3860 |  |  | } | 
| 3861 |  |  | qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */ | 
| 3862 |  |  | if (qh HALFspace) { | 
| 3863 |  |  | qh half_space= coordp= (coordT*) malloc (qh normal_size + sizeof(coordT)); | 
| 3864 |  |  | if (qh CDDinput) { | 
| 3865 |  |  | offsetp= qh half_space; | 
| 3866 |  |  | normalp= offsetp + 1; | 
| 3867 |  |  | }else { | 
| 3868 |  |  | normalp= qh half_space; | 
| 3869 |  |  | offsetp= normalp + *dimension; | 
| 3870 |  |  | } | 
| 3871 |  |  | } | 
| 3872 |  |  | qh maxline= diminput * (qh_REALdigits + 5); | 
| 3873 |  |  | maximize_(qh maxline, 500); | 
| 3874 |  |  | qh line= (char*)malloc ((qh maxline+1) * sizeof (char)); | 
| 3875 |  |  | *ismalloc= True;  /* use malloc since memory not setup */ | 
| 3876 |  |  | coords= points= qh temp_malloc= | 
| 3877 |  |  | (coordT*)malloc((*numpoints)*(*dimension)*sizeof(coordT)); | 
| 3878 |  |  | if (!coords || !qh line || (qh HALFspace && !qh half_space)) { | 
| 3879 |  |  | fprintf(qh ferr, "qhull error: insufficient memory to read %d points\n", | 
| 3880 |  |  | numinput); | 
| 3881 |  |  | qh_errexit(qh_ERRmem, NULL, NULL); | 
| 3882 |  |  | } | 
| 3883 |  |  | if (isdelaunay && qh ATinfinity) { | 
| 3884 |  |  | infinity= points + numinput * (*dimension); | 
| 3885 |  |  | for (k= (*dimension) - 1; k--; ) | 
| 3886 |  |  | infinity[k]= 0.0; | 
| 3887 |  |  | } | 
| 3888 |  |  | maxcount= numinput * diminput; | 
| 3889 |  |  | paraboloid= 0.0; | 
| 3890 |  |  | while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) { | 
| 3891 |  |  | if (!isfirst) { | 
| 3892 |  |  | linecount++; | 
| 3893 |  |  | if (*s == 'e' || *s == 'E') { | 
| 3894 |  |  | if (!memcmp (s, "end", 3) || !memcmp (s, "END", 3)) { | 
| 3895 |  |  | if (qh CDDinput ) | 
| 3896 |  |  | break; | 
| 3897 |  |  | else if (wasbegin) | 
| 3898 |  |  | fprintf (qh ferr, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n"); | 
| 3899 |  |  | } | 
| 3900 |  |  | } | 
| 3901 |  |  | } | 
| 3902 |  |  | islong= False; | 
| 3903 |  |  | while (*s) { | 
| 3904 |  |  | while (isspace(*s)) | 
| 3905 |  |  | s++; | 
| 3906 |  |  | value= qh_strtod (s, &t); | 
| 3907 |  |  | if (s == t) { | 
| 3908 |  |  | if (!*qh rbox_command) | 
| 3909 |  |  | strncat(qh rbox_command, s, sizeof (qh rbox_command)-1); | 
| 3910 |  |  | if (*s && !firsttext) | 
| 3911 |  |  | firsttext= linecount; | 
| 3912 |  |  | if (!islong && !firstshort && coordcount) | 
| 3913 |  |  | firstshort= linecount; | 
| 3914 |  |  | break; | 
| 3915 |  |  | } | 
| 3916 |  |  | if (!firstpoint) | 
| 3917 |  |  | firstpoint= linecount; | 
| 3918 |  |  | s= t; | 
| 3919 |  |  | if (++tokcount > maxcount) | 
| 3920 |  |  | continue; | 
| 3921 |  |  | if (qh HALFspace) { | 
| 3922 |  |  | if (qh CDDinput) | 
| 3923 |  |  | *(coordp++)= -value; /* both coefficients and offset */ | 
| 3924 |  |  | else | 
| 3925 |  |  | *(coordp++)= value; | 
| 3926 |  |  | }else { | 
| 3927 |  |  | *(coords++)= value; | 
| 3928 |  |  | if (qh CDDinput && !coordcount) { | 
| 3929 |  |  | if (value != 1.0) { | 
| 3930 |  |  | fprintf (qh ferr, "qhull input error: for cdd format, point at line %d does not start with '1'\n", | 
| 3931 |  |  | linecount); | 
| 3932 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3933 |  |  | } | 
| 3934 |  |  | coords--; | 
| 3935 |  |  | }else if (isdelaunay) { | 
| 3936 |  |  | paraboloid += value * value; | 
| 3937 |  |  | if (qh ATinfinity) { | 
| 3938 |  |  | if (qh CDDinput) | 
| 3939 |  |  | infinity[coordcount-1] += value; | 
| 3940 |  |  | else | 
| 3941 |  |  | infinity[coordcount] += value; | 
| 3942 |  |  | } | 
| 3943 |  |  | } | 
| 3944 |  |  | } | 
| 3945 |  |  | if (++coordcount == diminput) { | 
| 3946 |  |  | coordcount= 0; | 
| 3947 |  |  | if (isdelaunay) { | 
| 3948 |  |  | *(coords++)= paraboloid; | 
| 3949 |  |  | maximize_(maxboloid, paraboloid); | 
| 3950 |  |  | paraboloid= 0.0; | 
| 3951 |  |  | }else if (qh HALFspace) { | 
| 3952 |  |  | if (!qh_sethalfspace (*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) { | 
| 3953 |  |  | fprintf (qh ferr, "The halfspace was on line %d\n", linecount); | 
| 3954 |  |  | if (wasbegin) | 
| 3955 |  |  | fprintf (qh ferr, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n"); | 
| 3956 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 3957 |  |  | } | 
| 3958 |  |  | coordp= qh half_space; | 
| 3959 |  |  | } | 
| 3960 |  |  | while (isspace(*s)) | 
| 3961 |  |  | s++; | 
| 3962 |  |  | if (*s) { | 
| 3963 |  |  | islong= True; | 
| 3964 |  |  | if (!firstlong) | 
| 3965 |  |  | firstlong= linecount; | 
| 3966 |  |  | } | 
| 3967 |  |  | } | 
| 3968 |  |  | } | 
| 3969 |  |  | if (!islong && !firstshort && coordcount) | 
| 3970 |  |  | firstshort= linecount; | 
| 3971 |  |  | if (!isfirst && s - qh line >= qh maxline) { | 
| 3972 |  |  | fprintf(qh ferr, "qhull input error: line %d contained more than %d characters\n", | 
| 3973 |  |  | linecount, (int) (s - qh line)); | 
| 3974 |  |  | qh_errexit(qh_ERRinput, NULL, NULL); | 
| 3975 |  |  | } | 
| 3976 |  |  | isfirst= False; | 
| 3977 |  |  | } | 
| 3978 |  |  | if (tokcount != maxcount) { | 
| 3979 |  |  | newnum= fmin_(numinput, tokcount/diminput); | 
| 3980 |  |  | fprintf(qh ferr,"\ | 
| 3981 |  |  | qhull warning: instead of %d %d-dimensional points, input contains\n\ | 
| 3982 |  |  | %d points and %d extra coordinates.  Line %d is the first\npoint", | 
| 3983 |  |  | numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint); | 
| 3984 |  |  | if (firsttext) | 
| 3985 |  |  | fprintf(qh ferr, ", line %d is the first comment", firsttext); | 
| 3986 |  |  | if (firstshort) | 
| 3987 |  |  | fprintf(qh ferr, ", line %d is the first short\nline", firstshort); | 
| 3988 |  |  | if (firstlong) | 
| 3989 |  |  | fprintf(qh ferr, ", line %d is the first long line", firstlong); | 
| 3990 |  |  | fprintf(qh ferr, ".  Continue with %d points.\n", newnum); | 
| 3991 |  |  | numinput= newnum; | 
| 3992 |  |  | if (isdelaunay && qh ATinfinity) { | 
| 3993 |  |  | for (k= tokcount % diminput; k--; ) | 
| 3994 |  |  | infinity[k] -= *(--coords); | 
| 3995 |  |  | *numpoints= newnum+1; | 
| 3996 |  |  | }else { | 
| 3997 |  |  | coords -= tokcount % diminput; | 
| 3998 |  |  | *numpoints= newnum; | 
| 3999 |  |  | } | 
| 4000 |  |  | } | 
| 4001 |  |  | if (isdelaunay && qh ATinfinity) { | 
| 4002 |  |  | for (k= (*dimension) -1; k--; ) | 
| 4003 |  |  | infinity[k] /= numinput; | 
| 4004 |  |  | if (coords == infinity) | 
| 4005 |  |  | coords += (*dimension) -1; | 
| 4006 |  |  | else { | 
| 4007 |  |  | for (k= 0; k < (*dimension) -1; k++) | 
| 4008 |  |  | *(coords++)= infinity[k]; | 
| 4009 |  |  | } | 
| 4010 |  |  | *(coords++)= maxboloid * 1.1; | 
| 4011 |  |  | } | 
| 4012 |  |  | if (qh rbox_command[0]) { | 
| 4013 |  |  | qh rbox_command[strlen(qh rbox_command)-1]= '\0'; | 
| 4014 |  |  | if (!strcmp (qh rbox_command, "./rbox D4")) | 
| 4015 |  |  | fprintf (qh ferr, "\n\ | 
| 4016 |  |  | This is the qhull test case.  If any errors or core dumps occur,\n\ | 
| 4017 |  |  | recompile qhull with 'make new'.  If errors still occur, there is\n\ | 
| 4018 |  |  | an incompatibility.  You should try a different compiler.  You can also\n\ | 
| 4019 |  |  | change the choices in user.h.  If you discover the source of the problem,\n\ | 
| 4020 |  |  | please send mail to qhull_bug@qhull.org.\n\ | 
| 4021 |  |  | \n\ | 
| 4022 |  |  | Type 'qhull' for a short list of options.\n"); | 
| 4023 |  |  | } | 
| 4024 |  |  | free (qh line); | 
| 4025 |  |  | qh line= NULL; | 
| 4026 |  |  | if (qh half_space) { | 
| 4027 |  |  | free (qh half_space); | 
| 4028 |  |  | qh half_space= NULL; | 
| 4029 |  |  | } | 
| 4030 |  |  | qh temp_malloc= NULL; | 
| 4031 |  |  | trace1((qh ferr,"qh_readpoints: read in %d %d-dimensional points\n", numinput, diminput)); | 
| 4032 |  |  | return(points); | 
| 4033 |  |  | } /* readpoints */ | 
| 4034 |  |  |  | 
| 4035 |  |  |  | 
| 4036 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 4037 |  |  | >-------------------------------</a><a name="setfeasible">-</a> | 
| 4038 |  |  |  | 
| 4039 |  |  | qh_setfeasible( dim ) | 
| 4040 |  |  | set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format | 
| 4041 |  |  |  | 
| 4042 |  |  | notes: | 
| 4043 |  |  | "n,n,n" already checked by qh_initflags() | 
| 4044 |  |  | see qh_readfeasible() | 
| 4045 |  |  | */ | 
| 4046 |  |  | void qh_setfeasible (int dim) { | 
| 4047 |  |  | int tokcount= 0; | 
| 4048 |  |  | char *s; | 
| 4049 |  |  | coordT *coords, value; | 
| 4050 |  |  |  | 
| 4051 |  |  | if (!(s= qh feasible_string)) { | 
| 4052 |  |  | fprintf(qh ferr, "\ | 
| 4053 |  |  | qhull input error: halfspace intersection needs a feasible point.\n\ | 
| 4054 |  |  | Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n"); | 
| 4055 |  |  | qh_errexit (qh_ERRinput, NULL, NULL); | 
| 4056 |  |  | } | 
| 4057 |  |  | if (!(qh feasible_point= (pointT*)malloc (dim* sizeof(coordT)))) { | 
| 4058 |  |  | fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n"); | 
| 4059 |  |  | qh_errexit(qh_ERRmem, NULL, NULL); | 
| 4060 |  |  | } | 
| 4061 |  |  | coords= qh feasible_point; | 
| 4062 |  |  | while (*s) { | 
| 4063 |  |  | value= qh_strtod (s, &s); | 
| 4064 |  |  | if (++tokcount > dim) { | 
| 4065 |  |  | fprintf (qh ferr, "qhull input warning: more coordinates for 'H%s' than dimension %d\n", | 
| 4066 |  |  | qh feasible_string, dim); | 
| 4067 |  |  | break; | 
| 4068 |  |  | } | 
| 4069 |  |  | *(coords++)= value; | 
| 4070 |  |  | if (*s) | 
| 4071 |  |  | s++; | 
| 4072 |  |  | } | 
| 4073 |  |  | while (++tokcount <= dim) | 
| 4074 |  |  | *(coords++)= 0.0; | 
| 4075 |  |  | } /* setfeasible */ | 
| 4076 |  |  |  | 
| 4077 |  |  | /*-<a                             href="qh-io.htm#TOC" | 
| 4078 |  |  | >-------------------------------</a><a name="skipfacet">-</a> | 
| 4079 |  |  |  | 
| 4080 |  |  | qh_skipfacet( facet ) | 
| 4081 |  |  | returns 'True' if this facet is not to be printed | 
| 4082 |  |  |  | 
| 4083 |  |  | notes: | 
| 4084 |  |  | based on the user provided slice thresholds and 'good' specifications | 
| 4085 |  |  | */ | 
| 4086 |  |  | boolT qh_skipfacet(facetT *facet) { | 
| 4087 |  |  | facetT *neighbor, **neighborp; | 
| 4088 |  |  |  | 
| 4089 |  |  | if (qh PRINTneighbors) { | 
| 4090 |  |  | if (facet->good) | 
| 4091 |  |  | return !qh PRINTgood; | 
| 4092 |  |  | FOREACHneighbor_(facet) { | 
| 4093 |  |  | if (neighbor->good) | 
| 4094 |  |  | return False; | 
| 4095 |  |  | } | 
| 4096 |  |  | return True; | 
| 4097 |  |  | }else if (qh PRINTgood) | 
| 4098 |  |  | return !facet->good; | 
| 4099 |  |  | else if (!facet->normal) | 
| 4100 |  |  | return True; | 
| 4101 |  |  | return (!qh_inthresholds (facet->normal, NULL)); | 
| 4102 |  |  | } /* skipfacet */ | 
| 4103 |  |  |  |