geom2_r.c 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302
  1. /*<html><pre> -<a href="qh-geom_r.htm"
  2. >-------------------------------</a><a name="TOP">-</a>
  3. geom2_r.c
  4. infrequently used geometric routines of qhull
  5. see qh-geom_r.htm and geom_r.h
  6. Copyright (c) 1993-2020 The Geometry Center.
  7. $Id: //main/2019/qhull/src/libqhull_r/geom2_r.c#17 $$Change: 3037 $
  8. $DateTime: 2020/09/03 17:28:32 $$Author: bbarber $
  9. frequently used code goes into geom_r.c
  10. */
  11. #include "qhull_ra.h"
  12. /*================== functions in alphabetic order ============*/
  13. /*-<a href="qh-geom_r.htm#TOC"
  14. >-------------------------------</a><a name="copypoints">-</a>
  15. qh_copypoints(qh, points, numpoints, dimension )
  16. return qh_malloc'd copy of points
  17. notes:
  18. qh_free the returned points to avoid a memory leak
  19. */
  20. coordT *qh_copypoints(qhT *qh, coordT *points, int numpoints, int dimension)
  21. {
  22. int size;
  23. coordT *newpoints;
  24. size= numpoints * dimension * (int)sizeof(coordT);
  25. if (!(newpoints= (coordT *)qh_malloc((size_t)size))) {
  26. qh_fprintf(qh, qh->ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
  27. numpoints);
  28. qh_errexit(qh, qh_ERRmem, NULL, NULL);
  29. }
  30. memcpy((char *)newpoints, (char *)points, (size_t)size); /* newpoints!=0 by QH6004 */
  31. return newpoints;
  32. } /* copypoints */
  33. /*-<a href="qh-geom_r.htm#TOC"
  34. >-------------------------------</a><a name="crossproduct">-</a>
  35. qh_crossproduct( dim, vecA, vecB, vecC )
  36. crossproduct of 2 dim vectors
  37. C= A x B
  38. notes:
  39. from Glasner, Graphics Gems I, p. 639
  40. only defined for dim==3
  41. */
  42. void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
  43. if (dim == 3) {
  44. vecC[0]= det2_(vecA[1], vecA[2],
  45. vecB[1], vecB[2]);
  46. vecC[1]= - det2_(vecA[0], vecA[2],
  47. vecB[0], vecB[2]);
  48. vecC[2]= det2_(vecA[0], vecA[1],
  49. vecB[0], vecB[1]);
  50. }
  51. } /* vcross */
  52. /*-<a href="qh-geom_r.htm#TOC"
  53. >-------------------------------</a><a name="determinant">-</a>
  54. qh_determinant(qh, rows, dim, nearzero )
  55. compute signed determinant of a square matrix
  56. uses qh.NEARzero to test for degenerate matrices
  57. returns:
  58. determinant
  59. overwrites rows and the matrix
  60. if dim == 2 or 3
  61. nearzero iff determinant < qh->NEARzero[dim-1]
  62. (!quite correct, not critical)
  63. if dim >= 4
  64. nearzero iff diagonal[k] < qh->NEARzero[k]
  65. */
  66. realT qh_determinant(qhT *qh, realT **rows, int dim, boolT *nearzero) {
  67. realT det=0;
  68. int i;
  69. boolT sign= False;
  70. *nearzero= False;
  71. if (dim < 2) {
  72. qh_fprintf(qh, qh->ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
  73. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  74. }else if (dim == 2) {
  75. det= det2_(rows[0][0], rows[0][1],
  76. rows[1][0], rows[1][1]);
  77. if (fabs_(det) < 10*qh->NEARzero[1]) /* QH11031 FIX: not really correct, what should this be? */
  78. *nearzero= True;
  79. }else if (dim == 3) {
  80. det= det3_(rows[0][0], rows[0][1], rows[0][2],
  81. rows[1][0], rows[1][1], rows[1][2],
  82. rows[2][0], rows[2][1], rows[2][2]);
  83. if (fabs_(det) < 10*qh->NEARzero[2]) /* QH11031 FIX: what should this be? det 5.5e-12 was flat for qh_maxsimplex of qdelaunay 0,0 27,27 -36,36 -9,63 */
  84. *nearzero= True;
  85. }else {
  86. qh_gausselim(qh, rows, dim, dim, &sign, nearzero); /* if nearzero, diagonal still ok */
  87. det= 1.0;
  88. for (i=dim; i--; )
  89. det *= (rows[i])[i];
  90. if (sign)
  91. det= -det;
  92. }
  93. return det;
  94. } /* determinant */
  95. /*-<a href="qh-geom_r.htm#TOC"
  96. >-------------------------------</a><a name="detjoggle">-</a>
  97. qh_detjoggle(qh, points, numpoints, dimension )
  98. determine default max joggle for point array
  99. as qh_distround * qh_JOGGLEdefault
  100. returns:
  101. initial value for JOGGLEmax from points and REALepsilon
  102. notes:
  103. computes DISTround since qh_maxmin not called yet
  104. if qh->SCALElast, last dimension will be scaled later to MAXwidth
  105. loop duplicated from qh_maxmin
  106. */
  107. realT qh_detjoggle(qhT *qh, pointT *points, int numpoints, int dimension) {
  108. realT abscoord, distround, joggle, maxcoord, mincoord;
  109. pointT *point, *pointtemp;
  110. realT maxabs= -REALmax;
  111. realT sumabs= 0;
  112. realT maxwidth= 0;
  113. int k;
  114. if (qh->SETroundoff)
  115. distround= qh->DISTround; /* 'En' */
  116. else{
  117. for (k=0; k < dimension; k++) {
  118. if (qh->SCALElast && k == dimension-1)
  119. abscoord= maxwidth;
  120. else if (qh->DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
  121. abscoord= 2 * maxabs * maxabs; /* may be low by qh->hull_dim/2 */
  122. else {
  123. maxcoord= -REALmax;
  124. mincoord= REALmax;
  125. FORALLpoint_(qh, points, numpoints) {
  126. maximize_(maxcoord, point[k]);
  127. minimize_(mincoord, point[k]);
  128. }
  129. maximize_(maxwidth, maxcoord-mincoord);
  130. abscoord= fmax_(maxcoord, -mincoord);
  131. }
  132. sumabs += abscoord;
  133. maximize_(maxabs, abscoord);
  134. } /* for k */
  135. distround= qh_distround(qh, qh->hull_dim, maxabs, sumabs);
  136. }
  137. joggle= distround * qh_JOGGLEdefault;
  138. maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
  139. trace2((qh, qh->ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
  140. return joggle;
  141. } /* detjoggle */
  142. /*-<a href="qh-geom_r.htm#TOC"
  143. >-------------------------------</a><a name="detmaxoutside">-</a>
  144. qh_detmaxoutside(qh);
  145. determine qh.MAXoutside target for qh_RATIO... tests of distance
  146. updates option '_max-outside'
  147. notes:
  148. called from qh_addpoint and qh_detroundoff
  149. accounts for qh.ONEmerge, qh.DISTround, qh.MINoutside ('Wn'), qh.max_outside
  150. see qh_maxout for qh.max_outside with qh.DISTround
  151. */
  152. void qh_detmaxoutside(qhT *qh) {
  153. realT maxoutside;
  154. maxoutside= fmax_(qh->max_outside, qh->ONEmerge + qh->DISTround);
  155. maximize_(maxoutside, qh->MINoutside);
  156. qh->MAXoutside= maxoutside;
  157. trace3((qh, qh->ferr, 3056, "qh_detmaxoutside: MAXoutside %2.2g from qh.max_outside %2.2g, ONEmerge %2.2g, MINoutside %2.2g, DISTround %2.2g\n",
  158. qh->MAXoutside, qh->max_outside, qh->ONEmerge, qh->MINoutside, qh->DISTround));
  159. } /* detmaxoutside */
  160. /*-<a href="qh-geom_r.htm#TOC"
  161. >-------------------------------</a><a name="detroundoff">-</a>
  162. qh_detroundoff(qh)
  163. determine maximum roundoff errors from
  164. REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
  165. qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
  166. accounts for qh.SETroundoff, qh.RANDOMdist, qh->MERGEexact
  167. qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
  168. qh.postmerge_centrum, qh.MINoutside,
  169. qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
  170. returns:
  171. sets qh.DISTround, etc. (see below)
  172. appends precision constants to qh.qhull_options
  173. see:
  174. qh_maxmin() for qh.NEARzero
  175. design:
  176. determine qh.DISTround for distance computations
  177. determine minimum denominators for qh_divzero
  178. determine qh.ANGLEround for angle computations
  179. adjust qh.premerge_cos,... for roundoff error
  180. determine qh.ONEmerge for maximum error due to a single merge
  181. determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
  182. qh.MINoutside, qh.WIDEfacet
  183. initialize qh.max_vertex and qh.minvertex
  184. */
  185. void qh_detroundoff(qhT *qh) {
  186. qh_option(qh, "_max-width", NULL, &qh->MAXwidth);
  187. if (!qh->SETroundoff) {
  188. qh->DISTround= qh_distround(qh, qh->hull_dim, qh->MAXabs_coord, qh->MAXsumcoord);
  189. qh_option(qh, "Error-roundoff", NULL, &qh->DISTround);
  190. }
  191. qh->MINdenom= qh->MINdenom_1 * qh->MAXabs_coord;
  192. qh->MINdenom_1_2= sqrt(qh->MINdenom_1 * qh->hull_dim) ; /* if will be normalized */
  193. qh->MINdenom_2= qh->MINdenom_1_2 * qh->MAXabs_coord;
  194. /* for inner product */
  195. qh->ANGLEround= 1.01 * qh->hull_dim * REALepsilon;
  196. if (qh->RANDOMdist) {
  197. qh->ANGLEround += qh->RANDOMfactor;
  198. trace4((qh, qh->ferr, 4096, "qh_detroundoff: increase qh.ANGLEround by option 'R%2.2g'\n", qh->RANDOMfactor));
  199. }
  200. if (qh->premerge_cos < REALmax/2) {
  201. qh->premerge_cos -= qh->ANGLEround;
  202. if (qh->RANDOMdist)
  203. qh_option(qh, "Angle-premerge-with-random", NULL, &qh->premerge_cos);
  204. }
  205. if (qh->postmerge_cos < REALmax/2) {
  206. qh->postmerge_cos -= qh->ANGLEround;
  207. if (qh->RANDOMdist)
  208. qh_option(qh, "Angle-postmerge-with-random", NULL, &qh->postmerge_cos);
  209. }
  210. qh->premerge_centrum += 2 * qh->DISTround; /*2 for centrum and distplane()*/
  211. qh->postmerge_centrum += 2 * qh->DISTround;
  212. if (qh->RANDOMdist && (qh->MERGEexact || qh->PREmerge))
  213. qh_option(qh, "Centrum-premerge-with-random", NULL, &qh->premerge_centrum);
  214. if (qh->RANDOMdist && qh->POSTmerge)
  215. qh_option(qh, "Centrum-postmerge-with-random", NULL, &qh->postmerge_centrum);
  216. { /* compute ONEmerge, max vertex offset for merging simplicial facets */
  217. realT maxangle= 1.0, maxrho;
  218. minimize_(maxangle, qh->premerge_cos);
  219. minimize_(maxangle, qh->postmerge_cos);
  220. /* max diameter * sin theta + DISTround for vertex to its hyperplane */
  221. qh->ONEmerge= sqrt((realT)qh->hull_dim) * qh->MAXwidth *
  222. sqrt(1.0 - maxangle * maxangle) + qh->DISTround;
  223. maxrho= qh->hull_dim * qh->premerge_centrum + qh->DISTround;
  224. maximize_(qh->ONEmerge, maxrho);
  225. maxrho= qh->hull_dim * qh->postmerge_centrum + qh->DISTround;
  226. maximize_(qh->ONEmerge, maxrho);
  227. if (qh->MERGING)
  228. qh_option(qh, "_one-merge", NULL, &qh->ONEmerge);
  229. }
  230. qh->NEARinside= qh->ONEmerge * qh_RATIOnearinside; /* only used if qh->KEEPnearinside */
  231. if (qh->JOGGLEmax < REALmax/2 && (qh->KEEPcoplanar || qh->KEEPinside)) {
  232. realT maxdist; /* adjust qh.NEARinside for joggle */
  233. qh->KEEPnearinside= True;
  234. maxdist= sqrt((realT)qh->hull_dim) * qh->JOGGLEmax + qh->DISTround;
  235. maxdist= 2*maxdist; /* vertex and coplanar point can joggle in opposite directions */
  236. maximize_(qh->NEARinside, maxdist); /* must agree with qh_nearcoplanar() */
  237. }
  238. if (qh->KEEPnearinside)
  239. qh_option(qh, "_near-inside", NULL, &qh->NEARinside);
  240. if (qh->JOGGLEmax < qh->DISTround) {
  241. qh_fprintf(qh, qh->ferr, 6006, "qhull option error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
  242. qh->JOGGLEmax, qh->DISTround);
  243. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  244. }
  245. if (qh->MINvisible > REALmax/2) {
  246. if (!qh->MERGING)
  247. qh->MINvisible= qh->DISTround;
  248. else if (qh->hull_dim <= 3)
  249. qh->MINvisible= qh->premerge_centrum;
  250. else
  251. qh->MINvisible= qh_COPLANARratio * qh->premerge_centrum;
  252. if (qh->APPROXhull && qh->MINvisible > qh->MINoutside)
  253. qh->MINvisible= qh->MINoutside;
  254. qh_option(qh, "Visible-distance", NULL, &qh->MINvisible);
  255. }
  256. if (qh->MAXcoplanar > REALmax/2) {
  257. qh->MAXcoplanar= qh->MINvisible;
  258. qh_option(qh, "U-max-coplanar", NULL, &qh->MAXcoplanar);
  259. }
  260. if (!qh->APPROXhull) { /* user may specify qh->MINoutside */
  261. qh->MINoutside= 2 * qh->MINvisible;
  262. if (qh->premerge_cos < REALmax/2)
  263. maximize_(qh->MINoutside, (1- qh->premerge_cos) * qh->MAXabs_coord);
  264. qh_option(qh, "Width-outside", NULL, &qh->MINoutside);
  265. }
  266. qh->WIDEfacet= qh->MINoutside;
  267. maximize_(qh->WIDEfacet, qh_WIDEcoplanar * qh->MAXcoplanar);
  268. maximize_(qh->WIDEfacet, qh_WIDEcoplanar * qh->MINvisible);
  269. qh_option(qh, "_wide-facet", NULL, &qh->WIDEfacet);
  270. if (qh->MINvisible > qh->MINoutside + 3 * REALepsilon
  271. && !qh->BESToutside && !qh->FORCEoutput)
  272. qh_fprintf(qh, qh->ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g. Flipped facets are likely.\n",
  273. qh->MINvisible, qh->MINoutside);
  274. qh->max_vertex= qh->DISTround;
  275. qh->min_vertex= -qh->DISTround;
  276. /* numeric constants reported in printsummary */
  277. qh_detmaxoutside(qh);
  278. } /* detroundoff */
  279. /*-<a href="qh-geom_r.htm#TOC"
  280. >-------------------------------</a><a name="detsimplex">-</a>
  281. qh_detsimplex(qh, apex, points, dim, nearzero )
  282. compute determinant of a simplex with point apex and base points
  283. returns:
  284. signed determinant and nearzero from qh_determinant
  285. notes:
  286. called by qh_maxsimplex and qh_initialvertices
  287. uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
  288. design:
  289. construct qm_matrix by subtracting apex from points
  290. compute determinate
  291. */
  292. realT qh_detsimplex(qhT *qh, pointT *apex, setT *points, int dim, boolT *nearzero) {
  293. pointT *coorda, *coordp, *gmcoord, *point, **pointp;
  294. coordT **rows;
  295. int k, i=0;
  296. realT det;
  297. zinc_(Zdetsimplex);
  298. gmcoord= qh->gm_matrix;
  299. rows= qh->gm_row;
  300. FOREACHpoint_(points) {
  301. if (i == dim)
  302. break;
  303. rows[i++]= gmcoord;
  304. coordp= point;
  305. coorda= apex;
  306. for (k=dim; k--; )
  307. *(gmcoord++)= *coordp++ - *coorda++;
  308. }
  309. if (i < dim) {
  310. qh_fprintf(qh, qh->ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
  311. i, dim);
  312. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  313. }
  314. det= qh_determinant(qh, rows, dim, nearzero);
  315. trace2((qh, qh->ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
  316. det, qh_pointid(qh, apex), dim, *nearzero));
  317. return det;
  318. } /* detsimplex */
  319. /*-<a href="qh-geom_r.htm#TOC"
  320. >-------------------------------</a><a name="distnorm">-</a>
  321. qh_distnorm( dim, point, normal, offset )
  322. return distance from point to hyperplane at normal/offset
  323. returns:
  324. dist
  325. notes:
  326. dist > 0 if point is outside of hyperplane
  327. see:
  328. qh_distplane in geom_r.c
  329. */
  330. realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
  331. coordT *normalp= normal, *coordp= point;
  332. realT dist;
  333. int k;
  334. dist= *offsetp;
  335. for (k=dim; k--; )
  336. dist += *(coordp++) * *(normalp++);
  337. return dist;
  338. } /* distnorm */
  339. /*-<a href="qh-geom_r.htm#TOC"
  340. >-------------------------------</a><a name="distround">-</a>
  341. qh_distround(qh, dimension, maxabs, maxsumabs )
  342. compute maximum round-off error for a distance computation
  343. to a normalized hyperplane
  344. maxabs is the maximum absolute value of a coordinate
  345. maxsumabs is the maximum possible sum of absolute coordinate values
  346. if qh.RANDOMdist ('Qr'), adjusts qh_distround
  347. returns:
  348. max dist round for qh.REALepsilon and qh.RANDOMdist
  349. notes:
  350. calculate roundoff error according to Golub & van Loan, 1983, Lemma 3.2-1, "Rounding Errors"
  351. use sqrt(dim) since one vector is normalized
  352. or use maxsumabs since one vector is < 1
  353. */
  354. realT qh_distround(qhT *qh, int dimension, realT maxabs, realT maxsumabs) {
  355. realT maxdistsum, maxround, delta;
  356. maxdistsum= sqrt((realT)dimension) * maxabs;
  357. minimize_( maxdistsum, maxsumabs);
  358. maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
  359. /* adds maxabs for offset */
  360. if (qh->RANDOMdist) {
  361. delta= qh->RANDOMfactor * maxabs;
  362. maxround += delta;
  363. trace4((qh, qh->ferr, 4092, "qh_distround: increase roundoff by random delta %2.2g for option 'R%2.2g'\n", delta, qh->RANDOMfactor));
  364. }
  365. trace4((qh, qh->ferr, 4008, "qh_distround: %2.2g, maxabs %2.2g, maxsumabs %2.2g, maxdistsum %2.2g\n",
  366. maxround, maxabs, maxsumabs, maxdistsum));
  367. return maxround;
  368. } /* distround */
  369. /*-<a href="qh-geom_r.htm#TOC"
  370. >-------------------------------</a><a name="divzero">-</a>
  371. qh_divzero( numer, denom, mindenom1, zerodiv )
  372. divide by a number that's nearly zero
  373. mindenom1= minimum denominator for dividing into 1.0
  374. returns:
  375. quotient
  376. sets zerodiv and returns 0.0 if it would overflow
  377. design:
  378. if numer is nearly zero and abs(numer) < abs(denom)
  379. return numer/denom
  380. else if numer is nearly zero
  381. return 0 and zerodiv
  382. else if denom/numer non-zero
  383. return numer/denom
  384. else
  385. return 0 and zerodiv
  386. */
  387. realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
  388. realT temp, numerx, denomx;
  389. if (numer < mindenom1 && numer > -mindenom1) {
  390. numerx= fabs_(numer);
  391. denomx= fabs_(denom);
  392. if (numerx < denomx) {
  393. *zerodiv= False;
  394. return numer/denom;
  395. }else {
  396. *zerodiv= True;
  397. return 0.0;
  398. }
  399. }
  400. temp= denom/numer;
  401. if (temp > mindenom1 || temp < -mindenom1) {
  402. *zerodiv= False;
  403. return numer/denom;
  404. }else {
  405. *zerodiv= True;
  406. return 0.0;
  407. }
  408. } /* divzero */
  409. /*-<a href="qh-geom_r.htm#TOC"
  410. >-------------------------------</a><a name="facetarea">-</a>
  411. qh_facetarea(qh, facet )
  412. return area for a facet
  413. notes:
  414. if non-simplicial,
  415. uses centrum to triangulate facet and sums the projected areas.
  416. if (qh->DELAUNAY),
  417. computes projected area instead for last coordinate
  418. assumes facet->normal exists
  419. projecting tricoplanar facets to the hyperplane does not appear to make a difference
  420. design:
  421. if simplicial
  422. compute area
  423. else
  424. for each ridge
  425. compute area from centrum to ridge
  426. negate area if upper Delaunay facet
  427. */
  428. realT qh_facetarea(qhT *qh, facetT *facet) {
  429. vertexT *apex;
  430. pointT *centrum;
  431. realT area= 0.0;
  432. ridgeT *ridge, **ridgep;
  433. if (facet->simplicial) {
  434. apex= SETfirstt_(facet->vertices, vertexT);
  435. area= qh_facetarea_simplex(qh, qh->hull_dim, apex->point, facet->vertices,
  436. apex, facet->toporient, facet->normal, &facet->offset);
  437. }else {
  438. if (qh->CENTERtype == qh_AScentrum)
  439. centrum= facet->center;
  440. else
  441. centrum= qh_getcentrum(qh, facet);
  442. FOREACHridge_(facet->ridges)
  443. area += qh_facetarea_simplex(qh, qh->hull_dim, centrum, ridge->vertices,
  444. NULL, (boolT)(ridge->top == facet), facet->normal, &facet->offset);
  445. if (qh->CENTERtype != qh_AScentrum)
  446. qh_memfree(qh, centrum, qh->normal_size);
  447. }
  448. if (facet->upperdelaunay && qh->DELAUNAY)
  449. area= -area; /* the normal should be [0,...,1] */
  450. trace4((qh, qh->ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
  451. return area;
  452. } /* facetarea */
  453. /*-<a href="qh-geom_r.htm#TOC"
  454. >-------------------------------</a><a name="facetarea_simplex">-</a>
  455. qh_facetarea_simplex(qh, dim, apex, vertices, notvertex, toporient, normal, offset )
  456. return area for a simplex defined by
  457. an apex, a base of vertices, an orientation, and a unit normal
  458. if simplicial or tricoplanar facet,
  459. notvertex is defined and it is skipped in vertices
  460. returns:
  461. computes area of simplex projected to plane [normal,offset]
  462. returns 0 if vertex too far below plane (qh->WIDEfacet)
  463. vertex can't be apex of tricoplanar facet
  464. notes:
  465. if (qh->DELAUNAY),
  466. computes projected area instead for last coordinate
  467. uses qh->gm_matrix/gm_row and qh->hull_dim
  468. helper function for qh_facetarea
  469. design:
  470. if Notvertex
  471. translate simplex to apex
  472. else
  473. project simplex to normal/offset
  474. translate simplex to apex
  475. if Delaunay
  476. set last row/column to 0 with -1 on diagonal
  477. else
  478. set last row to Normal
  479. compute determinate
  480. scale and flip sign for area
  481. */
  482. realT qh_facetarea_simplex(qhT *qh, int dim, coordT *apex, setT *vertices,
  483. vertexT *notvertex, boolT toporient, coordT *normal, realT *offset) {
  484. pointT *coorda, *coordp, *gmcoord;
  485. coordT **rows, *normalp;
  486. int k, i=0;
  487. realT area, dist;
  488. vertexT *vertex, **vertexp;
  489. boolT nearzero;
  490. gmcoord= qh->gm_matrix;
  491. rows= qh->gm_row;
  492. FOREACHvertex_(vertices) {
  493. if (vertex == notvertex)
  494. continue;
  495. rows[i++]= gmcoord;
  496. coorda= apex;
  497. coordp= vertex->point;
  498. normalp= normal;
  499. if (notvertex) {
  500. for (k=dim; k--; )
  501. *(gmcoord++)= *coordp++ - *coorda++;
  502. }else {
  503. dist= *offset;
  504. for (k=dim; k--; )
  505. dist += *coordp++ * *normalp++;
  506. if (dist < -qh->WIDEfacet) {
  507. zinc_(Znoarea);
  508. return 0.0;
  509. }
  510. coordp= vertex->point;
  511. normalp= normal;
  512. for (k=dim; k--; )
  513. *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
  514. }
  515. }
  516. if (i != dim-1) {
  517. qh_fprintf(qh, qh->ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
  518. i, dim);
  519. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  520. }
  521. rows[i]= gmcoord;
  522. if (qh->DELAUNAY) {
  523. for (i=0; i < dim-1; i++)
  524. rows[i][dim-1]= 0.0;
  525. for (k=dim; k--; )
  526. *(gmcoord++)= 0.0;
  527. rows[dim-1][dim-1]= -1.0;
  528. }else {
  529. normalp= normal;
  530. for (k=dim; k--; )
  531. *(gmcoord++)= *normalp++;
  532. }
  533. zinc_(Zdetfacetarea);
  534. area= qh_determinant(qh, rows, dim, &nearzero);
  535. if (toporient)
  536. area= -area;
  537. area *= qh->AREAfactor;
  538. trace4((qh, qh->ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
  539. area, qh_pointid(qh, apex), toporient, nearzero));
  540. return area;
  541. } /* facetarea_simplex */
  542. /*-<a href="qh-geom_r.htm#TOC"
  543. >-------------------------------</a><a name="facetcenter">-</a>
  544. qh_facetcenter(qh, vertices )
  545. return Voronoi center (Voronoi vertex) for a facet's vertices
  546. returns:
  547. return temporary point equal to the center
  548. see:
  549. qh_voronoi_center()
  550. */
  551. pointT *qh_facetcenter(qhT *qh, setT *vertices) {
  552. setT *points= qh_settemp(qh, qh_setsize(qh, vertices));
  553. vertexT *vertex, **vertexp;
  554. pointT *center;
  555. FOREACHvertex_(vertices)
  556. qh_setappend(qh, &points, vertex->point);
  557. center= qh_voronoi_center(qh, qh->hull_dim-1, points);
  558. qh_settempfree(qh, &points);
  559. return center;
  560. } /* facetcenter */
  561. /*-<a href="qh-geom_r.htm#TOC"
  562. >-------------------------------</a><a name="findgooddist">-</a>
  563. qh_findgooddist(qh, point, facetA, dist, facetlist )
  564. find best good facet visible for point from facetA
  565. assumes facetA is visible from point
  566. returns:
  567. best facet, i.e., good facet that is furthest from point
  568. distance to best facet
  569. NULL if none
  570. moves good, visible facets (and some other visible facets)
  571. to end of qh->facet_list
  572. notes:
  573. uses qh->visit_id
  574. design:
  575. initialize bestfacet if facetA is good
  576. move facetA to end of facetlist
  577. for each facet on facetlist
  578. for each unvisited neighbor of facet
  579. move visible neighbors to end of facetlist
  580. update best good neighbor
  581. if no good neighbors, update best facet
  582. */
  583. facetT *qh_findgooddist(qhT *qh, pointT *point, facetT *facetA, realT *distp,
  584. facetT **facetlist) {
  585. realT bestdist= -REALmax, dist;
  586. facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
  587. boolT goodseen= False;
  588. if (facetA->good) {
  589. zzinc_(Zcheckpart); /* calls from check_bestdist occur after print stats */
  590. qh_distplane(qh, point, facetA, &bestdist);
  591. bestfacet= facetA;
  592. goodseen= True;
  593. }
  594. qh_removefacet(qh, facetA);
  595. qh_appendfacet(qh, facetA);
  596. *facetlist= facetA;
  597. facetA->visitid= ++qh->visit_id;
  598. FORALLfacet_(*facetlist) {
  599. FOREACHneighbor_(facet) {
  600. if (neighbor->visitid == qh->visit_id)
  601. continue;
  602. neighbor->visitid= qh->visit_id;
  603. if (goodseen && !neighbor->good)
  604. continue;
  605. zzinc_(Zcheckpart);
  606. qh_distplane(qh, point, neighbor, &dist);
  607. if (dist > 0) {
  608. qh_removefacet(qh, neighbor);
  609. qh_appendfacet(qh, neighbor);
  610. if (neighbor->good) {
  611. goodseen= True;
  612. if (dist > bestdist) {
  613. bestdist= dist;
  614. bestfacet= neighbor;
  615. }
  616. }
  617. }
  618. }
  619. }
  620. if (bestfacet) {
  621. *distp= bestdist;
  622. trace2((qh, qh->ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
  623. qh_pointid(qh, point), bestdist, bestfacet->id));
  624. return bestfacet;
  625. }
  626. trace4((qh, qh->ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
  627. qh_pointid(qh, point), facetA->id));
  628. return NULL;
  629. } /* findgooddist */
  630. /*-<a href="qh-geom_r.htm#TOC"
  631. >-------------------------------</a><a name="furthestnewvertex">-</a>
  632. qh_furthestnewvertex(qh, unvisited, facet, &maxdist )
  633. return furthest unvisited, new vertex to a facet
  634. return:
  635. NULL if no vertex is above facet
  636. maxdist to facet
  637. updates v.visitid
  638. notes:
  639. Ignores vertices in facetB
  640. Does not change qh.vertex_visit. Use in conjunction with qh_furthestvertex
  641. */
  642. vertexT *qh_furthestnewvertex(qhT *qh, unsigned int unvisited, facetT *facet, realT *maxdistp /* qh.newvertex_list */) {
  643. vertexT *maxvertex= NULL, *vertex;
  644. coordT dist, maxdist= 0.0;
  645. FORALLvertex_(qh->newvertex_list) {
  646. if (vertex->newfacet && vertex->visitid <= unvisited) {
  647. vertex->visitid= qh->vertex_visit;
  648. qh_distplane(qh, vertex->point, facet, &dist);
  649. if (dist > maxdist) {
  650. maxdist= dist;
  651. maxvertex= vertex;
  652. }
  653. }
  654. }
  655. trace4((qh, qh->ferr, 4085, "qh_furthestnewvertex: v%d dist %2.2g is furthest new vertex for f%d\n",
  656. getid_(maxvertex), maxdist, facet->id));
  657. *maxdistp= maxdist;
  658. return maxvertex;
  659. } /* furthestnewvertex */
  660. /*-<a href="qh-geom_r.htm#TOC"
  661. >-------------------------------</a><a name="furthestvertex">-</a>
  662. qh_furthestvertex(qh, facetA, facetB, &maxdist, &mindist )
  663. return furthest vertex in facetA from facetB, or NULL if none
  664. return:
  665. maxdist and mindist to facetB or 0.0 if none
  666. updates qh.vertex_visit
  667. notes:
  668. Ignores vertices in facetB
  669. */
  670. vertexT *qh_furthestvertex(qhT *qh, facetT *facetA, facetT *facetB, realT *maxdistp, realT *mindistp) {
  671. vertexT *maxvertex= NULL, *vertex, **vertexp;
  672. coordT dist, maxdist= -REALmax, mindist= REALmax;
  673. qh->vertex_visit++;
  674. FOREACHvertex_(facetB->vertices)
  675. vertex->visitid= qh->vertex_visit;
  676. FOREACHvertex_(facetA->vertices) {
  677. if (vertex->visitid != qh->vertex_visit) {
  678. vertex->visitid= qh->vertex_visit;
  679. zzinc_(Zvertextests);
  680. qh_distplane(qh, vertex->point, facetB, &dist);
  681. if (!maxvertex) {
  682. maxdist= dist;
  683. mindist= dist;
  684. maxvertex= vertex;
  685. }else if (dist > maxdist) {
  686. maxdist= dist;
  687. maxvertex= vertex;
  688. }else if (dist < mindist)
  689. mindist= dist;
  690. }
  691. }
  692. if (!maxvertex) {
  693. trace3((qh, qh->ferr, 3067, "qh_furthestvertex: all vertices of f%d are in f%d. Returning 0.0 for max and mindist\n",
  694. facetA->id, facetB->id));
  695. maxdist= mindist= 0.0;
  696. }else {
  697. trace4((qh, qh->ferr, 4084, "qh_furthestvertex: v%d dist %2.2g is furthest (mindist %2.2g) of f%d above f%d\n",
  698. maxvertex->id, maxdist, mindist, facetA->id, facetB->id));
  699. }
  700. *maxdistp= maxdist;
  701. *mindistp= mindist;
  702. return maxvertex;
  703. } /* furthestvertex */
  704. /*-<a href="qh-geom_r.htm#TOC"
  705. >-------------------------------</a><a name="getarea">-</a>
  706. qh_getarea(qh, facetlist )
  707. set area of all facets in facetlist
  708. collect statistics
  709. nop if hasAreaVolume
  710. returns:
  711. sets qh->totarea/totvol to total area and volume of convex hull
  712. for Delaunay triangulation, computes projected area of the lower or upper hull
  713. ignores upper hull if qh->ATinfinity
  714. notes:
  715. could compute outer volume by expanding facet area by rays from interior
  716. the following attempt at perpendicular projection underestimated badly:
  717. qh.totoutvol += (-dist + facet->maxoutside + qh->DISTround)
  718. * area/ qh->hull_dim;
  719. design:
  720. for each facet on facetlist
  721. compute facet->area
  722. update qh.totarea and qh.totvol
  723. */
  724. void qh_getarea(qhT *qh, facetT *facetlist) {
  725. realT area;
  726. realT dist;
  727. facetT *facet;
  728. if (qh->hasAreaVolume)
  729. return;
  730. if (qh->REPORTfreq)
  731. qh_fprintf(qh, qh->ferr, 8020, "computing area of each facet and volume of the convex hull\n");
  732. else
  733. trace1((qh, qh->ferr, 1001, "qh_getarea: computing area for each facet and its volume to qh.interior_point (dist*area/dim)\n"));
  734. qh->totarea= qh->totvol= 0.0;
  735. FORALLfacet_(facetlist) {
  736. if (!facet->normal)
  737. continue;
  738. if (facet->upperdelaunay && qh->ATinfinity)
  739. continue;
  740. if (!facet->isarea) {
  741. facet->f.area= qh_facetarea(qh, facet);
  742. facet->isarea= True;
  743. }
  744. area= facet->f.area;
  745. if (qh->DELAUNAY) {
  746. if (facet->upperdelaunay == qh->UPPERdelaunay)
  747. qh->totarea += area;
  748. }else {
  749. qh->totarea += area;
  750. qh_distplane(qh, qh->interior_point, facet, &dist);
  751. qh->totvol += -dist * area/ qh->hull_dim;
  752. }
  753. if (qh->PRINTstatistics) {
  754. wadd_(Wareatot, area);
  755. wmax_(Wareamax, area);
  756. wmin_(Wareamin, area);
  757. }
  758. }
  759. qh->hasAreaVolume= True;
  760. } /* getarea */
  761. /*-<a href="qh-geom_r.htm#TOC"
  762. >-------------------------------</a><a name="gram_schmidt">-</a>
  763. qh_gram_schmidt(qh, dim, row )
  764. implements Gram-Schmidt orthogonalization by rows
  765. returns:
  766. false if zero norm
  767. overwrites rows[dim][dim]
  768. notes:
  769. see Golub & van Loan, 1983, Algorithm 6.2-2, "Modified Gram-Schmidt"
  770. overflow due to small divisors not handled
  771. design:
  772. for each row
  773. compute norm for row
  774. if non-zero, normalize row
  775. for each remaining rowA
  776. compute inner product of row and rowA
  777. reduce rowA by row * inner product
  778. */
  779. boolT qh_gram_schmidt(qhT *qh, int dim, realT **row) {
  780. realT *rowi, *rowj, norm;
  781. int i, j, k;
  782. for (i=0; i < dim; i++) {
  783. rowi= row[i];
  784. for (norm=0.0, k=dim; k--; rowi++)
  785. norm += *rowi * *rowi;
  786. norm= sqrt(norm);
  787. wmin_(Wmindenom, norm);
  788. if (norm == 0.0) /* either 0 or overflow due to sqrt */
  789. return False;
  790. for (k=dim; k--; )
  791. *(--rowi) /= norm;
  792. for (j=i+1; j < dim; j++) {
  793. rowj= row[j];
  794. for (norm=0.0, k=dim; k--; )
  795. norm += *rowi++ * *rowj++;
  796. for (k=dim; k--; )
  797. *(--rowj) -= *(--rowi) * norm;
  798. }
  799. }
  800. return True;
  801. } /* gram_schmidt */
  802. /*-<a href="qh-geom_r.htm#TOC"
  803. >-------------------------------</a><a name="inthresholds">-</a>
  804. qh_inthresholds(qh, normal, angle )
  805. return True if normal within qh.lower_/upper_threshold
  806. returns:
  807. estimate of angle by summing of threshold diffs
  808. angle may be NULL
  809. smaller "angle" is better
  810. notes:
  811. invalid if qh.SPLITthresholds
  812. see:
  813. qh.lower_threshold in qh_initbuild()
  814. qh_initthresholds()
  815. design:
  816. for each dimension
  817. test threshold
  818. */
  819. boolT qh_inthresholds(qhT *qh, coordT *normal, realT *angle) {
  820. boolT within= True;
  821. int k;
  822. realT threshold;
  823. if (angle)
  824. *angle= 0.0;
  825. for (k=0; k < qh->hull_dim; k++) {
  826. threshold= qh->lower_threshold[k];
  827. if (threshold > -REALmax/2) {
  828. if (normal[k] < threshold)
  829. within= False;
  830. if (angle) {
  831. threshold -= normal[k];
  832. *angle += fabs_(threshold);
  833. }
  834. }
  835. if (qh->upper_threshold[k] < REALmax/2) {
  836. threshold= qh->upper_threshold[k];
  837. if (normal[k] > threshold)
  838. within= False;
  839. if (angle) {
  840. threshold -= normal[k];
  841. *angle += fabs_(threshold);
  842. }
  843. }
  844. }
  845. return within;
  846. } /* inthresholds */
  847. /*-<a href="qh-geom_r.htm#TOC"
  848. >-------------------------------</a><a name="joggleinput">-</a>
  849. qh_joggleinput(qh)
  850. randomly joggle input to Qhull by qh.JOGGLEmax
  851. initial input is qh.first_point/qh.num_points of qh.hull_dim
  852. repeated calls use qh.input_points/qh.num_points
  853. returns:
  854. joggles points at qh.first_point/qh.num_points
  855. copies data to qh.input_points/qh.input_malloc if first time
  856. determines qh.JOGGLEmax if it was zero
  857. if qh.DELAUNAY
  858. computes the Delaunay projection of the joggled points
  859. notes:
  860. if qh.DELAUNAY, unnecessarily joggles the last coordinate
  861. the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
  862. design:
  863. if qh.DELAUNAY
  864. set qh.SCALElast for reduced precision errors
  865. if first call
  866. initialize qh.input_points to the original input points
  867. if qh.JOGGLEmax == 0
  868. determine default qh.JOGGLEmax
  869. else
  870. increase qh.JOGGLEmax according to qh.build_cnt
  871. joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
  872. if qh.DELAUNAY
  873. sets the Delaunay projection
  874. */
  875. void qh_joggleinput(qhT *qh) {
  876. int i, seed, size;
  877. coordT *coordp, *inputp;
  878. realT randr, randa, randb;
  879. if (!qh->input_points) { /* first call */
  880. qh->input_points= qh->first_point;
  881. qh->input_malloc= qh->POINTSmalloc;
  882. size= qh->num_points * qh->hull_dim * (int)sizeof(coordT);
  883. if (!(qh->first_point= (coordT *)qh_malloc((size_t)size))) {
  884. qh_fprintf(qh, qh->ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
  885. qh->num_points);
  886. qh_errexit(qh, qh_ERRmem, NULL, NULL);
  887. }
  888. qh->POINTSmalloc= True;
  889. if (qh->JOGGLEmax == 0.0) {
  890. qh->JOGGLEmax= qh_detjoggle(qh, qh->input_points, qh->num_points, qh->hull_dim);
  891. qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
  892. }
  893. }else { /* repeated call */
  894. if (!qh->RERUN && qh->build_cnt > qh_JOGGLEretry) {
  895. if (((qh->build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
  896. realT maxjoggle= qh->MAXwidth * qh_JOGGLEmaxincrease;
  897. if (qh->JOGGLEmax < maxjoggle) {
  898. qh->JOGGLEmax *= qh_JOGGLEincrease;
  899. minimize_(qh->JOGGLEmax, maxjoggle);
  900. }
  901. }
  902. }
  903. qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
  904. }
  905. if (qh->build_cnt > 1 && qh->JOGGLEmax > fmax_(qh->MAXwidth/4, 0.1)) {
  906. qh_fprintf(qh, qh->ferr, 6010, "qhull input error (qh_joggleinput): the current joggle for 'QJn', %.2g, is too large for the width\nof the input. If possible, recompile Qhull with higher-precision reals.\n",
  907. qh->JOGGLEmax);
  908. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  909. }
  910. /* for some reason, using qh->ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
  911. seed= qh_RANDOMint;
  912. qh_option(qh, "_joggle-seed", &seed, NULL);
  913. trace0((qh, qh->ferr, 6, "qh_joggleinput: joggle input by %4.4g with seed %d\n",
  914. qh->JOGGLEmax, seed));
  915. inputp= qh->input_points;
  916. coordp= qh->first_point;
  917. randa= 2.0 * qh->JOGGLEmax/qh_RANDOMmax;
  918. randb= -qh->JOGGLEmax;
  919. size= qh->num_points * qh->hull_dim;
  920. for (i=size; i--; ) {
  921. randr= qh_RANDOMint;
  922. *(coordp++)= *(inputp++) + (randr * randa + randb);
  923. }
  924. if (qh->DELAUNAY) {
  925. qh->last_low= qh->last_high= qh->last_newhigh= REALmax;
  926. qh_setdelaunay(qh, qh->hull_dim, qh->num_points, qh->first_point);
  927. }
  928. } /* joggleinput */
  929. /*-<a href="qh-geom_r.htm#TOC"
  930. >-------------------------------</a><a name="maxabsval">-</a>
  931. qh_maxabsval( normal, dim )
  932. return pointer to maximum absolute value of a dim vector
  933. returns NULL if dim=0
  934. */
  935. realT *qh_maxabsval(realT *normal, int dim) {
  936. realT maxval= -REALmax;
  937. realT *maxp= NULL, *colp, absval;
  938. int k;
  939. for (k=dim, colp= normal; k--; colp++) {
  940. absval= fabs_(*colp);
  941. if (absval > maxval) {
  942. maxval= absval;
  943. maxp= colp;
  944. }
  945. }
  946. return maxp;
  947. } /* maxabsval */
  948. /*-<a href="qh-geom_r.htm#TOC"
  949. >-------------------------------</a><a name="maxmin">-</a>
  950. qh_maxmin(qh, points, numpoints, dimension )
  951. return max/min points for each dimension
  952. determine max and min coordinates
  953. returns:
  954. returns a temporary set of max and min points
  955. may include duplicate points. Does not include qh.GOODpoint
  956. sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
  957. qh.MAXlastcoord, qh.MINlastcoord
  958. initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
  959. notes:
  960. loop duplicated in qh_detjoggle()
  961. design:
  962. initialize global precision variables
  963. checks definition of REAL...
  964. for each dimension
  965. for each point
  966. collect maximum and minimum point
  967. collect maximum of maximums and minimum of minimums
  968. determine qh.NEARzero for Gaussian Elimination
  969. */
  970. setT *qh_maxmin(qhT *qh, pointT *points, int numpoints, int dimension) {
  971. int k;
  972. realT maxcoord, temp;
  973. pointT *minimum, *maximum, *point, *pointtemp;
  974. setT *set;
  975. qh->max_outside= 0.0;
  976. qh->MAXabs_coord= 0.0;
  977. qh->MAXwidth= -REALmax;
  978. qh->MAXsumcoord= 0.0;
  979. qh->min_vertex= 0.0;
  980. qh->WAScoplanar= False;
  981. if (qh->ZEROcentrum)
  982. qh->ZEROall_ok= True;
  983. if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
  984. && REALmax > 0.0 && -REALmax < 0.0)
  985. ; /* all ok */
  986. else {
  987. qh_fprintf(qh, qh->ferr, 6011, "qhull error: one or more floating point constants in user_r.h are inconsistent. REALmin %g, -REALmax %g, 0.0, REALepsilon %g, REALmax %g\n",
  988. REALmin, -REALmax, REALepsilon, REALmax);
  989. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  990. }
  991. set= qh_settemp(qh, 2*dimension);
  992. trace1((qh, qh->ferr, 8082, "qh_maxmin: dim min max width nearzero min-point max-point\n"));
  993. for (k=0; k < dimension; k++) {
  994. if (points == qh->GOODpointp)
  995. minimum= maximum= points + dimension;
  996. else
  997. minimum= maximum= points;
  998. FORALLpoint_(qh, points, numpoints) {
  999. if (point == qh->GOODpointp)
  1000. continue;
  1001. if (maximum[k] < point[k])
  1002. maximum= point;
  1003. else if (minimum[k] > point[k])
  1004. minimum= point;
  1005. }
  1006. if (k == dimension-1) {
  1007. qh->MINlastcoord= minimum[k];
  1008. qh->MAXlastcoord= maximum[k];
  1009. }
  1010. if (qh->SCALElast && k == dimension-1)
  1011. maxcoord= qh->MAXabs_coord;
  1012. else {
  1013. maxcoord= fmax_(maximum[k], -minimum[k]);
  1014. if (qh->GOODpointp) {
  1015. temp= fmax_(qh->GOODpointp[k], -qh->GOODpointp[k]);
  1016. maximize_(maxcoord, temp);
  1017. }
  1018. temp= maximum[k] - minimum[k];
  1019. maximize_(qh->MAXwidth, temp);
  1020. }
  1021. maximize_(qh->MAXabs_coord, maxcoord);
  1022. qh->MAXsumcoord += maxcoord;
  1023. qh_setappend(qh, &set, minimum);
  1024. qh_setappend(qh, &set, maximum);
  1025. /* calculation of qh NEARzero is based on Golub & van Loan, 1983,
  1026. Eq. 4.4-13 for "Gaussian elimination with complete pivoting".
  1027. Golub & van Loan say that n^3 can be ignored and 10 be used in
  1028. place of rho */
  1029. qh->NEARzero[k]= 80 * qh->MAXsumcoord * REALepsilon;
  1030. trace1((qh, qh->ferr, 8106, " %3d % 14.8e % 14.8e % 14.8e %4.4e p%-9d p%-d\n",
  1031. k, minimum[k], maximum[k], maximum[k]-minimum[k], qh->NEARzero[k], qh_pointid(qh, minimum), qh_pointid(qh, maximum)));
  1032. if (qh->SCALElast && k == dimension-1)
  1033. trace1((qh, qh->ferr, 8107, " last coordinate scaled to (%4.4g, %4.4g), width %4.4e for option 'Qbb'\n",
  1034. qh->MAXabs_coord - qh->MAXwidth, qh->MAXabs_coord, qh->MAXwidth));
  1035. }
  1036. if (qh->IStracing >= 1)
  1037. qh_printpoints(qh, qh->ferr, "qh_maxmin: found the max and min points (by dim):", set);
  1038. return(set);
  1039. } /* maxmin */
  1040. /*-<a href="qh-geom_r.htm#TOC"
  1041. >-------------------------------</a><a name="maxouter">-</a>
  1042. qh_maxouter(qh)
  1043. return maximum distance from facet to outer plane
  1044. normally this is qh.max_outside+qh.DISTround
  1045. does not include qh.JOGGLEmax
  1046. see:
  1047. qh_outerinner()
  1048. notes:
  1049. need to add another qh.DISTround if testing actual point with computation
  1050. see qh_detmaxoutside for a qh_RATIO... target
  1051. for joggle:
  1052. qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
  1053. need to use Wnewvertexmax since could have a coplanar point for a high
  1054. facet that is replaced by a low facet
  1055. need to add qh.JOGGLEmax if testing input points
  1056. */
  1057. realT qh_maxouter(qhT *qh) {
  1058. realT dist;
  1059. dist= fmax_(qh->max_outside, qh->DISTround);
  1060. dist += qh->DISTround;
  1061. trace4((qh, qh->ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %4.4g, qh.max_outside is %4.4g\n", dist, qh->max_outside));
  1062. return dist;
  1063. } /* maxouter */
  1064. /*-<a href="qh-geom_r.htm#TOC"
  1065. >-------------------------------</a><a name="maxsimplex">-</a>
  1066. qh_maxsimplex(qh, dim, maxpoints, points, numpoints, simplex )
  1067. determines maximum simplex for a set of points
  1068. maxpoints is the subset of points with a min or max coordinate
  1069. may start with points already in simplex
  1070. skips qh.GOODpointp (assumes that it isn't in maxpoints)
  1071. returns:
  1072. simplex with dim+1 points
  1073. notes:
  1074. called by qh_initialvertices, qh_detvnorm, and qh_voronoi_center
  1075. requires qh.MAXwidth to estimate determinate for each vertex
  1076. assumes at least needed points in points
  1077. maximizes determinate for x,y,z,w, etc.
  1078. uses maxpoints as long as determinate is clearly non-zero
  1079. design:
  1080. initialize simplex with at least two points
  1081. (find points with max or min x coordinate)
  1082. create a simplex of dim+1 vertices as follows
  1083. add point from maxpoints that maximizes the determinate of the point and the simplex vertices
  1084. if last point and maxdet/prevdet < qh_RATIOmaxsimplex (3.0e-2)
  1085. flag maybe_falsenarrow
  1086. if no maxpoint or maxnearzero or maybe_falsenarrow
  1087. search all points for maximum determinate
  1088. early exit if maybe_falsenarrow and !maxnearzero and maxdet > prevdet
  1089. */
  1090. void qh_maxsimplex(qhT *qh, int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
  1091. pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
  1092. boolT nearzero, maxnearzero= False, maybe_falsenarrow;
  1093. int i, sizinit;
  1094. realT maxdet= -1.0, prevdet= -1.0, det, mincoord= REALmax, maxcoord= -REALmax, mindet, ratio, targetdet;
  1095. if (qh->MAXwidth <= 0.0) {
  1096. qh_fprintf(qh, qh->ferr, 6421, "qhull internal error (qh_maxsimplex): qh.MAXwidth required for qh_maxsimplex. Used to estimate determinate\n");
  1097. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1098. }
  1099. sizinit= qh_setsize(qh, *simplex);
  1100. if (sizinit >= 2) {
  1101. maxdet= pow(qh->MAXwidth, sizinit - 1);
  1102. }else {
  1103. if (qh_setsize(qh, maxpoints) >= 2) {
  1104. FOREACHpoint_(maxpoints) {
  1105. if (maxcoord < point[0]) {
  1106. maxcoord= point[0];
  1107. maxx= point;
  1108. }
  1109. if (mincoord > point[0]) {
  1110. mincoord= point[0];
  1111. minx= point;
  1112. }
  1113. }
  1114. }else {
  1115. FORALLpoint_(qh, points, numpoints) {
  1116. if (point == qh->GOODpointp)
  1117. continue;
  1118. if (maxcoord < point[0]) {
  1119. maxcoord= point[0];
  1120. maxx= point;
  1121. }
  1122. if (mincoord > point[0]) {
  1123. mincoord= point[0];
  1124. minx= point;
  1125. }
  1126. }
  1127. }
  1128. maxdet= maxcoord - mincoord;
  1129. qh_setunique(qh, simplex, minx);
  1130. if (qh_setsize(qh, *simplex) < 2)
  1131. qh_setunique(qh, simplex, maxx);
  1132. sizinit= qh_setsize(qh, *simplex);
  1133. if (sizinit < 2) {
  1134. qh_joggle_restart(qh, "input has same x coordinate");
  1135. if (zzval_(Zsetplane) > qh->hull_dim+1) {
  1136. qh_fprintf(qh, qh->ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center): %d points with the same x coordinate %4.4g\n",
  1137. qh_setsize(qh, maxpoints)+numpoints, mincoord);
  1138. qh_errexit(qh, qh_ERRprec, NULL, NULL);
  1139. }else {
  1140. qh_fprintf(qh, qh->ferr, 6013, "qhull input error: input is less than %d-dimensional since all points have the same x coordinate %4.4g\n",
  1141. qh->hull_dim, mincoord);
  1142. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  1143. }
  1144. }
  1145. }
  1146. for (i=sizinit; i < dim+1; i++) {
  1147. prevdet= maxdet;
  1148. maxpoint= NULL;
  1149. maxdet= -1.0;
  1150. FOREACHpoint_(maxpoints) {
  1151. if (!qh_setin(*simplex, point) && point != maxpoint) {
  1152. det= qh_detsimplex(qh, point, *simplex, i, &nearzero); /* retests maxpoints if duplicate or multiple iterations */
  1153. if ((det= fabs_(det)) > maxdet) {
  1154. maxdet= det;
  1155. maxpoint= point;
  1156. maxnearzero= nearzero;
  1157. }
  1158. }
  1159. }
  1160. maybe_falsenarrow= False;
  1161. ratio= 1.0;
  1162. targetdet= prevdet * qh->MAXwidth;
  1163. mindet= 10 * qh_RATIOmaxsimplex * targetdet;
  1164. if (maxdet > 0.0) {
  1165. ratio= maxdet / targetdet;
  1166. if (ratio < qh_RATIOmaxsimplex)
  1167. maybe_falsenarrow= True;
  1168. }
  1169. if (!maxpoint || maxnearzero || maybe_falsenarrow) {
  1170. zinc_(Zsearchpoints);
  1171. if (!maxpoint) {
  1172. trace0((qh, qh->ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex, better than mindet %4.4g, targetdet %4.4g\n",
  1173. i+1, mindet, targetdet));
  1174. }else if (qh->ALLpoints) {
  1175. trace0((qh, qh->ferr, 30, "qh_maxsimplex: searching all points ('Qs') for %d-th initial vertex, better than p%d det %4.4g, targetdet %4.4g, ratio %4.4g\n",
  1176. i+1, qh_pointid(qh, maxpoint), maxdet, targetdet, ratio));
  1177. }else if (maybe_falsenarrow) {
  1178. trace0((qh, qh->ferr, 17, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %4.4g and mindet %4.4g, ratio %4.4g\n",
  1179. i+1, qh_pointid(qh, maxpoint), maxdet, mindet, ratio));
  1180. }else {
  1181. trace0((qh, qh->ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g and mindet %4.4g, targetdet %4.4g\n",
  1182. i+1, qh_pointid(qh, maxpoint), maxdet, mindet, targetdet));
  1183. }
  1184. FORALLpoint_(qh, points, numpoints) {
  1185. if (point == qh->GOODpointp)
  1186. continue;
  1187. if (!qh_setin(maxpoints, point) && !qh_setin(*simplex, point)) {
  1188. det= qh_detsimplex(qh, point, *simplex, i, &nearzero);
  1189. if ((det= fabs_(det)) > maxdet) {
  1190. maxdet= det;
  1191. maxpoint= point;
  1192. maxnearzero= nearzero;
  1193. if (!maxnearzero && !qh->ALLpoints && maxdet > mindet)
  1194. break;
  1195. }
  1196. }
  1197. }
  1198. } /* !maxpoint */
  1199. if (!maxpoint) {
  1200. qh_fprintf(qh, qh->ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
  1201. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1202. }
  1203. qh_setappend(qh, simplex, maxpoint);
  1204. trace1((qh, qh->ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%4.4g, targetdet=%4.4g, mindet=%4.4g\n",
  1205. qh_pointid(qh, maxpoint), i+1, maxdet, prevdet * qh->MAXwidth, mindet));
  1206. } /* i */
  1207. } /* maxsimplex */
  1208. /*-<a href="qh-geom_r.htm#TOC"
  1209. >-------------------------------</a><a name="minabsval">-</a>
  1210. qh_minabsval( normal, dim )
  1211. return minimum absolute value of a dim vector
  1212. */
  1213. realT qh_minabsval(realT *normal, int dim) {
  1214. realT minval= 0;
  1215. realT maxval= 0;
  1216. realT *colp;
  1217. int k;
  1218. for (k=dim, colp=normal; k--; colp++) {
  1219. maximize_(maxval, *colp);
  1220. minimize_(minval, *colp);
  1221. }
  1222. return fmax_(maxval, -minval);
  1223. } /* minabsval */
  1224. /*-<a href="qh-geom_r.htm#TOC"
  1225. >-------------------------------</a><a name="mindiff">-</a>
  1226. qh_mindif(qh, vecA, vecB, dim )
  1227. return index of min abs. difference of two vectors
  1228. */
  1229. int qh_mindiff(realT *vecA, realT *vecB, int dim) {
  1230. realT mindiff= REALmax, diff;
  1231. realT *vecAp= vecA, *vecBp= vecB;
  1232. int k, mink= 0;
  1233. for (k=0; k < dim; k++) {
  1234. diff= *vecAp++ - *vecBp++;
  1235. diff= fabs_(diff);
  1236. if (diff < mindiff) {
  1237. mindiff= diff;
  1238. mink= k;
  1239. }
  1240. }
  1241. return mink;
  1242. } /* mindiff */
  1243. /*-<a href="qh-geom_r.htm#TOC"
  1244. >-------------------------------</a><a name="orientoutside">-</a>
  1245. qh_orientoutside(qh, facet )
  1246. make facet outside oriented via qh.interior_point
  1247. returns:
  1248. True if facet reversed orientation.
  1249. */
  1250. boolT qh_orientoutside(qhT *qh, facetT *facet) {
  1251. int k;
  1252. realT dist;
  1253. qh_distplane(qh, qh->interior_point, facet, &dist);
  1254. if (dist > 0) {
  1255. for (k=qh->hull_dim; k--; )
  1256. facet->normal[k]= -facet->normal[k];
  1257. facet->offset= -facet->offset;
  1258. return True;
  1259. }
  1260. return False;
  1261. } /* orientoutside */
  1262. /*-<a href="qh-geom_r.htm#TOC"
  1263. >-------------------------------</a><a name="outerinner">-</a>
  1264. qh_outerinner(qh, facet, outerplane, innerplane )
  1265. if facet and qh.maxoutdone (i.e., qh_check_maxout)
  1266. returns outer and inner plane for facet
  1267. else
  1268. returns maximum outer and inner plane
  1269. accounts for qh.JOGGLEmax
  1270. see:
  1271. qh_maxouter(qh), qh_check_bestdist(), qh_check_points()
  1272. notes:
  1273. outerplaner or innerplane may be NULL
  1274. facet is const
  1275. Does not error (QhullFacet)
  1276. includes qh.DISTround for actual points
  1277. adds another qh.DISTround if testing with floating point arithmetic
  1278. */
  1279. void qh_outerinner(qhT *qh, facetT *facet, realT *outerplane, realT *innerplane) {
  1280. realT dist, mindist;
  1281. vertexT *vertex, **vertexp;
  1282. if (outerplane) {
  1283. if (!qh_MAXoutside || !facet || !qh->maxoutdone) {
  1284. *outerplane= qh_maxouter(qh); /* includes qh.DISTround */
  1285. }else { /* qh_MAXoutside ... */
  1286. #if qh_MAXoutside
  1287. *outerplane= facet->maxoutside + qh->DISTround;
  1288. #endif
  1289. }
  1290. if (qh->JOGGLEmax < REALmax/2)
  1291. *outerplane += qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
  1292. }
  1293. if (innerplane) {
  1294. if (facet) {
  1295. mindist= REALmax;
  1296. FOREACHvertex_(facet->vertices) {
  1297. zinc_(Zdistio);
  1298. qh_distplane(qh, vertex->point, facet, &dist);
  1299. minimize_(mindist, dist);
  1300. }
  1301. *innerplane= mindist - qh->DISTround;
  1302. }else
  1303. *innerplane= qh->min_vertex - qh->DISTround;
  1304. if (qh->JOGGLEmax < REALmax/2)
  1305. *innerplane -= qh->JOGGLEmax * sqrt((realT)qh->hull_dim);
  1306. }
  1307. } /* outerinner */
  1308. /*-<a href="qh-geom_r.htm#TOC"
  1309. >-------------------------------</a><a name="pointdist">-</a>
  1310. qh_pointdist( point1, point2, dim )
  1311. return distance between two points
  1312. notes:
  1313. returns distance squared if 'dim' is negative
  1314. */
  1315. coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
  1316. coordT dist, diff;
  1317. int k;
  1318. dist= 0.0;
  1319. for (k= (dim > 0 ? dim : -dim); k--; ) {
  1320. diff= *point1++ - *point2++;
  1321. dist += diff * diff;
  1322. }
  1323. if (dim > 0)
  1324. return(sqrt(dist));
  1325. return dist;
  1326. } /* pointdist */
  1327. /*-<a href="qh-geom_r.htm#TOC"
  1328. >-------------------------------</a><a name="printmatrix">-</a>
  1329. qh_printmatrix(qh, fp, string, rows, numrow, numcol )
  1330. print matrix to fp given by row vectors
  1331. print string as header
  1332. qh may be NULL if fp is defined
  1333. notes:
  1334. print a vector by qh_printmatrix(qh, fp, "", &vect, 1, len)
  1335. */
  1336. void qh_printmatrix(qhT *qh, FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
  1337. realT *rowp;
  1338. realT r; /*bug fix*/
  1339. int i,k;
  1340. qh_fprintf(qh, fp, 9001, "%s\n", string);
  1341. for (i=0; i < numrow; i++) {
  1342. rowp= rows[i];
  1343. for (k=0; k < numcol; k++) {
  1344. r= *rowp++;
  1345. qh_fprintf(qh, fp, 9002, "%6.3g ", r);
  1346. }
  1347. qh_fprintf(qh, fp, 9003, "\n");
  1348. }
  1349. } /* printmatrix */
  1350. /*-<a href="qh-geom_r.htm#TOC"
  1351. >-------------------------------</a><a name="printpoints">-</a>
  1352. qh_printpoints(qh, fp, string, points )
  1353. print pointids to fp for a set of points
  1354. if string, prints string and 'p' point ids
  1355. */
  1356. void qh_printpoints(qhT *qh, FILE *fp, const char *string, setT *points) {
  1357. pointT *point, **pointp;
  1358. if (string) {
  1359. qh_fprintf(qh, fp, 9004, "%s", string);
  1360. FOREACHpoint_(points)
  1361. qh_fprintf(qh, fp, 9005, " p%d", qh_pointid(qh, point));
  1362. qh_fprintf(qh, fp, 9006, "\n");
  1363. }else {
  1364. FOREACHpoint_(points)
  1365. qh_fprintf(qh, fp, 9007, " %d", qh_pointid(qh, point));
  1366. qh_fprintf(qh, fp, 9008, "\n");
  1367. }
  1368. } /* printpoints */
  1369. /*-<a href="qh-geom_r.htm#TOC"
  1370. >-------------------------------</a><a name="projectinput">-</a>
  1371. qh_projectinput(qh)
  1372. project input points using qh.lower_bound/upper_bound and qh->DELAUNAY
  1373. if qh.lower_bound[k]=qh.upper_bound[k]= 0,
  1374. removes dimension k
  1375. if halfspace intersection
  1376. removes dimension k from qh.feasible_point
  1377. input points in qh->first_point, num_points, input_dim
  1378. returns:
  1379. new point array in qh->first_point of qh->hull_dim coordinates
  1380. sets qh->POINTSmalloc
  1381. if qh->DELAUNAY
  1382. projects points to paraboloid
  1383. lowbound/highbound is also projected
  1384. if qh->ATinfinity
  1385. adds point "at-infinity"
  1386. if qh->POINTSmalloc
  1387. frees old point array
  1388. notes:
  1389. checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
  1390. design:
  1391. sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
  1392. determines newdim and newnum for qh->hull_dim and qh->num_points
  1393. projects points to newpoints
  1394. projects qh.lower_bound to itself
  1395. projects qh.upper_bound to itself
  1396. if qh->DELAUNAY
  1397. if qh->ATINFINITY
  1398. projects points to paraboloid
  1399. computes "infinity" point as vertex average and 10% above all points
  1400. else
  1401. uses qh_setdelaunay to project points to paraboloid
  1402. */
  1403. void qh_projectinput(qhT *qh) {
  1404. int k,i;
  1405. int newdim= qh->input_dim, newnum= qh->num_points;
  1406. signed char *project;
  1407. int projectsize= (qh->input_dim + 1) * (int)sizeof(*project);
  1408. pointT *newpoints, *coord, *infinity;
  1409. realT paraboloid, maxboloid= 0;
  1410. project= (signed char *)qh_memalloc(qh, projectsize);
  1411. memset((char *)project, 0, (size_t)projectsize);
  1412. for (k=0; k < qh->input_dim; k++) { /* skip Delaunay bound */
  1413. if (qh->lower_bound[k] == 0.0 && qh->upper_bound[k] == 0.0) {
  1414. project[k]= -1;
  1415. newdim--;
  1416. }
  1417. }
  1418. if (qh->DELAUNAY) {
  1419. project[k]= 1;
  1420. newdim++;
  1421. if (qh->ATinfinity)
  1422. newnum++;
  1423. }
  1424. if (newdim != qh->hull_dim) {
  1425. qh_memfree(qh, project, projectsize);
  1426. qh_fprintf(qh, qh->ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh->hull_dim);
  1427. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1428. }
  1429. if (!(newpoints= qh->temp_malloc= (coordT *)qh_malloc((size_t)(newnum * newdim) * sizeof(coordT)))) {
  1430. qh_memfree(qh, project, projectsize);
  1431. qh_fprintf(qh, qh->ferr, 6016, "qhull error: insufficient memory to project %d points\n",
  1432. qh->num_points);
  1433. qh_errexit(qh, qh_ERRmem, NULL, NULL);
  1434. }
  1435. /* qh_projectpoints throws error if mismatched dimensions */
  1436. qh_projectpoints(qh, project, qh->input_dim+1, qh->first_point,
  1437. qh->num_points, qh->input_dim, newpoints, newdim);
  1438. trace1((qh, qh->ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
  1439. qh_projectpoints(qh, project, qh->input_dim+1, qh->lower_bound,
  1440. 1, qh->input_dim+1, qh->lower_bound, newdim+1);
  1441. qh_projectpoints(qh, project, qh->input_dim+1, qh->upper_bound,
  1442. 1, qh->input_dim+1, qh->upper_bound, newdim+1);
  1443. if (qh->HALFspace) {
  1444. if (!qh->feasible_point) {
  1445. qh_memfree(qh, project, projectsize);
  1446. qh_fprintf(qh, qh->ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
  1447. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1448. }
  1449. qh_projectpoints(qh, project, qh->input_dim, qh->feasible_point,
  1450. 1, qh->input_dim, qh->feasible_point, newdim);
  1451. }
  1452. qh_memfree(qh, project, projectsize);
  1453. if (qh->POINTSmalloc)
  1454. qh_free(qh->first_point);
  1455. qh->first_point= newpoints;
  1456. qh->POINTSmalloc= True;
  1457. qh->temp_malloc= NULL;
  1458. if (qh->DELAUNAY && qh->ATinfinity) {
  1459. coord= qh->first_point;
  1460. infinity= qh->first_point + qh->hull_dim * qh->num_points;
  1461. for (k=qh->hull_dim-1; k--; )
  1462. infinity[k]= 0.0;
  1463. for (i=qh->num_points; i--; ) {
  1464. paraboloid= 0.0;
  1465. for (k=0; k < qh->hull_dim-1; k++) {
  1466. paraboloid += *coord * *coord;
  1467. infinity[k] += *coord;
  1468. coord++;
  1469. }
  1470. *(coord++)= paraboloid;
  1471. maximize_(maxboloid, paraboloid);
  1472. }
  1473. /* coord == infinity */
  1474. for (k=qh->hull_dim-1; k--; )
  1475. *(coord++) /= qh->num_points;
  1476. *(coord++)= maxboloid * 1.1;
  1477. qh->num_points++;
  1478. trace0((qh, qh->ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
  1479. }else if (qh->DELAUNAY) /* !qh->ATinfinity */
  1480. qh_setdelaunay(qh, qh->hull_dim, qh->num_points, qh->first_point);
  1481. } /* projectinput */
  1482. /*-<a href="qh-geom_r.htm#TOC"
  1483. >-------------------------------</a><a name="projectpoints">-</a>
  1484. qh_projectpoints(qh, project, n, points, numpoints, dim, newpoints, newdim )
  1485. project points/numpoints/dim to newpoints/newdim
  1486. if project[k] == -1
  1487. delete dimension k
  1488. if project[k] == 1
  1489. add dimension k by duplicating previous column
  1490. n is size of project
  1491. notes:
  1492. newpoints may be points if only adding dimension at end
  1493. design:
  1494. check that 'project' and 'newdim' agree
  1495. for each dimension
  1496. if project == -1
  1497. skip dimension
  1498. else
  1499. determine start of column in newpoints
  1500. determine start of column in points
  1501. if project == +1, duplicate previous column
  1502. copy dimension (column) from points to newpoints
  1503. */
  1504. void qh_projectpoints(qhT *qh, signed char *project, int n, realT *points,
  1505. int numpoints, int dim, realT *newpoints, int newdim) {
  1506. int testdim= dim, oldk=0, newk=0, i,j=0,k;
  1507. realT *newp, *oldp;
  1508. for (k=0; k < n; k++)
  1509. testdim += project[k];
  1510. if (testdim != newdim) {
  1511. qh_fprintf(qh, qh->ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
  1512. newdim, testdim);
  1513. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1514. }
  1515. for (j=0; j<n; j++) {
  1516. if (project[j] == -1)
  1517. oldk++;
  1518. else {
  1519. newp= newpoints+newk++;
  1520. if (project[j] == +1) {
  1521. if (oldk >= dim)
  1522. continue;
  1523. oldp= points+oldk;
  1524. }else
  1525. oldp= points+oldk++;
  1526. for (i=numpoints; i--; ) {
  1527. *newp= *oldp;
  1528. newp += newdim;
  1529. oldp += dim;
  1530. }
  1531. }
  1532. if (oldk >= dim)
  1533. break;
  1534. }
  1535. trace1((qh, qh->ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
  1536. numpoints, dim, newdim));
  1537. } /* projectpoints */
  1538. /*-<a href="qh-geom_r.htm#TOC"
  1539. >-------------------------------</a><a name="rotateinput">-</a>
  1540. qh_rotateinput(qh, rows )
  1541. rotate input using row matrix
  1542. input points given by qh->first_point, num_points, hull_dim
  1543. assumes rows[dim] is a scratch buffer
  1544. if qh->POINTSmalloc, overwrites input points, else mallocs a new array
  1545. returns:
  1546. rotated input
  1547. sets qh->POINTSmalloc
  1548. design:
  1549. see qh_rotatepoints
  1550. */
  1551. void qh_rotateinput(qhT *qh, realT **rows) {
  1552. if (!qh->POINTSmalloc) {
  1553. qh->first_point= qh_copypoints(qh, qh->first_point, qh->num_points, qh->hull_dim);
  1554. qh->POINTSmalloc= True;
  1555. }
  1556. qh_rotatepoints(qh, qh->first_point, qh->num_points, qh->hull_dim, rows);
  1557. } /* rotateinput */
  1558. /*-<a href="qh-geom_r.htm#TOC"
  1559. >-------------------------------</a><a name="rotatepoints">-</a>
  1560. qh_rotatepoints(qh, points, numpoints, dim, row )
  1561. rotate numpoints points by a d-dim row matrix
  1562. assumes rows[dim] is a scratch buffer
  1563. returns:
  1564. rotated points in place
  1565. design:
  1566. for each point
  1567. for each coordinate
  1568. use row[dim] to compute partial inner product
  1569. for each coordinate
  1570. rotate by partial inner product
  1571. */
  1572. void qh_rotatepoints(qhT *qh, realT *points, int numpoints, int dim, realT **row) {
  1573. realT *point, *rowi, *coord= NULL, sum, *newval;
  1574. int i,j,k;
  1575. if (qh->IStracing >= 1)
  1576. qh_printmatrix(qh, qh->ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
  1577. for (point=points, j=numpoints; j--; point += dim) {
  1578. newval= row[dim];
  1579. for (i=0; i < dim; i++) {
  1580. rowi= row[i];
  1581. coord= point;
  1582. for (sum=0.0, k=dim; k--; )
  1583. sum += *rowi++ * *coord++;
  1584. *(newval++)= sum;
  1585. }
  1586. for (k=dim; k--; )
  1587. *(--coord)= *(--newval);
  1588. }
  1589. } /* rotatepoints */
  1590. /*-<a href="qh-geom_r.htm#TOC"
  1591. >-------------------------------</a><a name="scaleinput">-</a>
  1592. qh_scaleinput(qh)
  1593. scale input points using qh->low_bound/high_bound
  1594. input points given by qh->first_point, num_points, hull_dim
  1595. if qh->POINTSmalloc, overwrites input points, else mallocs a new array
  1596. returns:
  1597. scales coordinates of points to low_bound[k], high_bound[k]
  1598. sets qh->POINTSmalloc
  1599. design:
  1600. see qh_scalepoints
  1601. */
  1602. void qh_scaleinput(qhT *qh) {
  1603. if (!qh->POINTSmalloc) {
  1604. qh->first_point= qh_copypoints(qh, qh->first_point, qh->num_points, qh->hull_dim);
  1605. qh->POINTSmalloc= True;
  1606. }
  1607. qh_scalepoints(qh, qh->first_point, qh->num_points, qh->hull_dim,
  1608. qh->lower_bound, qh->upper_bound);
  1609. } /* scaleinput */
  1610. /*-<a href="qh-geom_r.htm#TOC"
  1611. >-------------------------------</a><a name="scalelast">-</a>
  1612. qh_scalelast(qh, points, numpoints, dim, low, high, newhigh )
  1613. scale last coordinate to [0.0, newhigh], for Delaunay triangulation
  1614. input points given by points, numpoints, dim
  1615. returns:
  1616. changes scale of last coordinate from [low, high] to [0.0, newhigh]
  1617. overwrites last coordinate of each point
  1618. saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
  1619. notes:
  1620. to reduce precision issues, qh_scalelast makes the last coordinate similar to other coordinates
  1621. the last coordinate for Delaunay triangulation is the sum of squares of input coordinates
  1622. note that the range [0.0, newwidth] is wrong for narrow distributions with large positive coordinates (e.g., [995933.64, 995963.48])
  1623. when called by qh_setdelaunay, low/high may not match the data passed to qh_setdelaunay
  1624. design:
  1625. compute scale and shift factors
  1626. apply to last coordinate of each point
  1627. */
  1628. void qh_scalelast(qhT *qh, coordT *points, int numpoints, int dim, coordT low,
  1629. coordT high, coordT newhigh) {
  1630. realT scale, shift;
  1631. coordT *coord, newlow;
  1632. int i;
  1633. boolT nearzero= False;
  1634. newlow= 0.0;
  1635. trace4((qh, qh->ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [%2.2g, %2.2g]\n",
  1636. low, high, newlow, newhigh));
  1637. qh->last_low= low;
  1638. qh->last_high= high;
  1639. qh->last_newhigh= newhigh;
  1640. scale= qh_divzero(newhigh - newlow, high - low,
  1641. qh->MINdenom_1, &nearzero);
  1642. if (nearzero) {
  1643. if (qh->DELAUNAY)
  1644. qh_fprintf(qh, qh->ferr, 6019, "qhull input error (qh_scalelast): can not scale last coordinate to [%4.4g, %4.4g]. Input is cocircular or cospherical. Use option 'Qz' to add a point at infinity.\n",
  1645. newlow, newhigh);
  1646. else
  1647. qh_fprintf(qh, qh->ferr, 6020, "qhull input error (qh_scalelast): can not scale last coordinate to [%4.4g, %4.4g]. New bounds are too wide for compared to existing bounds [%4.4g, %4.4g] (width %4.4g)\n",
  1648. newlow, newhigh, low, high, high-low);
  1649. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  1650. }
  1651. shift= newlow - low * scale;
  1652. coord= points + dim - 1;
  1653. for (i=numpoints; i--; coord += dim)
  1654. *coord= *coord * scale + shift;
  1655. } /* scalelast */
  1656. /*-<a href="qh-geom_r.htm#TOC"
  1657. >-------------------------------</a><a name="scalepoints">-</a>
  1658. qh_scalepoints(qh, points, numpoints, dim, newlows, newhighs )
  1659. scale points to new lowbound and highbound
  1660. retains old bound when newlow= -REALmax or newhigh= +REALmax
  1661. returns:
  1662. scaled points
  1663. overwrites old points
  1664. design:
  1665. for each coordinate
  1666. compute current low and high bound
  1667. compute scale and shift factors
  1668. scale all points
  1669. enforce new low and high bound for all points
  1670. */
  1671. void qh_scalepoints(qhT *qh, pointT *points, int numpoints, int dim,
  1672. realT *newlows, realT *newhighs) {
  1673. int i,k;
  1674. realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
  1675. boolT nearzero= False;
  1676. for (k=0; k < dim; k++) {
  1677. newhigh= newhighs[k];
  1678. newlow= newlows[k];
  1679. if (newhigh > REALmax/2 && newlow < -REALmax/2)
  1680. continue;
  1681. low= REALmax;
  1682. high= -REALmax;
  1683. for (i=numpoints, coord=points+k; i--; coord += dim) {
  1684. minimize_(low, *coord);
  1685. maximize_(high, *coord);
  1686. }
  1687. if (newhigh > REALmax/2)
  1688. newhigh= high;
  1689. if (newlow < -REALmax/2)
  1690. newlow= low;
  1691. if (qh->DELAUNAY && k == dim-1 && newhigh < newlow) {
  1692. qh_fprintf(qh, qh->ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
  1693. k, k, newhigh, newlow);
  1694. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  1695. }
  1696. scale= qh_divzero(newhigh - newlow, high - low,
  1697. qh->MINdenom_1, &nearzero);
  1698. if (nearzero) {
  1699. qh_fprintf(qh, qh->ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
  1700. k, newlow, newhigh, low, high);
  1701. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  1702. }
  1703. shift= (newlow * high - low * newhigh)/(high-low);
  1704. coord= points+k;
  1705. for (i=numpoints; i--; coord += dim)
  1706. *coord= *coord * scale + shift;
  1707. coord= points+k;
  1708. if (newlow < newhigh) {
  1709. mincoord= newlow;
  1710. maxcoord= newhigh;
  1711. }else {
  1712. mincoord= newhigh;
  1713. maxcoord= newlow;
  1714. }
  1715. for (i=numpoints; i--; coord += dim) {
  1716. minimize_(*coord, maxcoord); /* because of roundoff error */
  1717. maximize_(*coord, mincoord);
  1718. }
  1719. trace0((qh, qh->ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
  1720. k, low, high, newlow, newhigh, numpoints, scale, shift));
  1721. }
  1722. } /* scalepoints */
  1723. /*-<a href="qh-geom_r.htm#TOC"
  1724. >-------------------------------</a><a name="setdelaunay">-</a>
  1725. qh_setdelaunay(qh, dim, count, points )
  1726. project count points to dim-d paraboloid for Delaunay triangulation
  1727. dim is one more than the dimension of the input set
  1728. assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
  1729. points is a dim*count realT array. The first dim-1 coordinates
  1730. are the coordinates of the first input point. array[dim] is
  1731. the first coordinate of the second input point. array[2*dim] is
  1732. the first coordinate of the third input point.
  1733. if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
  1734. calls qh_scalelast to scale the last coordinate the same as the other points
  1735. returns:
  1736. for each point
  1737. sets point[dim-1] to sum of squares of coordinates
  1738. scale points to 'Qbb' if needed
  1739. notes:
  1740. to project one point, use
  1741. qh_setdelaunay(qh, qh->hull_dim, 1, point)
  1742. Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
  1743. the coordinates after the original projection.
  1744. */
  1745. void qh_setdelaunay(qhT *qh, int dim, int count, pointT *points) {
  1746. int i, k;
  1747. coordT *coordp, coord;
  1748. realT paraboloid;
  1749. trace0((qh, qh->ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
  1750. coordp= points;
  1751. for (i=0; i < count; i++) {
  1752. coord= *coordp++;
  1753. paraboloid= coord*coord;
  1754. for (k=dim-2; k--; ) {
  1755. coord= *coordp++;
  1756. paraboloid += coord*coord;
  1757. }
  1758. *coordp++= paraboloid;
  1759. }
  1760. if (qh->last_low < REALmax/2)
  1761. qh_scalelast(qh, points, count, dim, qh->last_low, qh->last_high, qh->last_newhigh);
  1762. } /* setdelaunay */
  1763. /*-<a href="qh-geom_r.htm#TOC"
  1764. >-------------------------------</a><a name="sethalfspace">-</a>
  1765. qh_sethalfspace(qh, dim, coords, nextp, normal, offset, feasible )
  1766. set point to dual of halfspace relative to feasible point
  1767. halfspace is normal coefficients and offset.
  1768. returns:
  1769. false and prints error if feasible point is outside of hull
  1770. overwrites coordinates for point at dim coords
  1771. nextp= next point (coords)
  1772. does not call qh_errexit
  1773. design:
  1774. compute distance from feasible point to halfspace
  1775. divide each normal coefficient by -dist
  1776. */
  1777. boolT qh_sethalfspace(qhT *qh, int dim, coordT *coords, coordT **nextp,
  1778. coordT *normal, coordT *offset, coordT *feasible) {
  1779. coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
  1780. realT dist;
  1781. realT r; /*bug fix*/
  1782. int k;
  1783. boolT zerodiv;
  1784. dist= *offset;
  1785. for (k=dim; k--; )
  1786. dist += *(normp++) * *(feasiblep++);
  1787. if (dist > 0)
  1788. goto LABELerroroutside;
  1789. normp= normal;
  1790. if (dist < -qh->MINdenom) {
  1791. for (k=dim; k--; )
  1792. *(coordp++)= *(normp++) / -dist;
  1793. }else {
  1794. for (k=dim; k--; ) {
  1795. *(coordp++)= qh_divzero(*(normp++), -dist, qh->MINdenom_1, &zerodiv);
  1796. if (zerodiv)
  1797. goto LABELerroroutside;
  1798. }
  1799. }
  1800. *nextp= coordp;
  1801. #ifndef qh_NOtrace
  1802. if (qh->IStracing >= 4) {
  1803. qh_fprintf(qh, qh->ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
  1804. for (k=dim, coordp=coords; k--; ) {
  1805. r= *coordp++;
  1806. qh_fprintf(qh, qh->ferr, 8022, " %6.2g", r);
  1807. }
  1808. qh_fprintf(qh, qh->ferr, 8023, "\n");
  1809. }
  1810. #endif
  1811. return True;
  1812. LABELerroroutside:
  1813. feasiblep= feasible;
  1814. normp= normal;
  1815. qh_fprintf(qh, qh->ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
  1816. for (k=dim; k--; )
  1817. qh_fprintf(qh, qh->ferr, 8024, qh_REAL_1, r=*(feasiblep++));
  1818. qh_fprintf(qh, qh->ferr, 8025, "\n halfspace: ");
  1819. for (k=dim; k--; )
  1820. qh_fprintf(qh, qh->ferr, 8026, qh_REAL_1, r=*(normp++));
  1821. qh_fprintf(qh, qh->ferr, 8027, "\n at offset: ");
  1822. qh_fprintf(qh, qh->ferr, 8028, qh_REAL_1, *offset);
  1823. qh_fprintf(qh, qh->ferr, 8029, " and distance: ");
  1824. qh_fprintf(qh, qh->ferr, 8030, qh_REAL_1, dist);
  1825. qh_fprintf(qh, qh->ferr, 8031, "\n");
  1826. return False;
  1827. } /* sethalfspace */
  1828. /*-<a href="qh-geom_r.htm#TOC"
  1829. >-------------------------------</a><a name="sethalfspace_all">-</a>
  1830. qh_sethalfspace_all(qh, dim, count, halfspaces, feasible )
  1831. generate dual for halfspace intersection with feasible point
  1832. array of count halfspaces
  1833. each halfspace is normal coefficients followed by offset
  1834. the origin is inside the halfspace if the offset is negative
  1835. feasible is a point inside all halfspaces (http://www.qhull.org/html/qhalf.htm#notes)
  1836. returns:
  1837. malloc'd array of count X dim-1 points
  1838. notes:
  1839. call before qh_init_B or qh_initqhull_globals
  1840. free memory when done
  1841. unused/untested code: please email bradb@shore.net if this works ok for you
  1842. if using option 'Fp', qh.feasible_point must be set (e.g., to 'feasible')
  1843. qh->feasible_point is a malloc'd array that is freed by qh_freebuffers.
  1844. design:
  1845. see qh_sethalfspace
  1846. */
  1847. coordT *qh_sethalfspace_all(qhT *qh, int dim, int count, coordT *halfspaces, pointT *feasible) {
  1848. int i, newdim;
  1849. pointT *newpoints;
  1850. coordT *coordp, *normalp, *offsetp;
  1851. trace0((qh, qh->ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
  1852. newdim= dim - 1;
  1853. if (!(newpoints= (coordT *)qh_malloc((size_t)(count * newdim) * sizeof(coordT)))){
  1854. qh_fprintf(qh, qh->ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
  1855. count);
  1856. qh_errexit(qh, qh_ERRmem, NULL, NULL);
  1857. }
  1858. coordp= newpoints;
  1859. normalp= halfspaces;
  1860. for (i=0; i < count; i++) {
  1861. offsetp= normalp + newdim;
  1862. if (!qh_sethalfspace(qh, newdim, coordp, &coordp, normalp, offsetp, feasible)) {
  1863. qh_free(newpoints); /* feasible is not inside halfspace as reported by qh_sethalfspace */
  1864. qh_fprintf(qh, qh->ferr, 8032, "The halfspace was at index %d\n", i);
  1865. qh_errexit(qh, qh_ERRinput, NULL, NULL);
  1866. }
  1867. normalp= offsetp + 1;
  1868. }
  1869. return newpoints;
  1870. } /* sethalfspace_all */
  1871. /*-<a href="qh-geom_r.htm#TOC"
  1872. >-------------------------------</a><a name="sharpnewfacets">-</a>
  1873. qh_sharpnewfacets(qh)
  1874. returns:
  1875. true if could be an acute angle (facets in different quadrants)
  1876. notes:
  1877. for qh_findbest
  1878. design:
  1879. for all facets on qh.newfacet_list
  1880. if two facets are in different quadrants
  1881. set issharp
  1882. */
  1883. boolT qh_sharpnewfacets(qhT *qh) {
  1884. facetT *facet;
  1885. boolT issharp= False;
  1886. int *quadrant, k;
  1887. quadrant= (int *)qh_memalloc(qh, qh->hull_dim * (int)sizeof(int));
  1888. FORALLfacet_(qh->newfacet_list) {
  1889. if (facet == qh->newfacet_list) {
  1890. for (k=qh->hull_dim; k--; )
  1891. quadrant[ k]= (facet->normal[ k] > 0);
  1892. }else {
  1893. for (k=qh->hull_dim; k--; ) {
  1894. if (quadrant[ k] != (facet->normal[ k] > 0)) {
  1895. issharp= True;
  1896. break;
  1897. }
  1898. }
  1899. }
  1900. if (issharp)
  1901. break;
  1902. }
  1903. qh_memfree(qh, quadrant, qh->hull_dim * (int)sizeof(int));
  1904. trace3((qh, qh->ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
  1905. return issharp;
  1906. } /* sharpnewfacets */
  1907. /*-<a href="qh-geom_r.htm#TOC"
  1908. >-------------------------------</a><a name="vertex_bestdist">-</a>
  1909. qh_vertex_bestdist(qh, vertices )
  1910. qh_vertex_bestdist2(qh, vertices, vertexp, vertexp2 )
  1911. return nearest distance between vertices
  1912. optionally returns vertex and vertex2
  1913. notes:
  1914. called by qh_partitioncoplanar, qh_mergefacet, qh_check_maxout, qh_checkpoint
  1915. */
  1916. coordT qh_vertex_bestdist(qhT *qh, setT *vertices) {
  1917. vertexT *vertex, *vertex2;
  1918. return qh_vertex_bestdist2(qh, vertices, &vertex, &vertex2);
  1919. } /* vertex_bestdist */
  1920. coordT qh_vertex_bestdist2(qhT *qh, setT *vertices, vertexT **vertexp/*= NULL*/, vertexT **vertexp2/*= NULL*/) {
  1921. vertexT *vertex, *vertexA, *bestvertex= NULL, *bestvertex2= NULL;
  1922. coordT dist, bestdist= REALmax;
  1923. int k, vertex_i, vertex_n;
  1924. FOREACHvertex_i_(qh, vertices) {
  1925. for (k= vertex_i+1; k < vertex_n; k++) {
  1926. vertexA= SETelemt_(vertices, k, vertexT);
  1927. dist= qh_pointdist(vertex->point, vertexA->point, -qh->hull_dim);
  1928. if (dist < bestdist) {
  1929. bestdist= dist;
  1930. bestvertex= vertex;
  1931. bestvertex2= vertexA;
  1932. }
  1933. }
  1934. }
  1935. *vertexp= bestvertex;
  1936. *vertexp2= bestvertex2;
  1937. return sqrt(bestdist);
  1938. } /* vertex_bestdist */
  1939. /*-<a href="qh-geom_r.htm#TOC"
  1940. >-------------------------------</a><a name="voronoi_center">-</a>
  1941. qh_voronoi_center(qh, dim, points )
  1942. return Voronoi center for a set of points
  1943. dim is the orginal dimension of the points
  1944. gh.gm_matrix/qh.gm_row are scratch buffers
  1945. returns:
  1946. center as a temporary point (qh_memalloc)
  1947. if non-simplicial,
  1948. returns center for max simplex of points
  1949. notes:
  1950. only called by qh_facetcenter
  1951. from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
  1952. design:
  1953. if non-simplicial
  1954. determine max simplex for points
  1955. translate point0 of simplex to origin
  1956. compute sum of squares of diagonal
  1957. compute determinate
  1958. compute Voronoi center (see Bowyer & Woodwark)
  1959. */
  1960. pointT *qh_voronoi_center(qhT *qh, int dim, setT *points) {
  1961. pointT *point, **pointp, *point0;
  1962. pointT *center= (pointT *)qh_memalloc(qh, qh->center_size);
  1963. setT *simplex;
  1964. int i, j, k, size= qh_setsize(qh, points);
  1965. coordT *gmcoord;
  1966. realT *diffp, sum2, *sum2row, *sum2p, det, factor;
  1967. boolT nearzero, infinite;
  1968. if (size == dim+1)
  1969. simplex= points;
  1970. else if (size < dim+1) {
  1971. qh_memfree(qh, center, qh->center_size);
  1972. qh_fprintf(qh, qh->ferr, 6025, "qhull internal error (qh_voronoi_center): need at least %d points to construct a Voronoi center\n",
  1973. dim+1);
  1974. qh_errexit(qh, qh_ERRqhull, NULL, NULL);
  1975. simplex= points; /* never executed -- avoids warning */
  1976. }else {
  1977. simplex= qh_settemp(qh, dim+1);
  1978. qh_maxsimplex(qh, dim, points, NULL, 0, &simplex);
  1979. }
  1980. point0= SETfirstt_(simplex, pointT);
  1981. gmcoord= qh->gm_matrix;
  1982. for (k=0; k < dim; k++) {
  1983. qh->gm_row[k]= gmcoord;
  1984. FOREACHpoint_(simplex) {
  1985. if (point != point0)
  1986. *(gmcoord++)= point[k] - point0[k];
  1987. }
  1988. }
  1989. sum2row= gmcoord;
  1990. for (i=0; i < dim; i++) {
  1991. sum2= 0.0;
  1992. for (k=0; k < dim; k++) {
  1993. diffp= qh->gm_row[k] + i;
  1994. sum2 += *diffp * *diffp;
  1995. }
  1996. *(gmcoord++)= sum2;
  1997. }
  1998. det= qh_determinant(qh, qh->gm_row, dim, &nearzero);
  1999. factor= qh_divzero(0.5, det, qh->MINdenom, &infinite);
  2000. if (infinite) {
  2001. for (k=dim; k--; )
  2002. center[k]= qh_INFINITE;
  2003. if (qh->IStracing)
  2004. qh_printpoints(qh, qh->ferr, "qh_voronoi_center: at infinity for ", simplex);
  2005. }else {
  2006. for (i=0; i < dim; i++) {
  2007. gmcoord= qh->gm_matrix;
  2008. sum2p= sum2row;
  2009. for (k=0; k < dim; k++) {
  2010. qh->gm_row[k]= gmcoord;
  2011. if (k == i) {
  2012. for (j=dim; j--; )
  2013. *(gmcoord++)= *sum2p++;
  2014. }else {
  2015. FOREACHpoint_(simplex) {
  2016. if (point != point0)
  2017. *(gmcoord++)= point[k] - point0[k];
  2018. }
  2019. }
  2020. }
  2021. center[i]= qh_determinant(qh, qh->gm_row, dim, &nearzero)*factor + point0[i];
  2022. }
  2023. #ifndef qh_NOtrace
  2024. if (qh->IStracing >= 3) {
  2025. qh_fprintf(qh, qh->ferr, 3061, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
  2026. qh_printmatrix(qh, qh->ferr, "center:", &center, 1, dim);
  2027. if (qh->IStracing >= 5) {
  2028. qh_printpoints(qh, qh->ferr, "points", simplex);
  2029. FOREACHpoint_(simplex)
  2030. qh_fprintf(qh, qh->ferr, 8034, "p%d dist %.2g, ", qh_pointid(qh, point),
  2031. qh_pointdist(point, center, dim));
  2032. qh_fprintf(qh, qh->ferr, 8035, "\n");
  2033. }
  2034. }
  2035. #endif
  2036. }
  2037. if (simplex != points)
  2038. qh_settempfree(qh, &simplex);
  2039. return center;
  2040. } /* voronoi_center */