io_r.c 139 KB

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