00001 #ifndef ANSI_DECLARATORS
00002 #define ANSI_DECLARATORS
00003 #endif
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 
00189 
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 #ifdef SINGLE
00217 #define REAL float
00218 #else 
00219 #define REAL double
00220 #endif 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 
00244 
00245 
00246 
00247 
00248 
00249 
00250 
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 
00271 
00272 
00273 
00274 
00275 #define INEXACT 
00276 
00277 
00278 
00279 
00280 #define FILENAMESIZE 2048
00281 
00282 
00283 
00284 
00285 #define INPUTLINESIZE 1024
00286 
00287 
00288 
00289 
00290 
00291 #define TRIPERBLOCK 4092           
00292 #define SUBSEGPERBLOCK 508       
00293 #define VERTEXPERBLOCK 4092         
00294 #define VIRUSPERBLOCK 1020   
00295 
00296 #define BADSUBSEGPERBLOCK 252
00297 
00298 #define BADTRIPERBLOCK 4092
00299 
00300 #define FLIPSTACKERPERBLOCK 252
00301 
00302 #define SPLAYNODEPERBLOCK 508
00303 
00304 
00305 
00306 
00307 
00308 #define INPUTVERTEX 0
00309 #define SEGMENTVERTEX 1
00310 #define FREEVERTEX 2
00311 #define DEADVERTEX -32768
00312 #define UNDEADVERTEX -32767
00313 
00314 
00315 
00316 
00317 
00318 #define VOID int
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 #define SAMPLEFACTOR 11
00327 
00328 
00329 
00330 
00331 
00332 #define SAMPLERATE 10
00333 
00334 
00335 
00336 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
00337 
00338 
00339 
00340 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
00341 
00342 
00343 
00344 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
00345 
00346 #include <stdio.h>
00347 #include <stdlib.h>
00348 #include <string.h>
00349 #include <math.h>
00350 #ifndef NO_TIMER
00351 #include <sys/time.h>
00352 #endif 
00353 #ifdef CPU86
00354 #include <float.h>
00355 #endif 
00356 #ifdef LINUX
00357 #include <fpu_control.h>
00358 #endif 
00359 #ifdef TRILIBRARY
00360 #include "triangle.h"
00361 #endif 
00362 
00363 
00364 
00365 #ifndef TRILIBRARY
00366 char *readline(char *string, FILE *infile, char *infilename);
00367 char *findfield(char *string);
00368 #endif 
00369 
00370 
00371 
00372 
00373 
00374 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
00383                          DUPLICATEVERTEX};
00384 
00385 
00386 
00387 
00388 
00389 
00390 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503 
00504 
00505 
00506 
00507 
00508 
00509 typedef REAL **triangle;            
00510 
00511 
00512 
00513 
00514 
00515 
00516 struct otri {
00517   triangle *tri;
00518   int orient;                                         
00519 };
00520 
00521 
00522 
00523 
00524 
00525 
00526 typedef REAL **subseg;                  
00527 
00528 
00529 
00530 
00531 
00532 
00533 struct osub {
00534   subseg *ss;
00535   int ssorient;                                       
00536 };
00537 
00538 
00539 
00540 
00541 
00542 
00543 typedef REAL *vertex;
00544 
00545 
00546 
00547 
00548 struct badsubseg {
00549   subseg encsubseg;                             
00550   vertex subsegorg, subsegdest;                         
00551 };
00552 
00553 
00554 
00555 
00556 
00557 struct badtriang {
00558   triangle poortri;                       
00559   REAL key;                             
00560   vertex triangorg, triangdest, triangapex;           
00561   struct badtriang *nexttriang;             
00562 };
00563 
00564 
00565 
00566 
00567 
00568 struct flipstacker {
00569   triangle flippedtri;                       
00570   struct flipstacker *prevflip;               
00571 };
00572 
00573 
00574 
00575 
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 struct event {
00584   REAL xkey, ykey;                              
00585   VOID *eventptr;      
00586   int heapposition;              
00587 };
00588 
00589 
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 struct splaynode {
00601   struct otri keyedge;                     
00602   vertex keydest;           
00603   struct splaynode *lchild, *rchild;              
00604 };
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 
00624 
00625 
00626 
00627 
00628 
00629 struct memorypool {
00630   VOID **firstblock, **nowblock;
00631   VOID *nextitem;
00632   VOID *deaditemstack;
00633   VOID **pathblock;
00634   VOID *pathitem;
00635   int alignbytes;
00636   int itembytes;
00637   int itemsperblock;
00638   int itemsfirstblock;
00639   long items, maxitems;
00640   int unallocateditems;
00641   int pathitemsleft;
00642 };
00643 
00644 
00645 
00646 
00647 REAL splitter;       
00648 REAL epsilon;                             
00649 REAL resulterrbound;
00650 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00651 REAL iccerrboundA, iccerrboundB, iccerrboundC;
00652 REAL o3derrboundA, o3derrboundB, o3derrboundC;
00653 
00654 
00655 
00656 unsigned long randomseed;                     
00657 
00658 
00659 
00660 
00661 
00662 struct mesh {
00663 
00664 
00665 
00666 
00667 
00668   struct memorypool triangles;
00669   struct memorypool subsegs;
00670   struct memorypool vertices;
00671   struct memorypool viri;
00672   struct memorypool badsubsegs;
00673   struct memorypool badtriangles;
00674   struct memorypool flipstackers;
00675   struct memorypool splaynodes;
00676 
00677 
00678 
00679 
00680   struct badtriang *queuefront[4096];
00681   struct badtriang *queuetail[4096];
00682   int nextnonemptyq[4096];
00683   int firstnonemptyq;
00684 
00685 
00686 
00687   struct flipstacker *lastflip;
00688 
00689 
00690 
00691   REAL xmin, xmax, ymin, ymax;                            
00692   REAL xminextreme;      
00693   int invertices;                               
00694   int inelements;                              
00695   int insegments;                               
00696   int holes;                                       
00697   int regions;                                   
00698   int undeads;    
00699   long edges;                                     
00700   int mesh_dim;                                
00701   int nextras;                           
00702   int eextras;                         
00703   long hullsize;                          
00704   int steinerleft;                 
00705   int vertexmarkindex;         
00706   int vertex2triindex;     
00707   int highorderindex;  
00708   int elemattribindex;            
00709   int areaboundindex;             
00710   int checksegments;         
00711   int checkquality;                  
00712   int readnodefile;                           
00713   long samples;              
00714 
00715   long incirclecount;                 
00716   long counterclockcount;     
00717   long orient3dcount;           
00718   long hyperbolacount;      
00719   long circumcentercount;  
00720   long circletopcount;       
00721 
00722 
00723 
00724   vertex infvertex1, infvertex2, infvertex3;
00725 
00726 
00727 
00728   triangle *dummytri;
00729   triangle *dummytribase;    
00730 
00731 
00732 
00733 
00734 
00735   subseg *dummysub;
00736   subseg *dummysubbase;      
00737 
00738 
00739 
00740 
00741   struct otri recenttri;
00742 
00743 };                                                  
00744 
00745 
00746 
00747 
00748 
00749 struct behavior {
00750 
00751 
00752 
00753 
00754 
00755 
00756 
00757 
00758 
00759 
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774 
00775 
00776 
00777 
00778 
00779 
00780 
00781 
00782 
00783 
00784   int poly, refine, quality, vararea, fixedarea, usertest;
00785   int regionattrib, convex, weighted, jettison;
00786   int firstnumber;
00787   int edgesout, voronoi, neighbors, geomview;
00788   int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
00789   int noholes, noexact, conformdel;
00790   int incremental, sweepline, dwyer;
00791   int splitseg;
00792   int docheck;
00793   int quiet, verbose;
00794   int usesegments;
00795   int order;
00796   int nobisect;
00797   int steiner;
00798   REAL minangle, goodangle, offconstant;
00799   REAL maxarea;
00800 
00801 
00802 
00803 #ifndef TRILIBRARY
00804   char innodefilename[FILENAMESIZE];
00805   char inelefilename[FILENAMESIZE];
00806   char inpolyfilename[FILENAMESIZE];
00807   char areafilename[FILENAMESIZE];
00808   char outnodefilename[FILENAMESIZE];
00809   char outelefilename[FILENAMESIZE];
00810   char outpolyfilename[FILENAMESIZE];
00811   char edgefilename[FILENAMESIZE];
00812   char vnodefilename[FILENAMESIZE];
00813   char vedgefilename[FILENAMESIZE];
00814   char neighborfilename[FILENAMESIZE];
00815   char offfilename[FILENAMESIZE];
00816 #endif 
00817 
00818 };                                              
00819 
00820 
00821 
00822 
00823 
00824 
00825 
00826 
00827 
00828 
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00836 
00837 
00838 
00839 
00840 
00841 
00842 
00843 
00844 
00845 
00846 
00847 
00848 
00849 
00850 
00851 
00852 
00853 
00854 
00855 
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00864 
00865 
00866 
00867 
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 
00884 
00885 
00886 
00887 
00888 
00889 
00890 
00891 
00892 
00893 
00894 
00895 
00896 
00897 
00898 
00899 
00900 
00901 
00902 
00903 
00904 
00905 
00906 
00907 
00908 
00909 
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926 
00927 
00931 
00932 
00933 int plus1mod3[3] = {1, 2, 0};
00934 int minus1mod3[3] = {2, 0, 1};
00935 
00936 
00937 
00938 
00939 
00940 
00941 
00942 
00943 #define decode(ptr, otri)                                                     \
00944   (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);         \
00945   (otri).tri = (triangle *)                                                   \
00946                   ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
00947 
00948 
00949 
00950 
00951 
00952 #define encode(otri)                                                          \
00953   (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
00954 
00955 
00956 
00957 
00958 
00959 
00960 
00961 
00962 
00963 #define sym(otri1, otri2)                                                     \
00964   ptr = (otri1).tri[(otri1).orient];                                          \
00965   decode(ptr, otri2);
00966 
00967 #define symself(otri)                                                         \
00968   ptr = (otri).tri[(otri).orient];                                            \
00969   decode(ptr, otri);
00970 
00971 
00972 
00973 #define lnext(otri1, otri2)                                                   \
00974   (otri2).tri = (otri1).tri;                                                  \
00975   (otri2).orient = plus1mod3[(otri1).orient]
00976 
00977 #define lnextself(otri)                                                       \
00978   (otri).orient = plus1mod3[(otri).orient]
00979 
00980 
00981 
00982 #define lprev(otri1, otri2)                                                   \
00983   (otri2).tri = (otri1).tri;                                                  \
00984   (otri2).orient = minus1mod3[(otri1).orient]
00985 
00986 #define lprevself(otri)                                                       \
00987   (otri).orient = minus1mod3[(otri).orient]
00988 
00989 
00990 
00991 
00992 
00993 #define onext(otri1, otri2)                                                   \
00994   lprev(otri1, otri2);                                                        \
00995   symself(otri2);
00996 
00997 #define onextself(otri)                                                       \
00998   lprevself(otri);                                                            \
00999   symself(otri);
01000 
01001 
01002 
01003 
01004 
01005 #define oprev(otri1, otri2)                                                   \
01006   sym(otri1, otri2);                                                          \
01007   lnextself(otri2);
01008 
01009 #define oprevself(otri)                                                       \
01010   symself(otri);                                                              \
01011   lnextself(otri);
01012 
01013 
01014 
01015 
01016 
01017 #define dnext(otri1, otri2)                                                   \
01018   sym(otri1, otri2);                                                          \
01019   lprevself(otri2);
01020 
01021 #define dnextself(otri)                                                       \
01022   symself(otri);                                                              \
01023   lprevself(otri);
01024 
01025 
01026 
01027 
01028 
01029 #define dprev(otri1, otri2)                                                   \
01030   lnext(otri1, otri2);                                                        \
01031   symself(otri2);
01032 
01033 #define dprevself(otri)                                                       \
01034   lnextself(otri);                                                            \
01035   symself(otri);
01036 
01037 
01038 
01039 
01040 
01041 #define rnext(otri1, otri2)                                                   \
01042   sym(otri1, otri2);                                                          \
01043   lnextself(otri2);                                                           \
01044   symself(otri2);
01045 
01046 #define rnextself(otri)                                                       \
01047   symself(otri);                                                              \
01048   lnextself(otri);                                                            \
01049   symself(otri);
01050 
01051 
01052 
01053 
01054 
01055 #define rprev(otri1, otri2)                                                   \
01056   sym(otri1, otri2);                                                          \
01057   lprevself(otri2);                                                           \
01058   symself(otri2);
01059 
01060 #define rprevself(otri)                                                       \
01061   symself(otri);                                                              \
01062   lprevself(otri);                                                            \
01063   symself(otri);
01064 
01065 
01066 
01067 
01068 #define org(otri, vertexptr)                                                  \
01069   vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
01070 
01071 #define dest(otri, vertexptr)                                                 \
01072   vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
01073 
01074 #define apex(otri, vertexptr)                                                 \
01075   vertexptr = (vertex) (otri).tri[(otri).orient + 3]
01076 
01077 #define setorg(otri, vertexptr)                                               \
01078   (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01079 
01080 #define setdest(otri, vertexptr)                                              \
01081   (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01082 
01083 #define setapex(otri, vertexptr)                                              \
01084   (otri).tri[(otri).orient + 3] = (triangle) vertexptr
01085 
01086 
01087 
01088 #define bond(otri1, otri2)                                                    \
01089   (otri1).tri[(otri1).orient] = encode(otri2);                                \
01090   (otri2).tri[(otri2).orient] = encode(otri1)
01091 
01092 
01093 
01094 
01095 
01096 
01097 #define dissolve(otri)                                                        \
01098   (otri).tri[(otri).orient] = (triangle) m->dummytri
01099 
01100 
01101 
01102 #define otricopy(otri1, otri2)                                                \
01103   (otri2).tri = (otri1).tri;                                                  \
01104   (otri2).orient = (otri1).orient
01105 
01106 
01107 
01108 #define otriequal(otri1, otri2)                                               \
01109   (((otri1).tri == (otri2).tri) &&                                            \
01110    ((otri1).orient == (otri2).orient))
01111 
01112 
01113 
01114 
01115 #define infect(otri)                                                          \
01116   (otri).tri[6] = (triangle)                                                  \
01117                     ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
01118 
01119 #define uninfect(otri)                                                        \
01120   (otri).tri[6] = (triangle)                                                  \
01121                     ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
01122 
01123 
01124 
01125 #define infected(otri)                                                        \
01126   (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
01127 
01128 
01129 
01130 #define elemattribute(otri, attnum)                                           \
01131   ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
01132 
01133 #define setelemattribute(otri, attnum, value)                                 \
01134   ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
01135 
01136 
01137 
01138 #define areabound(otri)  ((REAL *) (otri).tri)[m->areaboundindex]
01139 
01140 #define setareabound(otri, value)                                             \
01141   ((REAL *) (otri).tri)[m->areaboundindex] = value
01142 
01143 
01144 
01145 
01146 
01147 
01148 #define deadtri(tria)  ((tria)[1] == (triangle) NULL)
01149 
01150 #define killtri(tria)                                                         \
01151   (tria)[1] = (triangle) NULL;                                                \
01152   (tria)[3] = (triangle) NULL
01153 
01154 
01155 
01156 
01157 
01158 
01159 
01160 
01161 
01162 
01163 #define sdecode(sptr, osub)                                                   \
01164   (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l);      \
01165   (osub).ss = (subseg *)                                                      \
01166               ((unsigned long) (sptr) & ~ (unsigned long) 3l)
01167 
01168 
01169 
01170 
01171 
01172 #define sencode(osub)                                                         \
01173   (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
01174 
01175 
01176 
01177 #define ssym(osub1, osub2)                                                    \
01178   (osub2).ss = (osub1).ss;                                                    \
01179   (osub2).ssorient = 1 - (osub1).ssorient
01180 
01181 #define ssymself(osub)                                                        \
01182   (osub).ssorient = 1 - (osub).ssorient
01183 
01184 
01185 
01186 
01187 #define spivot(osub1, osub2)                                                  \
01188   sptr = (osub1).ss[(osub1).ssorient];                                        \
01189   sdecode(sptr, osub2)
01190 
01191 #define spivotself(osub)                                                      \
01192   sptr = (osub).ss[(osub).ssorient];                                          \
01193   sdecode(sptr, osub)
01194 
01195 
01196 
01197 
01198 #define snext(osub1, osub2)                                                   \
01199   sptr = (osub1).ss[1 - (osub1).ssorient];                                    \
01200   sdecode(sptr, osub2)
01201 
01202 #define snextself(osub)                                                       \
01203   sptr = (osub).ss[1 - (osub).ssorient];                                      \
01204   sdecode(sptr, osub)
01205 
01206 
01207 
01208 
01209 #define sorg(osub, vertexptr)                                                 \
01210   vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
01211 
01212 #define sdest(osub, vertexptr)                                                \
01213   vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
01214 
01215 #define setsorg(osub, vertexptr)                                              \
01216   (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
01217 
01218 #define setsdest(osub, vertexptr)                                             \
01219   (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
01220 
01221 #define segorg(osub, vertexptr)                                               \
01222   vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
01223 
01224 #define segdest(osub, vertexptr)                                              \
01225   vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
01226 
01227 #define setsegorg(osub, vertexptr)                                            \
01228   (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
01229 
01230 #define setsegdest(osub, vertexptr)                                           \
01231   (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
01232 
01233 
01234 
01235 
01236 
01237 #define mark(osub)  (* (int *) ((osub).ss + 8))
01238 
01239 #define setmark(osub, value)                                                  \
01240   * (int *) ((osub).ss + 8) = value
01241 
01242 
01243 
01244 #define sbond(osub1, osub2)                                                   \
01245   (osub1).ss[(osub1).ssorient] = sencode(osub2);                              \
01246   (osub2).ss[(osub2).ssorient] = sencode(osub1)
01247 
01248 
01249 
01250 
01251 #define sdissolve(osub)                                                       \
01252   (osub).ss[(osub).ssorient] = (subseg) m->dummysub
01253 
01254 
01255 
01256 #define subsegcopy(osub1, osub2)                                              \
01257   (osub2).ss = (osub1).ss;                                                    \
01258   (osub2).ssorient = (osub1).ssorient
01259 
01260 
01261 
01262 #define subsegequal(osub1, osub2)                                             \
01263   (((osub1).ss == (osub2).ss) &&                                              \
01264    ((osub1).ssorient == (osub2).ssorient))
01265 
01266 
01267 
01268 
01269 
01270 
01271 #define deadsubseg(sub)  ((sub)[1] == (subseg) NULL)
01272 
01273 #define killsubseg(sub)                                                       \
01274   (sub)[1] = (subseg) NULL;                                                   \
01275   (sub)[2] = (subseg) NULL
01276 
01277 
01278 
01279 
01280 
01281 
01282 
01283 #define tspivot(otri, osub)                                                   \
01284   sptr = (subseg) (otri).tri[6 + (otri).orient];                              \
01285   sdecode(sptr, osub)
01286 
01287 
01288 
01289 
01290 #define stpivot(osub, otri)                                                   \
01291   ptr = (triangle) (osub).ss[6 + (osub).ssorient];                            \
01292   decode(ptr, otri)
01293 
01294 
01295 
01296 #define tsbond(otri, osub)                                                    \
01297   (otri).tri[6 + (otri).orient] = (triangle) sencode(osub);                   \
01298   (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
01299 
01300 
01301 
01302 #define tsdissolve(otri)                                                      \
01303   (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
01304 
01305 
01306 
01307 #define stdissolve(osub)                                                      \
01308   (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
01309 
01310 
01311 
01312 
01313 
01314 #define vertexmark(vx)  ((int *) (vx))[m->vertexmarkindex]
01315 
01316 #define setvertexmark(vx, value)                                              \
01317   ((int *) (vx))[m->vertexmarkindex] = value
01318 
01319 #define vertextype(vx)  ((int *) (vx))[m->vertexmarkindex + 1]
01320 
01321 #define setvertextype(vx, value)                                              \
01322   ((int *) (vx))[m->vertexmarkindex + 1] = value
01323 
01324 #define vertex2tri(vx)  ((triangle *) (vx))[m->vertex2triindex]
01325 
01326 #define setvertex2tri(vx, value)                                              \
01327   ((triangle *) (vx))[m->vertex2triindex] = value
01328 
01331 
01332 
01333 
01337 
01338 
01339 
01340 
01341 
01342 
01343 
01344 
01345 
01346 
01347 
01348 
01349 
01350 
01351 
01352 
01353 
01354 
01355 
01356 
01357 
01358 
01359 
01360 #ifdef EXTERNAL_TEST
01361 
01362 int triunsuitable();
01363 
01364 #else 
01365 
01366 #ifdef ANSI_DECLARATORS
01367 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
01368 #else 
01369 int triunsuitable(triorg, tridest, triapex, area)
01370 vertex triorg;                              
01371 vertex tridest;                        
01372 vertex triapex;                               
01373 REAL area;                                      
01374 #endif 
01375 
01376 {
01377   REAL dxoa, dxda, dxod;
01378   REAL dyoa, dyda, dyod;
01379   REAL oalen, dalen, odlen;
01380   REAL maxlen;
01381 
01382   dxoa = triorg[0] - triapex[0];
01383   dyoa = triorg[1] - triapex[1];
01384   dxda = tridest[0] - triapex[0];
01385   dyda = tridest[1] - triapex[1];
01386   dxod = triorg[0] - tridest[0];
01387   dyod = triorg[1] - tridest[1];
01388   
01389   oalen = dxoa * dxoa + dyoa * dyoa;
01390   dalen = dxda * dxda + dyda * dyda;
01391   odlen = dxod * dxod + dyod * dyod;
01392   
01393   maxlen = (dalen > oalen) ? dalen : oalen;
01394   maxlen = (odlen > maxlen) ? odlen : maxlen;
01395 
01396   if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
01397     return 1;
01398   } else {
01399     return 0;
01400   }
01401 }
01402 
01403 #endif 
01404 
01407 
01408 
01409 
01413 #ifdef ANSI_DECLARATORS
01414 void triexit(int status)
01415 #else 
01416 void triexit(status)
01417 int status;
01418 #endif 
01419 
01420 {
01421   exit(status);
01422 }
01423 
01424 #ifdef ANSI_DECLARATORS
01425 VOID *trimalloc(int size)
01426 #else 
01427 VOID *trimalloc(size)
01428 int size;
01429 #endif 
01430 
01431 {
01432   VOID *memptr;
01433 
01434   memptr = (VOID *) malloc((unsigned int) size);
01435   if (memptr == (VOID *) NULL) {
01436     printf("Error:  Out of memory.\n");
01437     triexit(1);
01438   }
01439   return(memptr);
01440 }
01441 
01442 #ifdef ANSI_DECLARATORS
01443 void trifree(VOID *memptr)
01444 #else 
01445 void trifree(memptr)
01446 VOID *memptr;
01447 #endif 
01448 
01449 {
01450   free(memptr);
01451 }
01452 
01455 
01456 
01457 
01461 
01462 
01463 
01464 
01465 
01466 
01467 #ifndef TRILIBRARY
01468 
01469 void syntax()
01470 {
01471 #ifdef CDT_ONLY
01472 #ifdef REDUCED
01473   printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
01474 #else 
01475   printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
01476 #endif 
01477 #else 
01478 #ifdef REDUCED
01479   printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
01480 #else 
01481   printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
01482 #endif 
01483 #endif 
01484 
01485   printf("    -p  Triangulates a Planar Straight Line Graph (.poly file).\n");
01486 #ifndef CDT_ONLY
01487   printf("    -r  Refines a previously generated mesh.\n");
01488   printf(
01489     "    -q  Quality mesh generation.  A minimum angle may be specified.\n");
01490   printf("    -a  Applies a maximum triangle area constraint.\n");
01491   printf("    -u  Applies a user-defined triangle constraint.\n");
01492 #endif 
01493   printf(
01494     "    -A  Applies attributes to identify triangles in certain regions.\n");
01495   printf("    -c  Encloses the convex hull with segments.\n");
01496 #ifndef CDT_ONLY
01497   printf("    -D  Conforming Delaunay:  all triangles are truly Delaunay.\n");
01498 #endif 
01499 
01500 
01501 
01502 
01503   printf("    -j  Jettison unused vertices from output .node file.\n");
01504   printf("    -e  Generates an edge list.\n");
01505   printf("    -v  Generates a Voronoi diagram.\n");
01506   printf("    -n  Generates a list of triangle neighbors.\n");
01507   printf("    -g  Generates an .off file for Geomview.\n");
01508   printf("    -B  Suppresses output of boundary information.\n");
01509   printf("    -P  Suppresses output of .poly file.\n");
01510   printf("    -N  Suppresses output of .node file.\n");
01511   printf("    -E  Suppresses output of .ele file.\n");
01512   printf("    -I  Suppresses mesh iteration numbers.\n");
01513   printf("    -O  Ignores holes in .poly file.\n");
01514   printf("    -X  Suppresses use of exact arithmetic.\n");
01515   printf("    -z  Numbers all items starting from zero (rather than one).\n");
01516   printf("    -o2 Generates second-order subparametric elements.\n");
01517 #ifndef CDT_ONLY
01518   printf("    -Y  Suppresses boundary segment splitting.\n");
01519   printf("    -S  Specifies maximum number of added Steiner points.\n");
01520 #endif 
01521 #ifndef REDUCED
01522   printf("    -i  Uses incremental method, rather than divide-and-conquer.\n");
01523   printf("    -F  Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
01524 #endif 
01525   printf("    -l  Uses vertical cuts only, rather than alternating cuts.\n");
01526 #ifndef REDUCED
01527 #ifndef CDT_ONLY
01528   printf(
01529     "    -s  Force segments into mesh by splitting (instead of using CDT).\n");
01530 #endif 
01531   printf("    -C  Check consistency of final mesh.\n");
01532 #endif 
01533   printf("    -Q  Quiet:  No terminal output except errors.\n");
01534   printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
01535   printf("    -h  Help:  Detailed instructions for Triangle.\n");
01536   triexit(0);
01537 }
01538 
01539 #endif 
01540 
01541 
01542 
01543 
01544 
01545 
01546 
01547 #ifndef TRILIBRARY
01548 
01549 void info()
01550 {
01551   printf("Triangle\n");
01552   printf(
01553 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
01554   printf("Version 1.6\n\n");
01555   printf(
01556 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
01557   printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
01558   printf("Bugs/comments to jrs@cs.berkeley.edu\n");
01559   printf(
01560 "Created as part of the Quake project (tools for earthquake simulation).\n");
01561   printf(
01562 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
01563   printf("There is no warranty whatsoever.  Use at your own risk.\n");
01564 #ifdef SINGLE
01565   printf("This executable is compiled for single precision arithmetic.\n\n\n");
01566 #else 
01567   printf("This executable is compiled for double precision arithmetic.\n\n\n");
01568 #endif 
01569   printf(
01570 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
01571   printf(
01572 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
01573   printf(
01574 "high-quality triangular meshes.  The latter can be generated with no small\n"
01575 );
01576   printf(
01577 "or large angles, and are thus suitable for finite element analysis.  If no\n"
01578 );
01579   printf(
01580 "command line switch is specified, your .node input file is read, and the\n");
01581   printf(
01582 "Delaunay triangulation is returned in .node and .ele output files.  The\n");
01583   printf("command syntax is:\n\n");
01584   printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
01585   printf(
01586 "Underscores indicate that numbers may optionally follow certain switches.\n");
01587   printf(
01588 "Do not leave any space between a switch and its numeric parameter.\n");
01589   printf(
01590 "input_file must be a file with extension .node, or extension .poly if the\n");
01591   printf(
01592 "-p switch is used.  If -r is used, you must supply .node and .ele files,\n");
01593   printf(
01594 "and possibly a .poly file and an .area file as well.  The formats of these\n"
01595 );
01596   printf("files are described below.\n\n");
01597   printf("Command Line Switches:\n\n");
01598   printf(
01599 "    -p  Reads a Planar Straight Line Graph (.poly file), which can specify\n"
01600 );
01601   printf(
01602 "        vertices, segments, holes, regional attributes, and regional area\n");
01603   printf(
01604 "        constraints.  Generates a constrained Delaunay triangulation (CDT)\n"
01605 );
01606   printf(
01607 "        fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
01608   printf(
01609 "        constrained Delaunay triangulation (CCDT).  If you want a truly\n");
01610   printf(
01611 "        Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
01612   printf(
01613 "        well.  When -p is not used, Triangle reads a .node file by default.\n"
01614 );
01615   printf(
01616 "    -r  Refines a previously generated mesh.  The mesh is read from a .node\n"
01617 );
01618   printf(
01619 "        file and an .ele file.  If -p is also used, a .poly file is read\n");
01620   printf(
01621 "        and used to constrain segments in the mesh.  If -a is also used\n");
01622   printf(
01623 "        (with no number following), an .area file is read and used to\n");
01624   printf(
01625 "        impose area constraints on the mesh.  Further details on refinement\n"
01626 );
01627   printf("        appear below.\n");
01628   printf(
01629 "    -q  Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
01630   printf(
01631 "        Chew's and Jim Ruppert's algorithms).  Adds vertices to the mesh to\n"
01632 );
01633   printf(
01634 "        ensure that all angles are between 20 and 140 degrees.  An\n");
01635   printf(
01636 "        alternative bound on the minimum angle, replacing 20 degrees, may\n");
01637   printf(
01638 "        be specified after the `q'.  The specified angle may include a\n");
01639   printf(
01640 "        decimal point, but not exponential notation.  Note that a bound of\n"
01641 );
01642   printf(
01643 "        theta degrees on the smallest angle also implies a bound of\n");
01644   printf(
01645 "        (180 - 2 theta) on the largest angle.  If the minimum angle is 28.6\n"
01646 );
01647   printf(
01648 "        degrees or smaller, Triangle is mathematically guaranteed to\n");
01649   printf(
01650 "        terminate (assuming infinite precision arithmetic--Triangle may\n");
01651   printf(
01652 "        fail to terminate if you run out of precision).  In practice,\n");
01653   printf(
01654 "        Triangle often succeeds for minimum angles up to 34 degrees.  For\n");
01655   printf(
01656 "        some meshes, however, you might need to reduce the minimum angle to\n"
01657 );
01658   printf(
01659 "        avoid problems associated with insufficient floating-point\n");
01660   printf("        precision.\n");
01661   printf(
01662 "    -a  Imposes a maximum triangle area.  If a number follows the `a', no\n");
01663   printf(
01664 "        triangle is generated whose area is larger than that number.  If no\n"
01665 );
01666   printf(
01667 "        number is specified, an .area file (if -r is used) or .poly file\n");
01668   printf(
01669 "        (if -r is not used) specifies a set of maximum area constraints.\n");
01670   printf(
01671 "        An .area file contains a separate area constraint for each\n");
01672   printf(
01673 "        triangle, and is useful for refining a finite element mesh based on\n"
01674 );
01675   printf(
01676 "        a posteriori error estimates.  A .poly file can optionally contain\n"
01677 );
01678   printf(
01679 "        an area constraint for each segment-bounded region, thereby\n");
01680   printf(
01681 "        controlling triangle densities in a first triangulation of a PSLG.\n"
01682 );
01683   printf(
01684 "        You can impose both a fixed area constraint and a varying area\n");
01685   printf(
01686 "        constraint by invoking the -a switch twice, once with and once\n");
01687   printf(
01688 "        without a number following.  Each area specified may include a\n");
01689   printf("        decimal point.\n");
01690   printf(
01691 "    -u  Imposes a user-defined constraint on triangle size.  There are two\n"
01692 );
01693   printf(
01694 "        ways to use this feature.  One is to edit the triunsuitable()\n");
01695   printf(
01696 "        procedure in triangle.c to encode any constraint you like, then\n");
01697   printf(
01698 "        recompile Triangle.  The other is to compile triangle.c with the\n");
01699   printf(
01700 "        EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
01701   printf(
01702 "        link Triangle with a separate object file that implements\n");
01703   printf(
01704 "        triunsuitable().  In either case, the -u switch causes the user-\n");
01705   printf("        defined test to be applied to every triangle.\n");
01706   printf(
01707 "    -A  Assigns an additional floating-point attribute to each triangle\n");
01708   printf(
01709 "        that identifies what segment-bounded region each triangle belongs\n");
01710   printf(
01711 "        to.  Attributes are assigned to regions by the .poly file.  If a\n");
01712   printf(
01713 "        region is not explicitly marked by the .poly file, triangles in\n");
01714   printf(
01715 "        that region are assigned an attribute of zero.  The -A switch has\n");
01716   printf(
01717 "        an effect only when the -p switch is used and the -r switch is not.\n"
01718 );
01719   printf(
01720 "    -c  Creates segments on the convex hull of the triangulation.  If you\n");
01721   printf(
01722 "        are triangulating a vertex set, this switch causes a .poly file to\n"
01723 );
01724   printf(
01725 "        be written, containing all edges of the convex hull.  If you are\n");
01726   printf(
01727 "        triangulating a PSLG, this switch specifies that the whole convex\n");
01728   printf(
01729 "        hull of the PSLG should be triangulated, regardless of what\n");
01730   printf(
01731 "        segments the PSLG has.  If you do not use this switch when\n");
01732   printf(
01733 "        triangulating a PSLG, Triangle assumes that you have identified the\n"
01734 );
01735   printf(
01736 "        region to be triangulated by surrounding it with segments of the\n");
01737   printf(
01738 "        input PSLG.  Beware:  if you are not careful, this switch can cause\n"
01739 );
01740   printf(
01741 "        the introduction of an extremely thin angle between a PSLG segment\n"
01742 );
01743   printf(
01744 "        and a convex hull segment, which can cause overrefinement (and\n");
01745   printf(
01746 "        possibly failure if Triangle runs out of precision).  If you are\n");
01747   printf(
01748 "        refining a mesh, the -c switch works differently:  it causes a\n");
01749   printf(
01750 "        .poly file to be written containing the boundary edges of the mesh\n"
01751 );
01752   printf("        (useful if no .poly file was read).\n");
01753   printf(
01754 "    -D  Conforming Delaunay triangulation:  use this switch if you want to\n"
01755 );
01756   printf(
01757 "        ensure that all the triangles in the mesh are Delaunay, and not\n");
01758   printf(
01759 "        merely constrained Delaunay; or if you want to ensure that all the\n"
01760 );
01761   printf(
01762 "        Voronoi vertices lie within the triangulation.  (Some finite volume\n"
01763 );
01764   printf(
01765 "        methods have this requirement.)  This switch invokes Ruppert's\n");
01766   printf(
01767 "        original algorithm, which splits every subsegment whose diametral\n");
01768   printf(
01769 "        circle is encroached.  It usually increases the number of vertices\n"
01770 );
01771   printf("        and triangles.\n");
01772   printf(
01773 "    -j  Jettisons vertices that are not part of the final triangulation\n");
01774   printf(
01775 "        from the output .node file.  By default, Triangle copies all\n");
01776   printf(
01777 "        vertices in the input .node file to the output .node file, in the\n");
01778   printf(
01779 "        same order, so their indices do not change.  The -j switch prevents\n"
01780 );
01781   printf(
01782 "        duplicated input vertices, or vertices `eaten' by holes, from\n");
01783   printf(
01784 "        appearing in the output .node file.  Thus, if two input vertices\n");
01785   printf(
01786 "        have exactly the same coordinates, only the first appears in the\n");
01787   printf(
01788 "        output.  If any vertices are jettisoned, the vertex numbering in\n");
01789   printf(
01790 "        the output .node file differs from that of the input .node file.\n");
01791   printf(
01792 "    -e  Outputs (to an .edge file) a list of edges of the triangulation.\n");
01793   printf(
01794 "    -v  Outputs the Voronoi diagram associated with the triangulation.\n");
01795   printf(
01796 "        Does not attempt to detect degeneracies, so some Voronoi vertices\n");
01797   printf(
01798 "        may be duplicated.  See the discussion of Voronoi diagrams below.\n");
01799   printf(
01800 "    -n  Outputs (to a .neigh file) a list of triangles neighboring each\n");
01801   printf("        triangle.\n");
01802   printf(
01803 "    -g  Outputs the mesh to an Object File Format (.off) file, suitable for\n"
01804 );
01805   printf("        viewing with the Geometry Center's Geomview package.\n");
01806   printf(
01807 "    -B  No boundary markers in the output .node, .poly, and .edge output\n");
01808   printf(
01809 "        files.  See the detailed discussion of boundary markers below.\n");
01810   printf(
01811 "    -P  No output .poly file.  Saves disk space, but you lose the ability\n");
01812   printf(
01813 "        to maintain constraining segments on later refinements of the mesh.\n"
01814 );
01815   printf("    -N  No output .node file.\n");
01816   printf("    -E  No output .ele file.\n");
01817   printf(
01818 "    -I  No iteration numbers.  Suppresses the output of .node and .poly\n");
01819   printf(
01820 "        files, so your input files won't be overwritten.  (If your input is\n"
01821 );
01822   printf(
01823 "        a .poly file only, a .node file is written.)  Cannot be used with\n");
01824   printf(
01825 "        the -r switch, because that would overwrite your input .ele file.\n");
01826   printf(
01827 "        Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
01828   printf(
01829 "        using a .node file for input, because no .node file is written, so\n"
01830 );
01831   printf("        there is no record of any added Steiner points.\n");
01832   printf("    -O  No holes.  Ignores the holes in the .poly file.\n");
01833   printf(
01834 "    -X  No exact arithmetic.  Normally, Triangle uses exact floating-point\n"
01835 );
01836   printf(
01837 "        arithmetic for certain tests if it thinks the inexact tests are not\n"
01838 );
01839   printf(
01840 "        accurate enough.  Exact arithmetic ensures the robustness of the\n");
01841   printf(
01842 "        triangulation algorithms, despite floating-point roundoff error.\n");
01843   printf(
01844 "        Disabling exact arithmetic with the -X switch causes a small\n");
01845   printf(
01846 "        improvement in speed and creates the possibility that Triangle will\n"
01847 );
01848   printf("        fail to produce a valid mesh.  Not recommended.\n");
01849   printf(
01850 "    -z  Numbers all items starting from zero (rather than one).  Note that\n"
01851 );
01852   printf(
01853 "        this switch is normally overridden by the value used to number the\n"
01854 );
01855   printf(
01856 "        first vertex of the input .node or .poly file.  However, this\n");
01857   printf(
01858 "        switch is useful when calling Triangle from another program.\n");
01859   printf(
01860 "    -o2 Generates second-order subparametric elements with six nodes each.\n"
01861 );
01862   printf(
01863 "    -Y  No new vertices on the boundary.  This switch is useful when the\n");
01864   printf(
01865 "        mesh boundary must be preserved so that it conforms to some\n");
01866   printf(
01867 "        adjacent mesh.  Be forewarned that you will probably sacrifice much\n"
01868 );
01869   printf(
01870 "        of the quality of the mesh; Triangle will try, but the resulting\n");
01871   printf(
01872 "        mesh may contain poorly shaped triangles.  Works well if all the\n");
01873   printf(
01874 "        boundary vertices are closely spaced.  Specify this switch twice\n");
01875   printf(
01876 "        (`-YY') to prevent all segment splitting, including internal\n");
01877   printf("        boundaries.\n");
01878   printf(
01879 "    -S  Specifies the maximum number of Steiner points (vertices that are\n");
01880   printf(
01881 "        not in the input, but are added to meet the constraints on minimum\n"
01882 );
01883   printf(
01884 "        angle and maximum area).  The default is to allow an unlimited\n");
01885   printf(
01886 "        number.  If you specify this switch with no number after it,\n");
01887   printf(
01888 "        the limit is set to zero.  Triangle always adds vertices at segment\n"
01889 );
01890   printf(
01891 "        intersections, even if it needs to use more vertices than the limit\n"
01892 );
01893   printf(
01894 "        you set.  When Triangle inserts segments by splitting (-s), it\n");
01895   printf(
01896 "        always adds enough vertices to ensure that all the segments of the\n"
01897 );
01898   printf("        PLSG are recovered, ignoring the limit if necessary.\n");
01899   printf(
01900 "    -i  Uses an incremental rather than a divide-and-conquer algorithm to\n");
01901   printf(
01902 "        construct a Delaunay triangulation.  Try it if the divide-and-\n");
01903   printf("        conquer algorithm fails.\n");
01904   printf(
01905 "    -F  Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
01906   printf(
01907 "        triangulation.  Warning:  does not use exact arithmetic for all\n");
01908   printf("        calculations.  An exact result is not guaranteed.\n");
01909   printf(
01910 "    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By\n");
01911   printf(
01912 "        default, Triangle alternates between vertical and horizontal cuts,\n"
01913 );
01914   printf(
01915 "        which usually improve the speed except with vertex sets that are\n");
01916   printf(
01917 "        small or short and wide.  This switch is primarily of theoretical\n");
01918   printf("        interest.\n");
01919   printf(
01920 "    -s  Specifies that segments should be forced into the triangulation by\n"
01921 );
01922   printf(
01923 "        recursively splitting them at their midpoints, rather than by\n");
01924   printf(
01925 "        generating a constrained Delaunay triangulation.  Segment splitting\n"
01926 );
01927   printf(
01928 "        is true to Ruppert's original algorithm, but can create needlessly\n"
01929 );
01930   printf(
01931 "        small triangles.  This switch is primarily of theoretical interest.\n"
01932 );
01933   printf(
01934 "    -C  Check the consistency of the final mesh.  Uses exact arithmetic for\n"
01935 );
01936   printf(
01937 "        checking, even if the -X switch is used.  Useful if you suspect\n");
01938   printf("        Triangle is buggy.\n");
01939   printf(
01940 "    -Q  Quiet:  Suppresses all explanation of what Triangle is doing,\n");
01941   printf("        unless an error occurs.\n");
01942   printf(
01943 "    -V  Verbose:  Gives detailed information about what Triangle is doing.\n"
01944 );
01945   printf(
01946 "        Add more `V's for increasing amount of detail.  `-V' is most\n");
01947   printf(
01948 "        useful; itgives information on algorithmic progress and much more\n");
01949   printf(
01950 "        detailed statistics.  `-VV' gives vertex-by-vertex details, and\n");
01951   printf(
01952 "        prints so much that Triangle runs much more slowly.  `-VVVV' gives\n"
01953 );
01954   printf("        information only a debugger could love.\n");
01955   printf("    -h  Help:  Displays these instructions.\n");
01956   printf("\n");
01957   printf("Definitions:\n");
01958   printf("\n");
01959   printf(
01960 "  A Delaunay triangulation of a vertex set is a triangulation whose\n");
01961   printf(
01962 "  vertices are the vertex set, that covers the convex hull of the vertex\n");
01963   printf(
01964 "  set.  A Delaunay triangulation has the property that no vertex lies\n");
01965   printf(
01966 "  inside the circumscribing circle (circle that passes through all three\n");
01967   printf("  vertices) of any triangle in the triangulation.\n\n");
01968   printf(
01969 "  A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
01970   printf(
01971 "  polygonal cells (some of which may be unbounded, meaning infinitely\n");
01972   printf(
01973 "  large), where each cell is the set of points in the plane that are closer\n"
01974 );
01975   printf(
01976 "  to some input vertex than to any other input vertex.  The Voronoi diagram\n"
01977 );
01978   printf("  is a geometric dual of the Delaunay triangulation.\n\n");
01979   printf(
01980 "  A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
01981   printf(
01982 "  Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
01983 );
01984   printf(
01985 "  Segments may intersect each other only at their endpoints.  The file\n");
01986   printf("  format for PSLGs (.poly files) is described below.\n\n");
01987   printf(
01988 "  A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
01989   printf(
01990 "  Delaunay triangulation, but each PSLG segment is present as a single edge\n"
01991 );
01992   printf(
01993 "  of the CDT.  (A constrained Delaunay triangulation is not truly a\n");
01994   printf(
01995 "  Delaunay triangulation, because some of its triangles might not be\n");
01996   printf(
01997 "  Delaunay.)  By definition, a CDT does not have any vertices other than\n");
01998   printf(
01999 "  those specified in the input PSLG.  Depending on context, a CDT might\n");
02000   printf(
02001 "  cover the convex hull of the PSLG, or it might cover only a segment-\n");
02002   printf("  bounded region (e.g. a polygon).\n\n");
02003   printf(
02004 "  A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
02005 );
02006   printf(
02007 "  each triangle is truly Delaunay, and each PSLG segment is represented by\n"
02008 );
02009   printf(
02010 "  a linear contiguous sequence of edges of the triangulation.  New vertices\n"
02011 );
02012   printf(
02013 "  (not part of the PSLG) may appear, and each input segment may have been\n");
02014   printf(
02015 "  subdivided into shorter edges (subsegments) by these additional vertices.\n"
02016 );
02017   printf(
02018 "  The new vertices are frequently necessary to maintain the Delaunay\n");
02019   printf("  property while ensuring that every segment is represented.\n\n");
02020   printf(
02021 "  A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
02022   printf(
02023 "  triangulation of a PSLG whose triangles are constrained Delaunay.  New\n");
02024   printf("  vertices may appear, and input segments may be subdivided into\n");
02025   printf(
02026 "  subsegments, but not to guarantee that segments are respected; rather, to\n"
02027 );
02028   printf(
02029 "  improve the quality of the triangles.  The high-quality meshes produced\n");
02030   printf(
02031 "  by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
02032   printf("  with the -D switch.\n\n");
02033   printf("File Formats:\n\n");
02034   printf(
02035 "  All files may contain comments prefixed by the character '#'.  Vertices,\n"
02036 );
02037   printf(
02038 "  triangles, edges, holes, and maximum area constraints must be numbered\n");
02039   printf(
02040 "  consecutively, starting from either 1 or 0.  Whichever you choose, all\n");
02041   printf(
02042 "  input files must be consistent; if the vertices are numbered from 1, so\n");
02043   printf(
02044 "  must be all other objects.  Triangle automatically detects your choice\n");
02045   printf(
02046 "  while reading the .node (or .poly) file.  (When calling Triangle from\n");
02047   printf(
02048 "  another program, use the -z switch if you wish to number objects from\n");
02049   printf("  zero.)  Examples of these file formats are given below.\n\n");
02050   printf("  .node files:\n");
02051   printf(
02052 "    First line:  <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02053 );
02054   printf(
02055 "                                           <# of boundary markers (0 or 1)>\n"
02056 );
02057   printf(
02058 "    Remaining lines:  <vertex #> <x> <y> [attributes] [boundary marker]\n");
02059   printf("\n");
02060   printf(
02061 "    The attributes, which are typically floating-point values of physical\n");
02062   printf(
02063 "    quantities (such as mass or conductivity) associated with the nodes of\n"
02064 );
02065   printf(
02066 "    a finite element mesh, are copied unchanged to the output mesh.  If -q,\n"
02067 );
02068   printf(
02069 "    -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
02070 );
02071   printf("    has attributes assigned to it by linear interpolation.\n\n");
02072   printf(
02073 "    If the fourth entry of the first line is `1', the last column of the\n");
02074   printf(
02075 "    remainder of the file is assumed to contain boundary markers.  Boundary\n"
02076 );
02077   printf(
02078 "    markers are used to identify boundary vertices and vertices resting on\n"
02079 );
02080   printf(
02081 "    PSLG segments; a complete description appears in a section below.  The\n"
02082 );
02083   printf(
02084 "    .node file produced by Triangle contains boundary markers in the last\n");
02085   printf("    column unless they are suppressed by the -B switch.\n\n");
02086   printf("  .ele files:\n");
02087   printf(
02088 "    First line:  <# of triangles> <nodes per triangle> <# of attributes>\n");
02089   printf(
02090 "    Remaining lines:  <triangle #> <node> <node> <node> ... [attributes]\n");
02091   printf("\n");
02092   printf(
02093 "    Nodes are indices into the corresponding .node file.  The first three\n");
02094   printf(
02095 "    nodes are the corner vertices, and are listed in counterclockwise order\n"
02096 );
02097   printf(
02098 "    around each triangle.  (The remaining nodes, if any, depend on the type\n"
02099 );
02100   printf("    of finite element used.)\n\n");
02101   printf(
02102 "    The attributes are just like those of .node files.  Because there is no\n"
02103 );
02104   printf(
02105 "    simple mapping from input to output triangles, Triangle attempts to\n");
02106   printf(
02107 "    interpolate attributes, and may cause a lot of diffusion of attributes\n"
02108 );
02109   printf(
02110 "    among nearby triangles as the triangulation is refined.  Attributes do\n"
02111 );
02112   printf("    not diffuse across segments, so attributes used to identify\n");
02113   printf("    segment-bounded regions remain intact.\n\n");
02114   printf(
02115 "    In .ele files produced by Triangle, each triangular element has three\n");
02116   printf(
02117 "    nodes (vertices) unless the -o2 switch is used, in which case\n");
02118   printf(
02119 "    subparametric quadratic elements with six nodes each are generated.\n");
02120   printf(
02121 "    The first three nodes are the corners in counterclockwise order, and\n");
02122   printf(
02123 "    the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
02124   printf(
02125 "    opposite the first, second, and third vertices, respectively.\n");
02126   printf("\n");
02127   printf("  .poly files:\n");
02128   printf(
02129 "    First line:  <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02130 );
02131   printf(
02132 "                                           <# of boundary markers (0 or 1)>\n"
02133 );
02134   printf(
02135 "    Following lines:  <vertex #> <x> <y> [attributes] [boundary marker]\n");
02136   printf("    One line:  <# of segments> <# of boundary markers (0 or 1)>\n");
02137   printf(
02138 "    Following lines:  <segment #> <endpoint> <endpoint> [boundary marker]\n");
02139   printf("    One line:  <# of holes>\n");
02140   printf("    Following lines:  <hole #> <x> <y>\n");
02141   printf(
02142 "    Optional line:  <# of regional attributes and/or area constraints>\n");
02143   printf(
02144 "    Optional following lines:  <region #> <x> <y> <attribute> <max area>\n");
02145   printf("\n");
02146   printf(
02147 "    A .poly file represents a PSLG, as well as some additional information.\n"
02148 );
02149   printf(
02150 "    The first section lists all the vertices, and is identical to the\n");
02151   printf(
02152 "    format of .node files.  <# of vertices> may be set to zero to indicate\n"
02153 );
02154   printf(
02155 "    that the vertices are listed in a separate .node file; .poly files\n");
02156   printf(
02157 "    produced by Triangle always have this format.  A vertex set represented\n"
02158 );
02159   printf(
02160 "    this way has the advantage that it may easily be triangulated with or\n");
02161   printf(
02162 "    without segments (depending on whether the -p switch is invoked).\n");
02163   printf("\n");
02164   printf(
02165 "    The second section lists the segments.  Segments are edges whose\n");
02166   printf(
02167 "    presence in the triangulation is enforced.  (Depending on the choice of\n"
02168 );
02169   printf(
02170 "    switches, segment might be subdivided into smaller edges).  Each\n");
02171   printf(
02172 "    segment is specified by listing the indices of its two endpoints.  This\n"
02173 );
02174   printf(
02175 "    means that you must include its endpoints in the vertex list.  Each\n");
02176   printf("    segment, like each point, may have a boundary marker.\n\n");
02177   printf(
02178 "    If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
02179 );
02180   printf(
02181 "    Delaunay triangulation (CDT), in which each segment appears as a single\n"
02182 );
02183   printf(
02184 "    edge in the triangulation.  If -q, -a, -u, or -s is selected, Triangle\n"
02185 );
02186   printf(
02187 "    produces a conforming constrained Delaunay triangulation (CCDT), in\n");
02188   printf(
02189 "    which segments may be subdivided into smaller edges.  If -D is\n");
02190   printf(
02191 "    selected, Triangle produces a conforming Delaunay triangulation, so\n");
02192   printf(
02193 "    that every triangle is Delaunay, and not just constrained Delaunay.\n");
02194   printf("\n");
02195   printf(
02196 "    The third section lists holes (and concavities, if -c is selected) in\n");
02197   printf(
02198 "    the triangulation.  Holes are specified by identifying a point inside\n");
02199   printf(
02200 "    each hole.  After the triangulation is formed, Triangle creates holes\n");
02201   printf(
02202 "    by eating triangles, spreading out from each hole point until its\n");
02203   printf(
02204 "    progress is blocked by segments in the PSLG.  You must be careful to\n");
02205   printf(
02206 "    enclose each hole in segments, or your whole triangulation might be\n");
02207   printf(
02208 "    eaten away.  If the two triangles abutting a segment are eaten, the\n");
02209   printf(
02210 "    segment itself is also eaten.  Do not place a hole directly on a\n");
02211   printf("    segment; if you do, Triangle chooses one side of the segment\n");
02212   printf("    arbitrarily.\n\n");
02213   printf(
02214 "    The optional fourth section lists regional attributes (to be assigned\n");
02215   printf(
02216 "    to all triangles in a region) and regional constraints on the maximum\n");
02217   printf(
02218 "    triangle area.  Triangle reads this section only if the -A switch is\n");
02219   printf(
02220 "    used or the -a switch is used without a number following it, and the -r\n"
02221 );
02222   printf(
02223 "    switch is not used.  Regional attributes and area constraints are\n");
02224   printf(
02225 "    propagated in the same manner as holes:  you specify a point for each\n");
02226   printf(
02227 "    attribute and/or constraint, and the attribute and/or constraint\n");
02228   printf(
02229 "    affects the whole region (bounded by segments) containing the point.\n");
02230   printf(
02231 "    If two values are written on a line after the x and y coordinate, the\n");
02232   printf(
02233 "    first such value is assumed to be a regional attribute (but is only\n");
02234   printf(
02235 "    applied if the -A switch is selected), and the second value is assumed\n"
02236 );
02237   printf(
02238 "    to be a regional area constraint (but is only applied if the -a switch\n"
02239 );
02240   printf(
02241 "    is selected).  You may specify just one value after the coordinates,\n");
02242   printf(
02243 "    which can serve as both an attribute and an area constraint, depending\n"
02244 );
02245   printf(
02246 "    on the choice of switches.  If you are using the -A and -a switches\n");
02247   printf(
02248 "    simultaneously and wish to assign an attribute to some region without\n");
02249   printf("    imposing an area constraint, use a negative maximum area.\n\n");
02250   printf(
02251 "    When a triangulation is created from a .poly file, you must either\n");
02252   printf(
02253 "    enclose the entire region to be triangulated in PSLG segments, or\n");
02254   printf(
02255 "    use the -c switch, which automatically creates extra segments that\n");
02256   printf(
02257 "    enclose the convex hull of the PSLG.  If you do not use the -c switch,\n"
02258 );
02259   printf(
02260 "    Triangle eats all triangles that are not enclosed by segments; if you\n");
02261   printf(
02262 "    are not careful, your whole triangulation may be eaten away.  If you do\n"
02263 );
02264   printf(
02265 "    use the -c switch, you can still produce concavities by the appropriate\n"
02266 );
02267   printf(
02268 "    placement of holes just inside the boundary of the convex hull.\n");
02269   printf("\n");
02270   printf(
02271 "    An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
02272   printf(
02273 "    upon segments (except, of course, the endpoints of each segment).  You\n"
02274 );
02275   printf(
02276 "    aren't required to make your .poly files ideal, but you should be aware\n"
02277 );
02278   printf(
02279 "    of what can go wrong.  Segment intersections are relatively safe--\n");
02280   printf(
02281 "    Triangle calculates the intersection points for you and adds them to\n");
02282   printf(
02283 "    the triangulation--as long as your machine's floating-point precision\n");
02284   printf(
02285 "    doesn't become a problem.  You are tempting the fates if you have three\n"
02286 );
02287   printf(
02288 "    segments that cross at the same location, and expect Triangle to figure\n"
02289 );
02290   printf(
02291 "    out where the intersection point is.  Thanks to floating-point roundoff\n"
02292 );
02293   printf(
02294 "    error, Triangle will probably decide that the three segments intersect\n"
02295 );
02296   printf(
02297 "    at three different points, and you will find a minuscule triangle in\n");
02298   printf(
02299 "    your output--unless Triangle tries to refine the tiny triangle, uses\n");
02300   printf(
02301 "    up the last bit of machine precision, and fails to terminate at all.\n");
02302   printf(
02303 "    You're better off putting the intersection point in the input files,\n");
02304   printf(
02305 "    and manually breaking up each segment into two.  Similarly, if you\n");
02306   printf(
02307 "    place a vertex at the middle of a segment, and hope that Triangle will\n"
02308 );
02309   printf(
02310 "    break up the segment at that vertex, you might get lucky.  On the other\n"
02311 );
02312   printf(
02313 "    hand, Triangle might decide that the vertex doesn't lie precisely on\n");
02314   printf(
02315 "    the segment, and you'll have a needle-sharp triangle in your output--or\n"
02316 );
02317   printf("    a lot of tiny triangles if you're generating a quality mesh.\n");
02318   printf("\n");
02319   printf(
02320 "    When Triangle reads a .poly file, it also writes a .poly file, which\n");
02321   printf(
02322 "    includes all the subsegments--the edges that are parts of input\n");
02323   printf(
02324 "    segments.  If the -c switch is used, the output .poly file also\n");
02325   printf(
02326 "    includes all of the edges on the convex hull.  Hence, the output .poly\n"
02327 );
02328   printf(
02329 "    file is useful for finding edges associated with input segments and for\n"
02330 );
02331   printf(
02332 "    setting boundary conditions in finite element simulations.  Moreover,\n");
02333   printf(
02334 "    you will need the output .poly file if you plan to refine the output\n");
02335   printf(
02336 "    mesh, and don't want segments to be missing in later triangulations.\n");
02337   printf("\n");
02338   printf("  .area files:\n");
02339   printf("    First line:  <# of triangles>\n");
02340   printf("    Following lines:  <triangle #> <maximum area>\n");
02341   printf("\n");
02342   printf(
02343 "    An .area file associates with each triangle a maximum area that is used\n"
02344 );
02345   printf(
02346 "    for mesh refinement.  As with other file formats, every triangle must\n");
02347   printf(
02348 "    be represented, and the triangles must be numbered consecutively.  A\n");
02349   printf(
02350 "    triangle may be left unconstrained by assigning it a negative maximum\n");
02351   printf("    area.\n\n");
02352   printf("  .edge files:\n");
02353   printf("    First line:  <# of edges> <# of boundary markers (0 or 1)>\n");
02354   printf(
02355 "    Following lines:  <edge #> <endpoint> <endpoint> [boundary marker]\n");
02356   printf("\n");
02357   printf(
02358 "    Endpoints are indices into the corresponding .node file.  Triangle can\n"
02359 );
02360   printf(
02361 "    produce .edge files (use the -e switch), but cannot read them.  The\n");
02362   printf(
02363 "    optional column of boundary markers is suppressed by the -B switch.\n");
02364   printf("\n");
02365   printf(
02366 "    In Voronoi diagrams, one also finds a special kind of edge that is an\n");
02367   printf(
02368 "    infinite ray with only one endpoint.  For these edges, a different\n");
02369   printf("    format is used:\n\n");
02370   printf("        <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
02371   printf(
02372 "    The `direction' is a floating-point vector that indicates the direction\n"
02373 );
02374   printf("    of the infinite ray.\n\n");
02375   printf("  .neigh files:\n");
02376   printf(
02377 "    First line:  <# of triangles> <# of neighbors per triangle (always 3)>\n"
02378 );
02379   printf(
02380 "    Following lines:  <triangle #> <neighbor> <neighbor> <neighbor>\n");
02381   printf("\n");
02382   printf(
02383 "    Neighbors are indices into the corresponding .ele file.  An index of -1\n"
02384 );
02385   printf(
02386 "    indicates no neighbor (because the triangle is on an exterior\n");
02387   printf(
02388 "    boundary).  The first neighbor of triangle i is opposite the first\n");
02389   printf("    corner of triangle i, and so on.\n\n");
02390   printf(
02391 "    Triangle can produce .neigh files (use the -n switch), but cannot read\n"
02392 );
02393   printf("    them.\n\n");
02394   printf("Boundary Markers:\n\n");
02395   printf(
02396 "  Boundary markers are tags used mainly to identify which output vertices\n");
02397   printf(
02398 "  and edges are associated with which PSLG segment, and to identify which\n");
02399   printf(
02400 "  vertices and edges occur on a boundary of the triangulation.  A common\n");
02401   printf(
02402 "  use is to determine where boundary conditions should be applied to a\n");
02403   printf(
02404 "  finite element mesh.  You can prevent boundary markers from being written\n"
02405 );
02406   printf("  into files produced by Triangle by using the -B switch.\n\n");
02407   printf(
02408 "  The boundary marker associated with each segment in an output .poly file\n"
02409 );
02410   printf("  and each edge in an output .edge file is chosen as follows:\n");
02411   printf(
02412 "    - If an output edge is part or all of a PSLG segment with a nonzero\n");
02413   printf(
02414 "      boundary marker, then the edge is assigned the same marker.\n");
02415   printf(
02416 "    - Otherwise, if the edge lies on a boundary of the triangulation\n");
02417   printf(
02418 "      (even the boundary of a hole), then the edge is assigned the marker\n");
02419   printf("      one (1).\n");
02420   printf("    - Otherwise, the edge is assigned the marker zero (0).\n");
02421   printf(
02422 "  The boundary marker associated with each vertex in an output .node file\n");
02423   printf("  is chosen as follows:\n");
02424   printf(
02425 "    - If a vertex is assigned a nonzero boundary marker in the input file,\n"
02426 );
02427   printf(
02428 "      then it is assigned the same marker in the output .node file.\n");
02429   printf(
02430 "    - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
02431   printf(
02432 "      endpoint of the segment) with a nonzero boundary marker, then the\n");
02433   printf(
02434 "      vertex is assigned the same marker.  If the vertex lies on several\n");
02435   printf("      such segments, one of the markers is chosen arbitrarily.\n");
02436   printf(
02437 "    - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
02438   printf("      then the vertex is assigned the marker one (1).\n");
02439   printf("    - Otherwise, the vertex is assigned the marker zero (0).\n");
02440   printf("\n");
02441   printf(
02442 "  If you want Triangle to determine for you which vertices and edges are on\n"
02443 );
02444   printf(
02445 "  the boundary, assign them the boundary marker zero (or use no markers at\n"
02446 );
02447   printf(
02448 "  all) in your input files.  In the output files, all boundary vertices,\n");
02449   printf("  edges, and segments will be assigned the value one.\n\n");
02450   printf("Triangulation Iteration Numbers:\n\n");
02451   printf(
02452 "  Because Triangle can read and refine its own triangulations, input\n");
02453   printf(
02454 "  and output files have iteration numbers.  For instance, Triangle might\n");
02455   printf(
02456 "  read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
02457   printf(
02458 "  triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
02459   printf("  mesh.4.poly.  Files with no iteration number are treated as if\n");
02460   printf(
02461 "  their iteration number is zero; hence, Triangle might read the file\n");
02462   printf(
02463 "  points.node, triangulate it, and produce the files points.1.node and\n");
02464   printf("  points.1.ele.\n\n");
02465   printf(
02466 "  Iteration numbers allow you to create a sequence of successively finer\n");
02467   printf(
02468 "  meshes suitable for multigrid methods.  They also allow you to produce a\n"
02469 );
02470   printf(
02471 "  sequence of meshes using error estimate-driven mesh refinement.\n");
02472   printf("\n");
02473   printf(
02474 "  If you're not using refinement or quality meshing, and you don't like\n");
02475   printf(
02476 "  iteration numbers, use the -I switch to disable them.  This switch also\n");
02477   printf(
02478 "  disables output of .node and .poly files to prevent your input files from\n"
02479 );
02480   printf(
02481 "  being overwritten.  (If the input is a .poly file that contains its own\n");
02482   printf(
02483 "  points, a .node file is written.  This can be quite convenient for\n");
02484   printf("  computing CDTs or quality meshes.)\n\n");
02485   printf("Examples of How to Use Triangle:\n\n");
02486   printf(
02487 "  `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
02488 );
02489   printf(
02490 "  triangulation to dots.1.node and dots.1.ele.  (dots.1.node is identical\n");
02491   printf(
02492 "  to dots.node.)  `triangle -I dots' writes the triangulation to dots.ele\n");
02493   printf(
02494 "  instead.  (No additional .node file is needed, so none is written.)\n");
02495   printf("\n");
02496   printf(
02497 "  `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
02498   printf(
02499 "  object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
02500 );
02501   printf(
02502 "  its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
02503 );
02504   printf(
02505 "  The segments are copied to object.2.poly, and all edges are written to\n");
02506   printf("  object.2.edge.\n\n");
02507   printf(
02508 "  `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
02509 );
02510   printf(
02511 "  object.node), generates a mesh whose angles are all between 31.5 and 117\n"
02512 );
02513   printf(
02514 "  degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
02515 );
02516   printf(
02517 "  mesh to object.1.node and object.1.ele.  Each segment may be broken up\n");
02518   printf("  into multiple subsegments; these are written to object.1.poly.\n");
02519   printf("\n");
02520   printf(
02521 "  Here is a sample file `box.poly' describing a square with a square hole:\n"
02522 );
02523   printf("\n");
02524   printf(
02525 "    # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
02526 );
02527   printf("    8 2 0 1\n");
02528   printf("     # Outer box has these vertices:\n");
02529   printf("     1   0 0   0\n");
02530   printf("     2   0 3   0\n");
02531   printf("     3   3 0   0\n");
02532   printf("     4   3 3   33     # A special marker for this vertex.\n");
02533   printf("     # Inner square has these vertices:\n");
02534   printf("     5   1 1   0\n");
02535   printf("     6   1 2   0\n");
02536   printf("     7   2 1   0\n");
02537   printf("     8   2 2   0\n");
02538   printf("    # Five segments with boundary markers.\n");
02539   printf("    5 1\n");
02540   printf("     1   1 2   5      # Left side of outer box.\n");
02541   printf("     # Square hole has these segments:\n");
02542   printf("     2   5 7   0\n");
02543   printf("     3   7 8   0\n");
02544   printf("     4   8 6   10\n");
02545   printf("     5   6 5   0\n");
02546   printf("    # One hole in the middle of the inner square.\n");
02547   printf("    1\n");
02548   printf("     1   1.5 1.5\n");
02549   printf("\n");
02550   printf(
02551 "  Note that some segments are missing from the outer square, so you must\n");
02552   printf(
02553 "  use the `-c' switch.  After `triangle -pqc box.poly', here is the output\n"
02554 );
02555   printf(
02556 "  file `box.1.node', with twelve vertices.  The last four vertices were\n");
02557   printf(
02558 "  added to meet the angle constraint.  Vertices 1, 2, and 9 have markers\n");
02559   printf(
02560 "  from segment 1.  Vertices 6 and 8 have markers from segment 4.  All the\n");
02561   printf(
02562 "  other vertices but 4 have been marked to indicate that they lie on a\n");
02563   printf("  boundary.\n\n");
02564   printf("    12  2  0  1\n");
02565   printf("       1    0   0      5\n");
02566   printf("       2    0   3      5\n");
02567   printf("       3    3   0      1\n");
02568   printf("       4    3   3     33\n");
02569   printf("       5    1   1      1\n");
02570   printf("       6    1   2     10\n");
02571   printf("       7    2   1      1\n");
02572   printf("       8    2   2     10\n");
02573   printf("       9    0   1.5    5\n");
02574   printf("      10    1.5   0    1\n");
02575   printf("      11    3   1.5    1\n");
02576   printf("      12    1.5   3    1\n");
02577   printf("    # Generated by triangle -pqc box.poly\n");
02578   printf("\n");
02579   printf("  Here is the output file `box.1.ele', with twelve triangles.\n");
02580   printf("\n");
02581   printf("    12  3  0\n");
02582   printf("       1     5   6   9\n");
02583   printf("       2    10   3   7\n");
02584   printf("       3     6   8  12\n");
02585   printf("       4     9   1   5\n");
02586   printf("       5     6   2   9\n");
02587   printf("       6     7   3  11\n");
02588   printf("       7    11   4   8\n");
02589   printf("       8     7   5  10\n");
02590   printf("       9    12   2   6\n");
02591   printf("      10     8   7  11\n");
02592   printf("      11     5   1  10\n");
02593   printf("      12     8   4  12\n");
02594   printf("    # Generated by triangle -pqc box.poly\n\n");
02595   printf(
02596 "  Here is the output file `box.1.poly'.  Note that segments have been added\n"
02597 );
02598   printf(
02599 "  to represent the convex hull, and some segments have been subdivided by\n");
02600   printf(
02601 "  newly added vertices.  Note also that <# of vertices> is set to zero to\n");
02602   printf("  indicate that the vertices should be read from the .node file.\n");
02603   printf("\n");
02604   printf("    0  2  0  1\n");
02605   printf("    12  1\n");
02606   printf("       1     1   9     5\n");
02607   printf("       2     5   7     1\n");
02608   printf("       3     8   7     1\n");
02609   printf("       4     6   8    10\n");
02610   printf("       5     5   6     1\n");
02611   printf("       6     3  10     1\n");
02612   printf("       7     4  11     1\n");
02613   printf("       8     2  12     1\n");
02614   printf("       9     9   2     5\n");
02615   printf("      10    10   1     1\n");
02616   printf("      11    11   3     1\n");
02617   printf("      12    12   4     1\n");
02618   printf("    1\n");
02619   printf("       1   1.5 1.5\n");
02620   printf("    # Generated by triangle -pqc box.poly\n");
02621   printf("\n");
02622   printf("Refinement and Area Constraints:\n");
02623   printf("\n");
02624   printf(
02625 "  The -r switch causes a mesh (.node and .ele files) to be read and\n");
02626   printf(
02627 "  refined.  If the -p switch is also used, a .poly file is read and used to\n"
02628 );
02629   printf(
02630 "  specify edges that are constrained and cannot be eliminated (although\n");
02631   printf(
02632 "  they can be subdivided into smaller edges) by the refinement process.\n");
02633   printf("\n");
02634   printf(
02635 "  When you refine a mesh, you generally want to impose tighter constraints.\n"
02636 );
02637   printf(
02638 "  One way to accomplish this is to use -q with a larger angle, or -a\n");
02639   printf(
02640 "  followed by a smaller area than you used to generate the mesh you are\n");
02641   printf(
02642 "  refining.  Another way to do this is to create an .area file, which\n");
02643   printf(
02644 "  specifies a maximum area for each triangle, and use the -a switch\n");
02645   printf(
02646 "  (without a number following).  Each triangle's area constraint is applied\n"
02647 );
02648   printf(
02649 "  to that triangle.  Area constraints tend to diffuse as the mesh is\n");
02650   printf(
02651 "  refined, so if there are large variations in area constraint between\n");
02652   printf(
02653 "  adjacent triangles, you may not get the results you want.  In that case,\n"
02654 );
02655   printf(
02656 "  consider instead using the -u switch and writing a C procedure that\n");
02657   printf("  determines which triangles are too large.\n\n");
02658   printf(
02659 "  If you are refining a mesh composed of linear (three-node) elements, the\n"
02660 );
02661   printf(
02662 "  output mesh contains all the nodes present in the input mesh, in the same\n"
02663 );
02664   printf(
02665 "  order, with new nodes added at the end of the .node file.  However, the\n");
02666   printf(
02667 "  refinement is not hierarchical: there is no guarantee that each output\n");
02668   printf(
02669 "  element is contained in a single input element.  Often, an output element\n"
02670 );
02671   printf(
02672 "  can overlap two or three input elements, and some input edges are not\n");
02673   printf(
02674 "  present in the output mesh.  Hence, a sequence of refined meshes forms a\n"
02675 );
02676   printf(
02677 "  hierarchy of nodes, but not a hierarchy of elements.  If you refine a\n");
02678   printf(
02679 "  mesh of higher-order elements, the hierarchical property applies only to\n"
02680 );
02681   printf(
02682 "  the nodes at the corners of an element; the midpoint nodes on each edge\n");
02683   printf("  are discarded before the mesh is refined.\n\n");
02684   printf(
02685 "  Maximum area constraints in .poly files operate differently from those in\n"
02686 );
02687   printf(
02688 "  .area files.  A maximum area in a .poly file applies to the whole\n");
02689   printf(
02690 "  (segment-bounded) region in which a point falls, whereas a maximum area\n");
02691   printf(
02692 "  in an .area file applies to only one triangle.  Area constraints in .poly\n"
02693 );
02694   printf(
02695 "  files are used only when a mesh is first generated, whereas area\n");
02696   printf(
02697 "  constraints in .area files are used only to refine an existing mesh, and\n"
02698 );
02699   printf(
02700 "  are typically based on a posteriori error estimates resulting from a\n");
02701   printf("  finite element simulation on that mesh.\n\n");
02702   printf(
02703 "  `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
02704   printf(
02705 "  refines the triangulation to enforce a 25 degree minimum angle, and then\n"
02706 );
02707   printf(
02708 "  writes the refined triangulation to object.2.node and object.2.ele.\n");
02709   printf("\n");
02710   printf(
02711 "  `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
02712 );
02713   printf(
02714 "  After reconstructing the mesh and its subsegments, Triangle refines the\n");
02715   printf(
02716 "  mesh so that no triangle has area greater than 6.2, and furthermore the\n");
02717   printf(
02718 "  triangles satisfy the maximum area constraints in z.3.area.  No angle\n");
02719   printf(
02720 "  bound is imposed at all.  The output is written to z.4.node, z.4.ele, and\n"
02721 );
02722   printf("  z.4.poly.\n\n");
02723   printf(
02724 "  The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
02725   printf(
02726 "  x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
02727   printf("  suitable for multigrid.\n\n");
02728   printf("Convex Hulls and Mesh Boundaries:\n\n");
02729   printf(
02730 "  If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
02731   printf(
02732 "  hull as a by-product in the output .poly file if you use the -c switch.\n");
02733   printf(
02734 "  There are faster algorithms for finding a two-dimensional convex hull\n");
02735   printf("  than triangulation, of course, but this one comes for free.\n\n");
02736   printf(
02737 "  If the input is an unconstrained mesh (you are using the -r switch but\n");
02738   printf(
02739 "  not the -p switch), Triangle produces a list of its boundary edges\n");
02740   printf(
02741 "  (including hole boundaries) as a by-product when you use the -c switch.\n");
02742   printf(
02743 "  If you also use the -p switch, the output .poly file contains all the\n");
02744   printf("  segments from the input .poly file as well.\n\n");
02745   printf("Voronoi Diagrams:\n\n");
02746   printf(
02747 "  The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
02748   printf(
02749 "  .v.edge.  For example, `triangle -v points' reads points.node, produces\n");
02750   printf(
02751 "  its Delaunay triangulation in points.1.node and points.1.ele, and\n");
02752   printf(
02753 "  produces its Voronoi diagram in points.1.v.node and points.1.v.edge.  The\n"
02754 );
02755   printf(
02756 "  .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
02757   printf(
02758 "  file contains a list of all Voronoi edges, some of which may be infinite\n"
02759 );
02760   printf(
02761 "  rays.  (The choice of filenames makes it easy to run the set of Voronoi\n");
02762   printf("  vertices through Triangle, if so desired.)\n\n");
02763   printf(
02764 "  This implementation does not use exact arithmetic to compute the Voronoi\n"
02765 );
02766   printf(
02767 "  vertices, and does not check whether neighboring vertices are identical.\n"
02768 );
02769   printf(
02770 "  Be forewarned that if the Delaunay triangulation is degenerate or\n");
02771   printf(
02772 "  near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
02773   printf("  crossing edges.\n\n");
02774   printf(
02775 "  The result is a valid Voronoi diagram only if Triangle's output is a true\n"
02776 );
02777   printf(
02778 "  Delaunay triangulation.  The Voronoi output is usually meaningless (and\n");
02779   printf(
02780 "  may contain crossing edges and other pathology) if the output is a CDT or\n"
02781 );
02782   printf(
02783 "  CCDT, or if it has holes or concavities.  If the triangulated domain is\n");
02784   printf(
02785 "  convex and has no holes, you can use -D switch to force Triangle to\n");
02786   printf(
02787 "  construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
02788   printf("  Voronoi diagram will be valid.\n\n");
02789   printf("Mesh Topology:\n\n");
02790   printf(
02791 "  You may wish to know which triangles are adjacent to a certain Delaunay\n");
02792   printf(
02793 "  edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
02794   printf(
02795 "  Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
02796   printf(
02797 "  each other.  All of this information can be found by cross-referencing\n");
02798   printf(
02799 "  output files with the recollection that the Delaunay triangulation and\n");
02800   printf("  the Voronoi diagram are planar duals.\n\n");
02801   printf(
02802 "  Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
02803   printf(
02804 "  the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
02805   printf(
02806 "  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of\n");
02807   printf(
02808 "  vertex j of the corresponding .v.node file.  Voronoi cell k is the dual\n");
02809   printf("  of vertex k of the corresponding .node file.\n\n");
02810   printf(
02811 "  Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
02812   printf(
02813 "  vertices of the corresponding Voronoi edge.  If the endpoints of a\n");
02814   printf(
02815 "  Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
02816 );
02817   printf(
02818 "  and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
02819 );
02820   printf(
02821 "  respectively.  To find the Voronoi cells adjacent to a Voronoi edge, look\n"
02822 );
02823   printf(
02824 "  at the endpoints of the corresponding Delaunay edge.  If the endpoints of\n"
02825 );
02826   printf(
02827 "  a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
02828 );
02829   printf(
02830 "  adjoin the right and left sides of the corresponding Voronoi edge,\n");
02831   printf(
02832 "  respectively.  To find which Voronoi cells are adjacent to each other,\n");
02833   printf("  just read the list of Delaunay edges.\n\n");
02834   printf(
02835 "  Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
02836 );
02837   printf(
02838 "  but you can reconstructed it straightforwardly.  For instance, to find\n");
02839   printf(
02840 "  all the edges of Voronoi cell 1, search the output .edge file for every\n");
02841   printf(
02842 "  edge that has input vertex 1 as an endpoint.  The corresponding dual\n");
02843   printf(
02844 "  edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
02845   printf("\n");
02846   printf(
02847 "  For each Voronoi vertex, the .neigh file gives a list of the three\n");
02848   printf(
02849 "  Voronoi vertices attached to it.  You might find this more convenient\n");
02850   printf("  than the .v.edge file.\n\n");
02851   printf("Quadratic Elements:\n\n");
02852   printf(
02853 "  Triangle generates meshes with subparametric quadratic elements if the\n");
02854   printf(
02855 "  -o2 switch is specified.  Quadratic elements have six nodes per element,\n"
02856 );
02857   printf(
02858 "  rather than three.  `Subparametric' means that the edges of the triangles\n"
02859 );
02860   printf(
02861 "  are always straight, so that subparametric quadratic elements are\n");
02862   printf(
02863 "  geometrically identical to linear elements, even though they can be used\n"
02864 );
02865   printf(
02866 "  with quadratic interpolating functions.  The three extra nodes of an\n");
02867   printf(
02868 "  element fall at the midpoints of the three edges, with the fourth, fifth,\n"
02869 );
02870   printf(
02871 "  and sixth nodes appearing opposite the first, second, and third corners\n");
02872   printf("  respectively.\n\n");
02873   printf("Domains with Small Angles:\n\n");
02874   printf(
02875 "  If two input segments adjoin each other at a small angle, clearly the -q\n"
02876 );
02877   printf(
02878 "  switch cannot remove the small angle.  Moreover, Triangle may have no\n");
02879   printf(
02880 "  choice but to generate additional triangles whose smallest angles are\n");
02881   printf(
02882 "  smaller than the specified bound.  However, these triangles only appear\n");
02883   printf(
02884 "  between input segments separated by small angles.  Moreover, if you\n");
02885   printf(
02886 "  request a minimum angle of theta degrees, Triangle will generally produce\n"
02887 );
02888   printf(
02889 "  no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
02890 );
02891   printf("  the minimum angle.\n\n");
02892   printf("Statistics:\n\n");
02893   printf(
02894 "  After generating a mesh, Triangle prints a count of entities in the\n");
02895   printf(
02896 "  output mesh, including the number of vertices, triangles, edges, exterior\n"
02897 );
02898   printf(
02899 "  boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
02900   printf(
02901 "  including hole boundaries), interior boundary edges (i.e. subsegments of\n"
02902 );
02903   printf(
02904 "  input segments not on the boundary), and total subsegments.  If you've\n");
02905   printf(
02906 "  forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
02907 );
02908   printf(
02909 "  with the -rNEP switches to read the mesh and print the statistics without\n"
02910 );
02911   printf(
02912 "  writing any files.  Use -rpNEP if you've got a .poly file for the mesh.\n");
02913   printf("\n");
02914   printf(
02915 "  The -V switch produces extended statistics, including a rough estimate\n");
02916   printf(
02917 "  of memory use, the number of calls to geometric predicates, and\n");
02918   printf(
02919 "  histograms of the angles and the aspect ratios of the triangles in the\n");
02920   printf("  mesh.\n\n");
02921   printf("Exact Arithmetic:\n\n");
02922   printf(
02923 "  Triangle uses adaptive exact arithmetic to perform what computational\n");
02924   printf(
02925 "  geometers call the `orientation' and `incircle' tests.  If the floating-\n"
02926 );
02927   printf(
02928 "  point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
02929   printf(
02930 "  most workstations do), and does not use extended precision internal\n");
02931   printf(
02932 "  floating-point registers, then your output is guaranteed to be an\n");
02933   printf(
02934 "  absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
02935 );
02936   printf(
02937 "  error notwithstanding.  The word `adaptive' implies that these arithmetic\n"
02938 );
02939   printf(
02940 "  routines compute the result only to the precision necessary to guarantee\n"
02941 );
02942   printf(
02943 "  correctness, so they are usually nearly as fast as their approximate\n");
02944   printf("  counterparts.\n\n");
02945   printf(
02946 "  May CPUs, including Intel x86 processors, have extended precision\n");
02947   printf(
02948 "  floating-point registers.  These must be reconfigured so their precision\n"
02949 );
02950   printf(
02951 "  is reduced to memory precision.  Triangle does this if it is compiled\n");
02952   printf("  correctly.  See the makefile for details.\n\n");
02953   printf(
02954 "  The exact tests can be disabled with the -X switch.  On most inputs, this\n"
02955 );
02956   printf(
02957 "  switch reduces the computation time by about eight percent--it's not\n");
02958   printf(
02959 "  worth the risk.  There are rare difficult inputs (having many collinear\n");
02960   printf(
02961 "  and cocircular vertices), however, for which the difference in speed\n");
02962   printf(
02963 "  could be a factor of two.  Be forewarned that these are precisely the\n");
02964   printf(
02965 "  inputs most likely to cause errors if you use the -X switch.  Hence, the\n"
02966 );
02967   printf("  -X switch is not recommended.\n\n");
02968   printf(
02969 "  Unfortunately, the exact tests don't solve every numerical problem.\n");
02970   printf(
02971 "  Exact arithmetic is not used to compute the positions of new vertices,\n");
02972   printf(
02973 "  because the bit complexity of vertex coordinates would grow without\n");
02974   printf(
02975 "  bound.  Hence, segment intersections aren't computed exactly; in very\n");
02976   printf(
02977 "  unusual cases, roundoff error in computing an intersection point might\n");
02978   printf(
02979 "  actually lead to an inverted triangle and an invalid triangulation.\n");
02980   printf(
02981 "  (This is one reason to specify your own intersection points in your .poly\n"
02982 );
02983   printf(
02984 "  files.)  Similarly, exact arithmetic is not used to compute the vertices\n"
02985 );
02986   printf("  of the Voronoi diagram.\n\n");
02987   printf(
02988 "  Another pair of problems not solved by the exact arithmetic routines is\n");
02989   printf(
02990 "  underflow and overflow.  If Triangle is compiled for double precision\n");
02991   printf(
02992 "  arithmetic, I believe that Triangle's geometric predicates work correctly\n"
02993 );
02994   printf(
02995 "  if the exponent of every input coordinate falls in the range [-148, 201].\n"
02996 );
02997   printf(
02998 "  Underflow can silently prevent the orientation and incircle tests from\n");
02999   printf(
03000 "  being performed exactly, while overflow typically causes a floating\n");
03001   printf("  exception.\n\n");
03002   printf("Calling Triangle from Another Program:\n\n");
03003   printf("  Read the file triangle.h for details.\n\n");
03004   printf("Troubleshooting:\n\n");
03005   printf("  Please read this section before mailing me bugs.\n\n");
03006   printf("  `My output mesh has no triangles!'\n\n");
03007   printf(
03008 "    If you're using a PSLG, you've probably failed to specify a proper set\n"
03009 );
03010   printf(
03011 "    of bounding segments, or forgotten to use the -c switch.  Or you may\n");
03012   printf(
03013 "    have placed a hole badly, thereby eating all your triangles.  To test\n");
03014   printf("    these possibilities, try again with the -c and -O switches.\n");
03015   printf(
03016 "    Alternatively, all your input vertices may be collinear, in which case\n"
03017 );
03018   printf("    you can hardly expect to triangulate them.\n\n");
03019   printf("  `Triangle doesn't terminate, or just crashes.'\n\n");
03020   printf(
03021 "    Bad things can happen when triangles get so small that the distance\n");
03022   printf(
03023 "    between their vertices isn't much larger than the precision of your\n");
03024   printf(
03025 "    machine's arithmetic.  If you've compiled Triangle for single-precision\n"
03026 );
03027   printf(
03028 "    arithmetic, you might do better by recompiling it for double-precision.\n"
03029 );
03030   printf(
03031 "    Then again, you might just have to settle for more lenient constraints\n"
03032 );
03033   printf(
03034 "    on the minimum angle and the maximum area than you had planned.\n");
03035   printf("\n");
03036   printf(
03037 "    You can minimize precision problems by ensuring that the origin lies\n");
03038   printf(
03039 "    inside your vertex set, or even inside the densest part of your\n");
03040   printf(
03041 "    mesh.  If you're triangulating an object whose x-coordinates all fall\n");
03042   printf(
03043 "    between 6247133 and 6247134, you're not leaving much floating-point\n");
03044   printf("    precision for Triangle to work with.\n\n");
03045   printf(
03046 "    Precision problems can occur covertly if the input PSLG contains two\n");
03047   printf(
03048 "    segments that meet (or intersect) at an extremely small angle, or if\n");
03049   printf(
03050 "    such an angle is introduced by the -c switch.  If you don't realize\n");
03051   printf(
03052 "    that a tiny angle is being formed, you might never discover why\n");
03053   printf(
03054 "    Triangle is crashing.  To check for this possibility, use the -S switch\n"
03055 );
03056   printf(
03057 "    (with an appropriate limit on the number of Steiner points, found by\n");
03058   printf(
03059 "    trial-and-error) to stop Triangle early, and view the output .poly file\n"
03060 );
03061   printf(
03062 "    with Show Me (described below).  Look carefully for regions where dense\n"
03063 );
03064   printf(
03065 "    clusters of vertices are forming and for small angles between segments.\n"
03066 );
03067   printf(
03068 "    Zoom in closely, as such segments might look like a single segment from\n"
03069 );
03070   printf("    a distance.\n\n");
03071   printf(
03072 "    If some of the input values are too large, Triangle may suffer a\n");
03073   printf(
03074 "    floating exception due to overflow when attempting to perform an\n");
03075   printf(
03076 "    orientation or incircle test.  (Read the section on exact arithmetic\n");
03077   printf(
03078 "    above.)  Again, I recommend compiling Triangle for double (rather\n");
03079   printf("    than single) precision arithmetic.\n\n");
03080   printf(
03081 "    Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
03082   printf(
03083 "    -u) with an input that is not segment-bounded--that is, if your input\n");
03084   printf(
03085 "    is a vertex set, or you're using the -c switch.  If the convex hull of\n"
03086 );
03087   printf(
03088 "    your input vertices has collinear vertices on its boundary, an input\n");
03089   printf(
03090 "    vertex that you think lies on the convex hull might actually lie just\n");
03091   printf(
03092 "    inside the convex hull.  If so, the vertex and the nearby convex hull\n");
03093   printf(
03094 "    edge form an extremely thin triangle.  When Triangle tries to refine\n");
03095   printf(
03096 "    the mesh to enforce angle and area constraints, Triangle might generate\n"
03097 );
03098   printf(
03099 "    extremely tiny triangles, or it might fail because of insufficient\n");
03100   printf("    floating-point precision.\n\n");
03101   printf(
03102 "  `The numbering of the output vertices doesn't match the input vertices.'\n"
03103 );
03104   printf("\n");
03105   printf(
03106 "    You may have had duplicate input vertices, or you may have eaten some\n");
03107   printf(
03108 "    of your input vertices with a hole, or by placing them outside the area\n"
03109 );
03110   printf(
03111 "    enclosed by segments.  In any case, you can solve the problem by not\n");
03112   printf("    using the -j switch.\n\n");
03113   printf(
03114 "  `Triangle executes without incident, but when I look at the resulting\n");
03115   printf(
03116 "  mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
03117   printf("\n");
03118   printf(
03119 "    If you select the -X switch, Triangle occasionally makes mistakes due\n");
03120   printf(
03121 "    to floating-point roundoff error.  Although these errors are rare,\n");
03122   printf(
03123 "    don't use the -X switch.  If you still have problems, please report the\n"
03124 );
03125   printf("    bug.\n\n");
03126   printf(
03127 "  `Triangle executes without incident, but when I look at the resulting\n");
03128   printf("  Voronoi diagram, it has overlapping edges or other geometric\n");
03129   printf("  inconsistencies.'\n");
03130   printf("\n");
03131   printf(
03132 "    If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
03133 );
03134   printf(
03135 "    diagram if the domain you are triangulating is convex and free of\n");
03136   printf(
03137 "    holes, and you use the -D switch to construct a conforming Delaunay\n");
03138   printf("    triangulation (instead of a CDT or CCDT).\n\n");
03139   printf(
03140 "  Strange things can happen if you've taken liberties with your PSLG.  Do\n");
03141   printf(
03142 "  you have a vertex lying in the middle of a segment?  Triangle sometimes\n");
03143   printf(
03144 "  copes poorly with that sort of thing.  Do you want to lay out a collinear\n"
03145 );
03146   printf(
03147 "  row of evenly spaced, segment-connected vertices?  Have you simply\n");
03148   printf(
03149 "  defined one long segment connecting the leftmost vertex to the rightmost\n"
03150 );
03151   printf(
03152 "  vertex, and a bunch of vertices lying along it?  This method occasionally\n"
03153 );
03154   printf(
03155 "  works, especially with horizontal and vertical lines, but often it\n");
03156   printf(
03157 "  doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
03158 );
03159   printf("  separate segment.  If you don't like it, tough.\n\n");
03160   printf(
03161 "  Furthermore, if you have segments that intersect other than at their\n");
03162   printf(
03163 "  endpoints, try not to let the intersections fall extremely close to PSLG\n"
03164 );
03165   printf("  vertices or each other.\n\n");
03166   printf(
03167 "  If you have problems refining a triangulation not produced by Triangle:\n");
03168   printf(
03169 "  Are you sure the triangulation is geometrically valid?  Is it formatted\n");
03170   printf(
03171 "  correctly for Triangle?  Are the triangles all listed so the first three\n"
03172 );
03173   printf(
03174 "  vertices are their corners in counterclockwise order?  Are all of the\n");
03175   printf(
03176 "  triangles constrained Delaunay?  Triangle's Delaunay refinement algorithm\n"
03177 );
03178   printf("  assumes that it starts with a CDT.\n\n");
03179   printf("Show Me:\n\n");
03180   printf(
03181 "  Triangle comes with a separate program named `Show Me', whose primary\n");
03182   printf(
03183 "  purpose is to draw meshes on your screen or in PostScript.  Its secondary\n"
03184 );
03185   printf(
03186 "  purpose is to check the validity of your input files, and do so more\n");
03187   printf(
03188 "  thoroughly than Triangle does.  Unlike Triangle, Show Me requires that\n");
03189   printf(
03190 "  you have the X Windows system.  Sorry, Microsoft Windows users.\n");
03191   printf("\n");
03192   printf("Triangle on the Web:\n");
03193   printf("\n");
03194   printf("  To see an illustrated version of these instructions, check out\n");
03195   printf("\n");
03196   printf("    http://www.cs.cmu.edu/~quake/triangle.html\n");
03197   printf("\n");
03198   printf("A Brief Plea:\n");
03199   printf("\n");
03200   printf(
03201 "  If you use Triangle, and especially if you use it to accomplish real\n");
03202   printf(
03203 "  work, I would like very much to hear from you.  A short letter or email\n");
03204   printf(
03205 "  (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
03206 );
03207   printf(
03208 "  to me.  The more people I know are using this program, the more easily I\n"
03209 );
03210   printf(
03211 "  can justify spending time on improvements, which in turn will benefit\n");
03212   printf(
03213 "  you.  Also, I can put you on a list to receive email whenever a new\n");
03214   printf("  version of Triangle is available.\n\n");
03215   printf(
03216 "  If you use a mesh generated by Triangle in a publication, please include\n"
03217 );
03218   printf(
03219 "  an acknowledgment as well.  And please spell Triangle with a capital `T'!\n"
03220 );
03221   printf(
03222 "  If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
03223   printf(
03224 "  ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
03225   printf(
03226 "  Triangulator,'' in Applied Computational Geometry:  Towards Geometric\n");
03227   printf(
03228 "  Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
03229   printf(
03230 "  Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
03231   printf(
03232 "  Berlin, May 1996.  (From the First ACM Workshop on Applied Computational\n"
03233 );
03234   printf("  Geometry.)'\n\n");
03235   printf("Research credit:\n\n");
03236   printf(
03237 "  Of course, I can take credit for only a fraction of the ideas that made\n");
03238   printf(
03239 "  this mesh generator possible.  Triangle owes its existence to the efforts\n"
03240 );
03241   printf(
03242 "  of many fine computational geometers and other researchers, including\n");
03243   printf(
03244 "  Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
03245 );
03246   printf(
03247 "  Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
03248   printf(
03249 "  Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
03250   printf(
03251 "  Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
03252   printf(
03253 "  Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
03254 );
03255   printf("  Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
03256   printf(
03257 "  Walkington, and Binhai Zhu.  See the comments at the beginning of the\n");
03258   printf("  source code for references.\n\n");
03259   triexit(0);
03260 }
03261 
03262 #endif 
03263 
03264 
03265 
03266 
03267 
03268 
03269 
03270 void internalerror()
03271 {
03272   printf("  Please report this bug to jrs@cs.berkeley.edu\n");
03273   printf("  Include the message above, your input data set, and the exact\n");
03274   printf("    command line you used to run Triangle.\n");
03275   triexit(1);
03276 }
03277 
03278 
03279 
03280 
03281 
03282 
03283 
03284 
03285 #ifdef ANSI_DECLARATORS
03286 void parsecommandline(int argc, char **argv, struct behavior *b)
03287 #else 
03288 void parsecommandline(argc, argv, b)
03289 int argc;
03290 char **argv;
03291 struct behavior *b;
03292 #endif 
03293 
03294 {
03295 #ifdef TRILIBRARY
03296 #define STARTINDEX 0
03297 #else 
03298 #define STARTINDEX 1
03299   int increment;
03300   int meshnumber;
03301 #endif 
03302   int i, j, k;
03303   char workstring[FILENAMESIZE];
03304 
03305   b->poly = b->refine = b->quality = 0;
03306   b->vararea = b->fixedarea = b->usertest = 0;
03307   b->regionattrib = b->convex = b->weighted = b->jettison = 0;
03308   b->firstnumber = 1;
03309   b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
03310   b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
03311   b->noiterationnum = 0;
03312   b->noholes = b->noexact = 0;
03313   b->incremental = b->sweepline = 0;
03314   b->dwyer = 1;
03315   b->splitseg = 0;
03316   b->docheck = 0;
03317   b->nobisect = 0;
03318   b->conformdel = 0;
03319   b->steiner = -1;
03320   b->order = 1;
03321   b->minangle = 0.0;
03322   b->maxarea = -1.0;
03323   b->quiet = b->verbose = 0;
03324 #ifndef TRILIBRARY
03325   b->innodefilename[0] = '\0';
03326 #endif 
03327 
03328   for (i = STARTINDEX; i < argc; i++) {
03329 #ifndef TRILIBRARY
03330     if (argv[i][0] == '-') {
03331 #endif 
03332       for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
03333         if (argv[i][j] == 'p') {
03334           b->poly = 1;
03335         }
03336 #ifndef CDT_ONLY
03337         if (argv[i][j] == 'r') {
03338           b->refine = 1;
03339         }
03340         if (argv[i][j] == 'q') {
03341           b->quality = 1;
03342           if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03343               (argv[i][j + 1] == '.')) {
03344             k = 0;
03345             while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03346                    (argv[i][j + 1] == '.')) {
03347               j++;
03348               workstring[k] = argv[i][j];
03349               k++;
03350             }
03351             workstring[k] = '\0';
03352             b->minangle = (REAL) strtod(workstring, (char **) NULL);
03353           } else {
03354             b->minangle = 20.0;
03355           }
03356         }
03357         if (argv[i][j] == 'a') {
03358           b->quality = 1;
03359           if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03360               (argv[i][j + 1] == '.')) {
03361             b->fixedarea = 1;
03362             k = 0;
03363             while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03364                    (argv[i][j + 1] == '.')) {
03365               j++;
03366               workstring[k] = argv[i][j];
03367               k++;
03368             }
03369             workstring[k] = '\0';
03370             b->maxarea = (REAL) strtod(workstring, (char **) NULL);
03371             if (b->maxarea <= 0.0) {
03372               printf("Error:  Maximum area must be greater than zero.\n");
03373               triexit(1);
03374             }
03375           } else {
03376             b->vararea = 1;
03377           }
03378         }
03379         if (argv[i][j] == 'u') {
03380           b->quality = 1;
03381           b->usertest = 1;
03382         }
03383 #endif 
03384         if (argv[i][j] == 'A') {
03385           b->regionattrib = 1;
03386         }
03387         if (argv[i][j] == 'c') {
03388           b->convex = 1;
03389         }
03390         if (argv[i][j] == 'w') {
03391           b->weighted = 1;
03392         }
03393         if (argv[i][j] == 'W') {
03394           b->weighted = 2;
03395         }
03396         if (argv[i][j] == 'j') {
03397           b->jettison = 1;
03398         }
03399         if (argv[i][j] == 'z') {
03400           b->firstnumber = 0;
03401         }
03402         if (argv[i][j] == 'e') {
03403           b->edgesout = 1;
03404         }
03405         if (argv[i][j] == 'v') {
03406           b->voronoi = 1;
03407         }
03408         if (argv[i][j] == 'n') {
03409           b->neighbors = 1;
03410         }
03411         if (argv[i][j] == 'g') {
03412           b->geomview = 1;
03413         }
03414         if (argv[i][j] == 'B') {
03415           b->nobound = 1;
03416         }
03417         if (argv[i][j] == 'P') {
03418           b->nopolywritten = 1;
03419         }
03420         if (argv[i][j] == 'N') {
03421           b->nonodewritten = 1;
03422         }
03423         if (argv[i][j] == 'E') {
03424           b->noelewritten = 1;
03425         }
03426 #ifndef TRILIBRARY
03427         if (argv[i][j] == 'I') {
03428           b->noiterationnum = 1;
03429         }
03430 #endif 
03431         if (argv[i][j] == 'O') {
03432           b->noholes = 1;
03433         }
03434         if (argv[i][j] == 'X') {
03435           b->noexact = 1;
03436         }
03437         if (argv[i][j] == 'o') {
03438           if (argv[i][j + 1] == '2') {
03439             j++;
03440             b->order = 2;
03441           }
03442         }
03443 #ifndef CDT_ONLY
03444         if (argv[i][j] == 'Y') {
03445           b->nobisect++;
03446         }
03447         if (argv[i][j] == 'S') {
03448           b->steiner = 0;
03449           while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
03450             j++;
03451             b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
03452           }
03453         }
03454 #endif 
03455 #ifndef REDUCED
03456         if (argv[i][j] == 'i') {
03457           b->incremental = 1;
03458         }
03459         if (argv[i][j] == 'F') {
03460           b->sweepline = 1;
03461         }
03462 #endif 
03463         if (argv[i][j] == 'l') {
03464           b->dwyer = 0;
03465         }
03466 #ifndef REDUCED
03467 #ifndef CDT_ONLY
03468         if (argv[i][j] == 's') {
03469           b->splitseg = 1;
03470         }
03471         if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
03472           b->quality = 1;
03473           b->conformdel = 1;
03474         }
03475 #endif 
03476         if (argv[i][j] == 'C') {
03477           b->docheck = 1;
03478         }
03479 #endif 
03480         if (argv[i][j] == 'Q') {
03481           b->quiet = 1;
03482         }
03483         if (argv[i][j] == 'V') {
03484           b->verbose++;
03485         }
03486 #ifndef TRILIBRARY
03487         if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03488             (argv[i][j] == '?')) {
03489           info();
03490         }
03491 #endif 
03492       }
03493 #ifndef TRILIBRARY
03494     } else {
03495       strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
03496       b->innodefilename[FILENAMESIZE - 1] = '\0';
03497     }
03498 #endif 
03499   }
03500 #ifndef TRILIBRARY
03501   if (b->innodefilename[0] == '\0') {
03502     syntax();
03503   }
03504   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
03505     b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03506   }
03507   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
03508     b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03509     b->poly = 1;
03510   }
03511 #ifndef CDT_ONLY
03512   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
03513     b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
03514     b->refine = 1;
03515   }
03516   if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
03517     b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03518     b->refine = 1;
03519     b->quality = 1;
03520     b->vararea = 1;
03521   }
03522 #endif 
03523 #endif 
03524   b->usesegments = b->poly || b->refine || b->quality || b->convex;
03525   b->goodangle = cos(b->minangle * PI / 180.0);
03526   if (b->goodangle == 1.0) {
03527     b->offconstant = 0.0;
03528   } else {
03529     b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
03530   }
03531   b->goodangle *= b->goodangle;
03532   if (b->refine && b->noiterationnum) {
03533     printf(
03534       "Error:  You cannot use the -I switch when refining a triangulation.\n");
03535     triexit(1);
03536   }
03537   
03538   
03539   if (!b->refine && !b->poly) {
03540     b->vararea = 0;
03541   }
03542   
03543   
03544   if (b->refine || !b->poly) {
03545     b->regionattrib = 0;
03546   }
03547   
03548   
03549   if (b->weighted && (b->poly || b->quality)) {
03550     b->weighted = 0;
03551     if (!b->quiet) {
03552       printf("Warning:  weighted triangulations (-w, -W) are incompatible\n");
03553       printf("  with PSLGs (-p) and meshing (-q, -a, -u).  Weights ignored.\n"
03554              );
03555     }
03556   }
03557   if (b->jettison && b->nonodewritten && !b->quiet) {
03558     printf("Warning:  -j and -N switches are somewhat incompatible.\n");
03559     printf("  If any vertices are jettisoned, you will need the output\n");
03560     printf("  .node file to reconstruct the new node indices.");
03561   }
03562 
03563 #ifndef TRILIBRARY
03564   strcpy(b->inpolyfilename, b->innodefilename);
03565   strcpy(b->inelefilename, b->innodefilename);
03566   strcpy(b->areafilename, b->innodefilename);
03567   increment = 0;
03568   strcpy(workstring, b->innodefilename);
03569   j = 1;
03570   while (workstring[j] != '\0') {
03571     if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03572       increment = j + 1;
03573     }
03574     j++;
03575   }
03576   meshnumber = 0;
03577   if (increment > 0) {
03578     j = increment;
03579     do {
03580       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03581         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03582       } else {
03583         increment = 0;
03584       }
03585       j++;
03586     } while (workstring[j] != '\0');
03587   }
03588   if (b->noiterationnum) {
03589     strcpy(b->outnodefilename, b->innodefilename);
03590     strcpy(b->outelefilename, b->innodefilename);
03591     strcpy(b->edgefilename, b->innodefilename);
03592     strcpy(b->vnodefilename, b->innodefilename);
03593     strcpy(b->vedgefilename, b->innodefilename);
03594     strcpy(b->neighborfilename, b->innodefilename);
03595     strcpy(b->offfilename, b->innodefilename);
03596     strcat(b->outnodefilename, ".node");
03597     strcat(b->outelefilename, ".ele");
03598     strcat(b->edgefilename, ".edge");
03599     strcat(b->vnodefilename, ".v.node");
03600     strcat(b->vedgefilename, ".v.edge");
03601     strcat(b->neighborfilename, ".neigh");
03602     strcat(b->offfilename, ".off");
03603   } else if (increment == 0) {
03604     strcpy(b->outnodefilename, b->innodefilename);
03605     strcpy(b->outpolyfilename, b->innodefilename);
03606     strcpy(b->outelefilename, b->innodefilename);
03607     strcpy(b->edgefilename, b->innodefilename);
03608     strcpy(b->vnodefilename, b->innodefilename);
03609     strcpy(b->vedgefilename, b->innodefilename);
03610     strcpy(b->neighborfilename, b->innodefilename);
03611     strcpy(b->offfilename, b->innodefilename);
03612     strcat(b->outnodefilename, ".1.node");
03613     strcat(b->outpolyfilename, ".1.poly");
03614     strcat(b->outelefilename, ".1.ele");
03615     strcat(b->edgefilename, ".1.edge");
03616     strcat(b->vnodefilename, ".1.v.node");
03617     strcat(b->vedgefilename, ".1.v.edge");
03618     strcat(b->neighborfilename, ".1.neigh");
03619     strcat(b->offfilename, ".1.off");
03620   } else {
03621     workstring[increment] = '%';
03622     workstring[increment + 1] = 'd';
03623     workstring[increment + 2] = '\0';
03624     sprintf(b->outnodefilename, workstring, meshnumber + 1);
03625     strcpy(b->outpolyfilename, b->outnodefilename);
03626     strcpy(b->outelefilename, b->outnodefilename);
03627     strcpy(b->edgefilename, b->outnodefilename);
03628     strcpy(b->vnodefilename, b->outnodefilename);
03629     strcpy(b->vedgefilename, b->outnodefilename);
03630     strcpy(b->neighborfilename, b->outnodefilename);
03631     strcpy(b->offfilename, b->outnodefilename);
03632     strcat(b->outnodefilename, ".node");
03633     strcat(b->outpolyfilename, ".poly");
03634     strcat(b->outelefilename, ".ele");
03635     strcat(b->edgefilename, ".edge");
03636     strcat(b->vnodefilename, ".v.node");
03637     strcat(b->vedgefilename, ".v.edge");
03638     strcat(b->neighborfilename, ".neigh");
03639     strcat(b->offfilename, ".off");
03640   }
03641   strcat(b->innodefilename, ".node");
03642   strcat(b->inpolyfilename, ".poly");
03643   strcat(b->inelefilename, ".ele");
03644   strcat(b->areafilename, ".area");
03645 #endif 
03646 }
03647 
03650 
03651 
03652 
03656 
03657 
03658 
03659 
03660 
03661 
03662 
03663 
03664 
03665 
03666 
03667 #ifdef ANSI_DECLARATORS
03668 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
03669 #else 
03670 void printtriangle(m, b, t)
03671 struct mesh *m;
03672 struct behavior *b;
03673 struct otri *t;
03674 #endif 
03675 
03676 {
03677   struct otri printtri;
03678   struct osub printsh;
03679   vertex printvertex;
03680 
03681   printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
03682          t->orient);
03683   decode(t->tri[0], printtri);
03684   if (printtri.tri == m->dummytri) {
03685     printf("    [0] = Outer space\n");
03686   } else {
03687     printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
03688            printtri.orient);
03689   }
03690   decode(t->tri[1], printtri);
03691   if (printtri.tri == m->dummytri) {
03692     printf("    [1] = Outer space\n");
03693   } else {
03694     printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
03695            printtri.orient);
03696   }
03697   decode(t->tri[2], printtri);
03698   if (printtri.tri == m->dummytri) {
03699     printf("    [2] = Outer space\n");
03700   } else {
03701     printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
03702            printtri.orient);
03703   }
03704 
03705   org(*t, printvertex);
03706   if (printvertex == (vertex) NULL)
03707     printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
03708   else
03709     printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
03710            (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
03711            printvertex[0], printvertex[1]);
03712   dest(*t, printvertex);
03713   if (printvertex == (vertex) NULL)
03714     printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
03715   else
03716     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
03717            (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
03718            printvertex[0], printvertex[1]);
03719   apex(*t, printvertex);
03720   if (printvertex == (vertex) NULL)
03721     printf("    Apex  [%d] = NULL\n", t->orient + 3);
03722   else
03723     printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
03724            t->orient + 3, (unsigned long) printvertex,
03725            printvertex[0], printvertex[1]);
03726 
03727   if (b->usesegments) {
03728     sdecode(t->tri[6], printsh);
03729     if (printsh.ss != m->dummysub) {
03730       printf("    [6] = x%lx  %d\n", (unsigned long) printsh.ss,
03731              printsh.ssorient);
03732     }
03733     sdecode(t->tri[7], printsh);
03734     if (printsh.ss != m->dummysub) {
03735       printf("    [7] = x%lx  %d\n", (unsigned long) printsh.ss,
03736              printsh.ssorient);
03737     }
03738     sdecode(t->tri[8], printsh);
03739     if (printsh.ss != m->dummysub) {
03740       printf("    [8] = x%lx  %d\n", (unsigned long) printsh.ss,
03741              printsh.ssorient);
03742     }
03743   }
03744 
03745   if (b->vararea) {
03746     printf("    Area constraint:  %.4g\n", areabound(*t));
03747   }
03748 }
03749 
03750 
03751 
03752 
03753 
03754 
03755 
03756 
03757 
03758 
03759 
03760 
03761 #ifdef ANSI_DECLARATORS
03762 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
03763 #else 
03764 void printsubseg(m, b, s)
03765 struct mesh *m;
03766 struct behavior *b;
03767 struct osub *s;
03768 #endif 
03769 
03770 {
03771   struct osub printsh;
03772   struct otri printtri;
03773   vertex printvertex;
03774 
03775   printf("subsegment x%lx with orientation %d and mark %d:\n",
03776          (unsigned long) s->ss, s->ssorient, mark(*s));
03777   sdecode(s->ss[0], printsh);
03778   if (printsh.ss == m->dummysub) {
03779     printf("    [0] = No subsegment\n");
03780   } else {
03781     printf("    [0] = x%lx  %d\n", (unsigned long) printsh.ss,
03782            printsh.ssorient);
03783   }
03784   sdecode(s->ss[1], printsh);
03785   if (printsh.ss == m->dummysub) {
03786     printf("    [1] = No subsegment\n");
03787   } else {
03788     printf("    [1] = x%lx  %d\n", (unsigned long) printsh.ss,
03789            printsh.ssorient);
03790   }
03791 
03792   sorg(*s, printvertex);
03793   if (printvertex == (vertex) NULL)
03794     printf("    Origin[%d] = NULL\n", 2 + s->ssorient);
03795   else
03796     printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
03797            2 + s->ssorient, (unsigned long) printvertex,
03798            printvertex[0], printvertex[1]);
03799   sdest(*s, printvertex);
03800   if (printvertex == (vertex) NULL)
03801     printf("    Dest  [%d] = NULL\n", 3 - s->ssorient);
03802   else
03803     printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
03804            3 - s->ssorient, (unsigned long) printvertex,
03805            printvertex[0], printvertex[1]);
03806 
03807   decode(s->ss[6], printtri);
03808   if (printtri.tri == m->dummytri) {
03809     printf("    [6] = Outer space\n");
03810   } else {
03811     printf("    [6] = x%lx  %d\n", (unsigned long) printtri.tri,
03812            printtri.orient);
03813   }
03814   decode(s->ss[7], printtri);
03815   if (printtri.tri == m->dummytri) {
03816     printf("    [7] = Outer space\n");
03817   } else {
03818     printf("    [7] = x%lx  %d\n", (unsigned long) printtri.tri,
03819            printtri.orient);
03820   }
03821 
03822   segorg(*s, printvertex);
03823   if (printvertex == (vertex) NULL)
03824     printf("    Segment origin[%d] = NULL\n", 4 + s->ssorient);
03825   else
03826     printf("    Segment origin[%d] = x%lx  (%.12g, %.12g)\n",
03827            4 + s->ssorient, (unsigned long) printvertex,
03828            printvertex[0], printvertex[1]);
03829   segdest(*s, printvertex);
03830   if (printvertex == (vertex) NULL)
03831     printf("    Segment dest  [%d] = NULL\n", 5 - s->ssorient);
03832   else
03833     printf("    Segment dest  [%d] = x%lx  (%.12g, %.12g)\n",
03834            5 - s->ssorient, (unsigned long) printvertex,
03835            printvertex[0], printvertex[1]);
03836 }
03837 
03840 
03841 
03842 
03846 
03847 
03848 
03849 
03850 
03851 
03852 
03853 
03854 
03855 #ifdef ANSI_DECLARATORS
03856 void poolzero(struct memorypool *pool)
03857 #else 
03858 void poolzero(pool)
03859 struct memorypool *pool;
03860 #endif 
03861 
03862 {
03863   pool->firstblock = (VOID **) NULL;
03864   pool->nowblock = (VOID **) NULL;
03865   pool->nextitem = (VOID *) NULL;
03866   pool->deaditemstack = (VOID *) NULL;
03867   pool->pathblock = (VOID **) NULL;
03868   pool->pathitem = (VOID *) NULL;
03869   pool->alignbytes = 0;
03870   pool->itembytes = 0;
03871   pool->itemsperblock = 0;
03872   pool->itemsfirstblock = 0;
03873   pool->items = 0;
03874   pool->maxitems = 0;
03875   pool->unallocateditems = 0;
03876   pool->pathitemsleft = 0;
03877 }
03878 
03879 
03880 
03881 
03882 
03883 
03884 
03885 
03886 
03887 
03888 
03889 #ifdef ANSI_DECLARATORS
03890 void poolrestart(struct memorypool *pool)
03891 #else 
03892 void poolrestart(pool)
03893 struct memorypool *pool;
03894 #endif 
03895 
03896 {
03897   unsigned long alignptr;
03898 
03899   pool->items = 0;
03900   pool->maxitems = 0;
03901 
03902   
03903   pool->nowblock = pool->firstblock;
03904   
03905   alignptr = (unsigned long) (pool->nowblock + 1);
03906   
03907   pool->nextitem = (VOID *)
03908     (alignptr + (unsigned long) pool->alignbytes -
03909      (alignptr % (unsigned long) pool->alignbytes));
03910   
03911   pool->unallocateditems = pool->itemsfirstblock;
03912   
03913   pool->deaditemstack = (VOID *) NULL;
03914 }
03915 
03916 
03917 
03918 
03919 
03920 
03921 
03922 
03923 
03924 
03925 
03926 
03927 
03928 
03929 
03930 
03931 
03932 
03933 
03934 
03935 #ifdef ANSI_DECLARATORS
03936 void poolinit(struct memorypool *pool, int bytecount, int itemcount,
03937               int firstitemcount, int alignment)
03938 #else 
03939 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
03940 struct memorypool *pool;
03941 int bytecount;
03942 int itemcount;
03943 int firstitemcount;
03944 int alignment;
03945 #endif 
03946 
03947 {
03948   
03949   
03950   
03951   
03952   if (alignment > sizeof(VOID *)) {
03953     pool->alignbytes = alignment;
03954   } else {
03955     pool->alignbytes = sizeof(VOID *);
03956   }
03957   pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
03958                     pool->alignbytes;
03959   pool->itemsperblock = itemcount;
03960   if (firstitemcount == 0) {
03961     pool->itemsfirstblock = itemcount;
03962   } else {
03963     pool->itemsfirstblock = firstitemcount;
03964   }
03965 
03966   
03967   
03968   
03969   pool->firstblock = (VOID **)
03970     trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
03971               pool->alignbytes);
03972   
03973   *(pool->firstblock) = (VOID *) NULL;
03974   poolrestart(pool);
03975 }
03976 
03977 
03978 
03979 
03980 
03981 
03982 
03983 #ifdef ANSI_DECLARATORS
03984 void pooldeinit(struct memorypool *pool)
03985 #else 
03986 void pooldeinit(pool)
03987 struct memorypool *pool;
03988 #endif 
03989 
03990 {
03991   while (pool->firstblock != (VOID **) NULL) {
03992     pool->nowblock = (VOID **) *(pool->firstblock);
03993     trifree((VOID *) pool->firstblock);
03994     pool->firstblock = pool->nowblock;
03995   }
03996 }
03997 
03998 
03999 
04000 
04001 
04002 
04003 
04004 #ifdef ANSI_DECLARATORS
04005 VOID *poolalloc(struct memorypool *pool)
04006 #else 
04007 VOID *poolalloc(pool)
04008 struct memorypool *pool;
04009 #endif 
04010 
04011 {
04012   VOID *newitem;
04013   VOID **newblock;
04014   unsigned long alignptr;
04015 
04016   
04017   
04018   if (pool->deaditemstack != (VOID *) NULL) {
04019     newitem = pool->deaditemstack;               
04020     pool->deaditemstack = * (VOID **) pool->deaditemstack;
04021   } else {
04022     
04023     if (pool->unallocateditems == 0) {
04024       
04025       if (*(pool->nowblock) == (VOID *) NULL) {
04026         
04027         newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
04028                                        (int) sizeof(VOID *) +
04029                                        pool->alignbytes);
04030         *(pool->nowblock) = (VOID *) newblock;
04031         
04032         *newblock = (VOID *) NULL;
04033       }
04034 
04035       
04036       pool->nowblock = (VOID **) *(pool->nowblock);
04037       
04038       
04039       alignptr = (unsigned long) (pool->nowblock + 1);
04040       
04041       pool->nextitem = (VOID *)
04042         (alignptr + (unsigned long) pool->alignbytes -
04043          (alignptr % (unsigned long) pool->alignbytes));
04044       
04045       pool->unallocateditems = pool->itemsperblock;
04046     }
04047 
04048     
04049     newitem = pool->nextitem;
04050     
04051     pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
04052     pool->unallocateditems--;
04053     pool->maxitems++;
04054   }
04055   pool->items++;
04056   return newitem;
04057 }
04058 
04059 
04060 
04061 
04062 
04063 
04064 
04065 
04066 
04067 #ifdef ANSI_DECLARATORS
04068 void pooldealloc(struct memorypool *pool, VOID *dyingitem)
04069 #else 
04070 void pooldealloc(pool, dyingitem)
04071 struct memorypool *pool;
04072 VOID *dyingitem;
04073 #endif 
04074 
04075 {
04076   
04077   *((VOID **) dyingitem) = pool->deaditemstack;
04078   pool->deaditemstack = dyingitem;
04079   pool->items--;
04080 }
04081 
04082 
04083 
04084 
04085 
04086 
04087 
04088 
04089 
04090 #ifdef ANSI_DECLARATORS
04091 void traversalinit(struct memorypool *pool)
04092 #else 
04093 void traversalinit(pool)
04094 struct memorypool *pool;
04095 #endif 
04096 
04097 {
04098   unsigned long alignptr;
04099 
04100   
04101   pool->pathblock = pool->firstblock;
04102   
04103   alignptr = (unsigned long) (pool->pathblock + 1);
04104   
04105   pool->pathitem = (VOID *)
04106     (alignptr + (unsigned long) pool->alignbytes -
04107      (alignptr % (unsigned long) pool->alignbytes));
04108   
04109   pool->pathitemsleft = pool->itemsfirstblock;
04110 }
04111 
04112 
04113 
04114 
04115 
04116 
04117 
04118 
04119 
04120 
04121 
04122 
04123 
04124 
04125 
04126 #ifdef ANSI_DECLARATORS
04127 VOID *traverse(struct memorypool *pool)
04128 #else 
04129 VOID *traverse(pool)
04130 struct memorypool *pool;
04131 #endif 
04132 
04133 {
04134   VOID *newitem;
04135   unsigned long alignptr;
04136 
04137   
04138   if (pool->pathitem == pool->nextitem) {
04139     return (VOID *) NULL;
04140   }
04141 
04142   
04143   if (pool->pathitemsleft == 0) {
04144     
04145     pool->pathblock = (VOID **) *(pool->pathblock);
04146     
04147     alignptr = (unsigned long) (pool->pathblock + 1);
04148     
04149     pool->pathitem = (VOID *)
04150       (alignptr + (unsigned long) pool->alignbytes -
04151        (alignptr % (unsigned long) pool->alignbytes));
04152     
04153     pool->pathitemsleft = pool->itemsperblock;
04154   }
04155 
04156   newitem = pool->pathitem;
04157   
04158   pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
04159   pool->pathitemsleft--;
04160   return newitem;
04161 }
04162 
04163 
04164 
04165 
04166 
04167 
04168 
04169 
04170 
04171 
04172 
04173 
04174 
04175 
04176 
04177 
04178 
04179 
04180 
04181 
04182 
04183 
04184 
04185 
04186 
04187 
04188 
04189 
04190 
04191 #ifdef ANSI_DECLARATORS
04192 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
04193                int subsegbytes)
04194 #else 
04195 void dummyinit(m, b, trianglebytes, subsegbytes)
04196 struct mesh *m;
04197 struct behavior *b;
04198 int trianglebytes;
04199 int subsegbytes;
04200 #endif 
04201 
04202 {
04203   unsigned long alignptr;
04204 
04205   
04206   m->dummytribase = (triangle *) trimalloc(trianglebytes +
04207                                            m->triangles.alignbytes);
04208   
04209   alignptr = (unsigned long) m->dummytribase;
04210   m->dummytri = (triangle *)
04211     (alignptr + (unsigned long) m->triangles.alignbytes -
04212      (alignptr % (unsigned long) m->triangles.alignbytes));
04213   
04214   
04215   
04216   
04217   m->dummytri[0] = (triangle) m->dummytri;
04218   m->dummytri[1] = (triangle) m->dummytri;
04219   m->dummytri[2] = (triangle) m->dummytri;
04220   
04221   m->dummytri[3] = (triangle) NULL;
04222   m->dummytri[4] = (triangle) NULL;
04223   m->dummytri[5] = (triangle) NULL;
04224 
04225   if (b->usesegments) {
04226     
04227     
04228     
04229     m->dummysubbase = (subseg *) trimalloc(subsegbytes +
04230                                            m->subsegs.alignbytes);
04231     
04232     alignptr = (unsigned long) m->dummysubbase;
04233     m->dummysub = (subseg *)
04234       (alignptr + (unsigned long) m->subsegs.alignbytes -
04235        (alignptr % (unsigned long) m->subsegs.alignbytes));
04236     
04237     
04238     
04239     
04240     m->dummysub[0] = (subseg) m->dummysub;
04241     m->dummysub[1] = (subseg) m->dummysub;
04242     
04243     m->dummysub[2] = (subseg) NULL;
04244     m->dummysub[3] = (subseg) NULL;
04245     m->dummysub[4] = (subseg) NULL;
04246     m->dummysub[5] = (subseg) NULL;
04247     
04248     m->dummysub[6] = (subseg) m->dummytri;
04249     m->dummysub[7] = (subseg) m->dummytri;
04250     
04251     * (int *) (m->dummysub + 8) = 0;
04252 
04253     
04254     
04255     m->dummytri[6] = (triangle) m->dummysub;
04256     m->dummytri[7] = (triangle) m->dummysub;
04257     m->dummytri[8] = (triangle) m->dummysub;
04258   }
04259 }
04260 
04261 
04262 
04263 
04264 
04265 
04266 
04267 
04268 
04269 
04270 
04271 #ifdef ANSI_DECLARATORS
04272 void initializevertexpool(struct mesh *m, struct behavior *b)
04273 #else 
04274 void initializevertexpool(m, b)
04275 struct mesh *m;
04276 struct behavior *b;
04277 #endif 
04278 
04279 {
04280   int vertexsize;
04281 
04282   
04283   
04284   
04285   m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
04286                         sizeof(int) - 1) /
04287                        sizeof(int);
04288   vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
04289   if (b->poly) {
04290     
04291     
04292     m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
04293                          sizeof(triangle);
04294     vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
04295   }
04296 
04297   
04298   poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
04299            m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
04300            sizeof(REAL));
04301 }
04302 
04303 
04304 
04305 
04306 
04307 
04308 
04309 
04310 
04311 
04312 
04313 
04314 #ifdef ANSI_DECLARATORS
04315 void initializetrisubpools(struct mesh *m, struct behavior *b)
04316 #else 
04317 void initializetrisubpools(m, b)
04318 struct mesh *m;
04319 struct behavior *b;
04320 #endif 
04321 
04322 {
04323   int trisize;
04324 
04325   
04326   
04327   
04328   
04329   m->highorderindex = 6 + (b->usesegments * 3);
04330   
04331   trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
04332             sizeof(triangle);
04333   
04334   
04335   m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
04336   
04337   
04338   
04339   m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
04340   
04341   
04342   if (b->vararea) {
04343     trisize = (m->areaboundindex + 1) * sizeof(REAL);
04344   } else if (m->eextras + b->regionattrib > 0) {
04345     trisize = m->areaboundindex * sizeof(REAL);
04346   }
04347   
04348   
04349   
04350   
04351   if ((b->voronoi || b->neighbors) &&
04352       (trisize < 6 * sizeof(triangle) + sizeof(int))) {
04353     trisize = 6 * sizeof(triangle) + sizeof(int);
04354   }
04355 
04356   
04357   poolinit(&m->triangles, trisize, TRIPERBLOCK,
04358            (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
04359            TRIPERBLOCK, 4);
04360 
04361   if (b->usesegments) {
04362     
04363     
04364     poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
04365              SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
04366 
04367     
04368     dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
04369   } else {
04370     
04371     dummyinit(m, b, m->triangles.itembytes, 0);
04372   }
04373 }
04374 
04375 
04376 
04377 
04378 
04379 
04380 
04381 #ifdef ANSI_DECLARATORS
04382 void triangledealloc(struct mesh *m, triangle *dyingtriangle)
04383 #else 
04384 void triangledealloc(m, dyingtriangle)
04385 struct mesh *m;
04386 triangle *dyingtriangle;
04387 #endif 
04388 
04389 {
04390   
04391   
04392   killtri(dyingtriangle);
04393   pooldealloc(&m->triangles, (VOID *) dyingtriangle);
04394 }
04395 
04396 
04397 
04398 
04399 
04400 
04401 
04402 #ifdef ANSI_DECLARATORS
04403 triangle *triangletraverse(struct mesh *m)
04404 #else 
04405 triangle *triangletraverse(m)
04406 struct mesh *m;
04407 #endif 
04408 
04409 {
04410   triangle *newtriangle;
04411 
04412   do {
04413     newtriangle = (triangle *) traverse(&m->triangles);
04414     if (newtriangle == (triangle *) NULL) {
04415       return (triangle *) NULL;
04416     }
04417   } while (deadtri(newtriangle));                         
04418   return newtriangle;
04419 }
04420 
04421 
04422 
04423 
04424 
04425 
04426 
04427 #ifdef ANSI_DECLARATORS
04428 void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
04429 #else 
04430 void subsegdealloc(m, dyingsubseg)
04431 struct mesh *m;
04432 subseg *dyingsubseg;
04433 #endif 
04434 
04435 {
04436   
04437   
04438   killsubseg(dyingsubseg);
04439   pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
04440 }
04441 
04442 
04443 
04444 
04445 
04446 
04447 
04448 #ifdef ANSI_DECLARATORS
04449 subseg *subsegtraverse(struct mesh *m)
04450 #else 
04451 subseg *subsegtraverse(m)
04452 struct mesh *m;
04453 #endif 
04454 
04455 {
04456   subseg *newsubseg;
04457 
04458   do {
04459     newsubseg = (subseg *) traverse(&m->subsegs);
04460     if (newsubseg == (subseg *) NULL) {
04461       return (subseg *) NULL;
04462     }
04463   } while (deadsubseg(newsubseg));                        
04464   return newsubseg;
04465 }
04466 
04467 
04468 
04469 
04470 
04471 
04472 
04473 #ifdef ANSI_DECLARATORS
04474 void vertexdealloc(struct mesh *m, vertex dyingvertex)
04475 #else 
04476 void vertexdealloc(m, dyingvertex)
04477 struct mesh *m;
04478 vertex dyingvertex;
04479 #endif 
04480 
04481 {
04482   
04483   
04484   setvertextype(dyingvertex, DEADVERTEX);
04485   pooldealloc(&m->vertices, (VOID *) dyingvertex);
04486 }
04487 
04488 
04489 
04490 
04491 
04492 
04493 
04494 #ifdef ANSI_DECLARATORS
04495 vertex vertextraverse(struct mesh *m)
04496 #else 
04497 vertex vertextraverse(m)
04498 struct mesh *m;
04499 #endif 
04500 
04501 {
04502   vertex newvertex;
04503 
04504   do {
04505     newvertex = (vertex) traverse(&m->vertices);
04506     if (newvertex == (vertex) NULL) {
04507       return (vertex) NULL;
04508     }
04509   } while (vertextype(newvertex) == DEADVERTEX);          
04510   return newvertex;
04511 }
04512 
04513 
04514 
04515 
04516 
04517 
04518 
04519 
04520 #ifndef CDT_ONLY
04521 
04522 #ifdef ANSI_DECLARATORS
04523 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
04524 #else 
04525 void badsubsegdealloc(m, dyingseg)
04526 struct mesh *m;
04527 struct badsubseg *dyingseg;
04528 #endif 
04529 
04530 {
04531   
04532   
04533   dyingseg->subsegorg = (vertex) NULL;
04534   pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
04535 }
04536 
04537 #endif 
04538 
04539 
04540 
04541 
04542 
04543 
04544 
04545 #ifndef CDT_ONLY
04546 
04547 #ifdef ANSI_DECLARATORS
04548 struct badsubseg *badsubsegtraverse(struct mesh *m)
04549 #else 
04550 struct badsubseg *badsubsegtraverse(m)
04551 struct mesh *m;
04552 #endif 
04553 
04554 {
04555   struct badsubseg *newseg;
04556 
04557   do {
04558     newseg = (struct badsubseg *) traverse(&m->badsubsegs);
04559     if (newseg == (struct badsubseg *) NULL) {
04560       return (struct badsubseg *) NULL;
04561     }
04562   } while (newseg->subsegorg == (vertex) NULL);           
04563   return newseg;
04564 }
04565 
04566 #endif 
04567 
04568 
04569 
04570 
04571 
04572 
04573 
04574 
04575 
04576 
04577 
04578 
04579 
04580 #ifdef ANSI_DECLARATORS
04581 vertex getvertex(struct mesh *m, struct behavior *b, int number)
04582 #else 
04583 vertex getvertex(m, b, number)
04584 struct mesh *m;
04585 struct behavior *b;
04586 int number;
04587 #endif 
04588 
04589 {
04590   VOID **getblock;
04591   char *foundvertex;
04592   unsigned long alignptr;
04593   int current;
04594 
04595   getblock = m->vertices.firstblock;
04596   current = b->firstnumber;
04597 
04598   
04599   if (current + m->vertices.itemsfirstblock <= number) {
04600     getblock = (VOID **) *getblock;
04601     current += m->vertices.itemsfirstblock;
04602     while (current + m->vertices.itemsperblock <= number) {
04603       getblock = (VOID **) *getblock;
04604       current += m->vertices.itemsperblock;
04605     }
04606   }
04607 
04608   
04609   alignptr = (unsigned long) (getblock + 1);
04610   foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
04611                           (alignptr % (unsigned long) m->vertices.alignbytes));
04612   return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
04613 }
04614 
04615 
04616 
04617 
04618 
04619 
04620 
04621 #ifdef ANSI_DECLARATORS
04622 void triangledeinit(struct mesh *m, struct behavior *b)
04623 #else 
04624 void triangledeinit(m, b)
04625 struct mesh *m;
04626 struct behavior *b;
04627 #endif 
04628 
04629 {
04630   pooldeinit(&m->triangles);
04631   trifree((VOID *) m->dummytribase);
04632   if (b->usesegments) {
04633     pooldeinit(&m->subsegs);
04634     trifree((VOID *) m->dummysubbase);
04635   }
04636   pooldeinit(&m->vertices);
04637 #ifndef CDT_ONLY
04638   if (b->quality) {
04639     pooldeinit(&m->badsubsegs);
04640     if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
04641       pooldeinit(&m->badtriangles);
04642       pooldeinit(&m->flipstackers);
04643     }
04644   }
04645 #endif 
04646 }
04647 
04650 
04651 
04652 
04656 
04657 
04658 
04659 
04660 
04661 
04662 #ifdef ANSI_DECLARATORS
04663 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
04664 #else 
04665 void maketriangle(m, b, newotri)
04666 struct mesh *m;
04667 struct behavior *b;
04668 struct otri *newotri;
04669 #endif 
04670 
04671 {
04672   int i;
04673 
04674   newotri->tri = (triangle *) poolalloc(&m->triangles);
04675   
04676   newotri->tri[0] = (triangle) m->dummytri;
04677   newotri->tri[1] = (triangle) m->dummytri;
04678   newotri->tri[2] = (triangle) m->dummytri;
04679   
04680   newotri->tri[3] = (triangle) NULL;
04681   newotri->tri[4] = (triangle) NULL;
04682   newotri->tri[5] = (triangle) NULL;
04683   if (b->usesegments) {
04684     
04685     
04686     newotri->tri[6] = (triangle) m->dummysub;
04687     newotri->tri[7] = (triangle) m->dummysub;
04688     newotri->tri[8] = (triangle) m->dummysub;
04689   }
04690   for (i = 0; i < m->eextras; i++) {
04691     setelemattribute(*newotri, i, 0.0);
04692   }
04693   if (b->vararea) {
04694     setareabound(*newotri, -1.0);
04695   }
04696 
04697   newotri->orient = 0;
04698 }
04699 
04700 
04701 
04702 
04703 
04704 
04705 
04706 #ifdef ANSI_DECLARATORS
04707 void makesubseg(struct mesh *m, struct osub *newsubseg)
04708 #else 
04709 void makesubseg(m, newsubseg)
04710 struct mesh *m;
04711 struct osub *newsubseg;
04712 #endif 
04713 
04714 {
04715   newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
04716   
04717   
04718   newsubseg->ss[0] = (subseg) m->dummysub;
04719   newsubseg->ss[1] = (subseg) m->dummysub;
04720   
04721   newsubseg->ss[2] = (subseg) NULL;
04722   newsubseg->ss[3] = (subseg) NULL;
04723   newsubseg->ss[4] = (subseg) NULL;
04724   newsubseg->ss[5] = (subseg) NULL;
04725   
04726   newsubseg->ss[6] = (subseg) m->dummytri;
04727   newsubseg->ss[7] = (subseg) m->dummytri;
04728   
04729   setmark(*newsubseg, 0);
04730 
04731   newsubseg->ssorient = 0;
04732 }
04733 
04736 
04737 
04738 
04742 
04743 
04744 
04745 
04746 
04747 
04748 
04749 
04750 
04751 
04752 
04753 
04754 
04755 #define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
04756 
04757 
04758 
04759 
04760 
04761 
04762 
04763 
04764 
04765 
04766 
04767 
04768 
04769 
04770 
04771 #define Fast_Two_Sum_Tail(a, b, x, y) \
04772   bvirt = x - a; \
04773   y = b - bvirt
04774 
04775 #define Fast_Two_Sum(a, b, x, y) \
04776   x = (REAL) (a + b); \
04777   Fast_Two_Sum_Tail(a, b, x, y)
04778 
04779 #define Two_Sum_Tail(a, b, x, y) \
04780   bvirt = (REAL) (x - a); \
04781   avirt = x - bvirt; \
04782   bround = b - bvirt; \
04783   around = a - avirt; \
04784   y = around + bround
04785 
04786 #define Two_Sum(a, b, x, y) \
04787   x = (REAL) (a + b); \
04788   Two_Sum_Tail(a, b, x, y)
04789 
04790 #define Two_Diff_Tail(a, b, x, y) \
04791   bvirt = (REAL) (a - x); \
04792   avirt = x + bvirt; \
04793   bround = bvirt - b; \
04794   around = a - avirt; \
04795   y = around + bround
04796 
04797 #define Two_Diff(a, b, x, y) \
04798   x = (REAL) (a - b); \
04799   Two_Diff_Tail(a, b, x, y)
04800 
04801 #define Split(a, ahi, alo) \
04802   c = (REAL) (splitter * a); \
04803   abig = (REAL) (c - a); \
04804   ahi = c - abig; \
04805   alo = a - ahi
04806 
04807 #define Two_Product_Tail(a, b, x, y) \
04808   Split(a, ahi, alo); \
04809   Split(b, bhi, blo); \
04810   err1 = x - (ahi * bhi); \
04811   err2 = err1 - (alo * bhi); \
04812   err3 = err2 - (ahi * blo); \
04813   y = (alo * blo) - err3
04814 
04815 #define Two_Product(a, b, x, y) \
04816   x = (REAL) (a * b); \
04817   Two_Product_Tail(a, b, x, y)
04818 
04819 
04820 
04821 
04822 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
04823   x = (REAL) (a * b); \
04824   Split(a, ahi, alo); \
04825   err1 = x - (ahi * bhi); \
04826   err2 = err1 - (alo * bhi); \
04827   err3 = err2 - (ahi * blo); \
04828   y = (alo * blo) - err3
04829 
04830 
04831 
04832 #define Square_Tail(a, x, y) \
04833   Split(a, ahi, alo); \
04834   err1 = x - (ahi * ahi); \
04835   err3 = err1 - ((ahi + ahi) * alo); \
04836   y = (alo * alo) - err3
04837 
04838 #define Square(a, x, y) \
04839   x = (REAL) (a * a); \
04840   Square_Tail(a, x, y)
04841 
04842 
04843 
04844 
04845 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
04846   Two_Sum(a0, b , _i, x0); \
04847   Two_Sum(a1, _i, x2, x1)
04848 
04849 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
04850   Two_Diff(a0, b , _i, x0); \
04851   Two_Sum( a1, _i, x2, x1)
04852 
04853 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
04854   Two_One_Sum(a1, a0, b0, _j, _0, x0); \
04855   Two_One_Sum(_j, _0, b1, x3, x2, x1)
04856 
04857 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
04858   Two_One_Diff(a1, a0, b0, _j, _0, x0); \
04859   Two_One_Diff(_j, _0, b1, x3, x2, x1)
04860 
04861 
04862 
04863 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
04864   Split(b, bhi, blo); \
04865   Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
04866   Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
04867   Two_Sum(_i, _0, _k, x1); \
04868   Fast_Two_Sum(_j, _k, x3, x2)
04869 
04870 
04871 
04872 
04873 
04874 
04875 
04876 
04877 
04878 
04879 
04880 
04881 
04882 
04883 
04884 
04885 
04886 
04887 
04888 
04889 void exactinit()
04890 {
04891   REAL half;
04892   REAL check, lastcheck;
04893   int every_other;
04894 #ifdef LINUX
04895   int cword;
04896 #endif 
04897 
04898 #ifdef CPU86
04899 #ifdef SINGLE
04900   _control87(_PC_24, _MCW_PC); 
04901 #else 
04902   _control87(_PC_53, _MCW_PC); 
04903 #endif 
04904 #endif 
04905 #ifdef LINUX
04906 #ifdef SINGLE
04907   
04908   cword = 4210;                 
04909 #else 
04910   
04911   cword = 4722;                 
04912 #endif 
04913   _FPU_SETCW(cword);
04914 #endif 
04915 
04916   every_other = 1;
04917   half = 0.5;
04918   epsilon = 1.0;
04919   splitter = 1.0;
04920   check = 1.0;
04921   
04922   
04923   
04924   
04925   do {
04926     lastcheck = check;
04927     epsilon *= half;
04928     if (every_other) {
04929       splitter *= 2.0;
04930     }
04931     every_other = !every_other;
04932     check = 1.0 + epsilon;
04933   } while ((check != 1.0) && (check != lastcheck));
04934   splitter += 1.0;
04935   
04936   resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
04937   ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
04938   ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
04939   ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
04940   iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
04941   iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
04942   iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
04943   o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
04944   o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
04945   o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
04946 }
04947 
04948 
04949 
04950 
04951 
04952 
04953 
04954 
04955 
04956 
04957 
04958 
04959 
04960 
04961 
04962 #ifdef ANSI_DECLARATORS
04963 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
04964 #else 
04965 int fast_expansion_sum_zeroelim(elen, e, flen, f, h)  
04966 int elen;
04967 REAL *e;
04968 int flen;
04969 REAL *f;
04970 REAL *h;
04971 #endif 
04972 
04973 {
04974   REAL Q;
04975   INEXACT REAL Qnew;
04976   INEXACT REAL hh;
04977   INEXACT REAL bvirt;
04978   REAL avirt, bround, around;
04979   int eindex, findex, hindex;
04980   REAL enow, fnow;
04981 
04982   enow = e[0];
04983   fnow = f[0];
04984   eindex = findex = 0;
04985   if ((fnow > enow) == (fnow > -enow)) {
04986     Q = enow;
04987     enow = e[++eindex];
04988   } else {
04989     Q = fnow;
04990     fnow = f[++findex];
04991   }
04992   hindex = 0;
04993   if ((eindex < elen) && (findex < flen)) {
04994     if ((fnow > enow) == (fnow > -enow)) {
04995       Fast_Two_Sum(enow, Q, Qnew, hh);
04996       enow = e[++eindex];
04997     } else {
04998       Fast_Two_Sum(fnow, Q, Qnew, hh);
04999       fnow = f[++findex];
05000     }
05001     Q = Qnew;
05002     if (hh != 0.0) {
05003       h[hindex++] = hh;
05004     }
05005     while ((eindex < elen) && (findex < flen)) {
05006       if ((fnow > enow) == (fnow > -enow)) {
05007         Two_Sum(Q, enow, Qnew, hh);
05008         enow = e[++eindex];
05009       } else {
05010         Two_Sum(Q, fnow, Qnew, hh);
05011         fnow = f[++findex];
05012       }
05013       Q = Qnew;
05014       if (hh != 0.0) {
05015         h[hindex++] = hh;
05016       }
05017     }
05018   }
05019   while (eindex < elen) {
05020     Two_Sum(Q, enow, Qnew, hh);
05021     enow = e[++eindex];
05022     Q = Qnew;
05023     if (hh != 0.0) {
05024       h[hindex++] = hh;
05025     }
05026   }
05027   while (findex < flen) {
05028     Two_Sum(Q, fnow, Qnew, hh);
05029     fnow = f[++findex];
05030     Q = Qnew;
05031     if (hh != 0.0) {
05032       h[hindex++] = hh;
05033     }
05034   }
05035   if ((Q != 0.0) || (hindex == 0)) {
05036     h[hindex++] = Q;
05037   }
05038   return hindex;
05039 }
05040 
05041 
05042 
05043 
05044 
05045 
05046 
05047 
05048 
05049 
05050 
05051 
05052 
05053 
05054 
05055 
05056 #ifdef ANSI_DECLARATORS
05057 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
05058 #else 
05059 int scale_expansion_zeroelim(elen, e, b, h)   
05060 int elen;
05061 REAL *e;
05062 REAL b;
05063 REAL *h;
05064 #endif 
05065 
05066 {
05067   INEXACT REAL Q, sum;
05068   REAL hh;
05069   INEXACT REAL product1;
05070   REAL product0;
05071   int eindex, hindex;
05072   REAL enow;
05073   INEXACT REAL bvirt;
05074   REAL avirt, bround, around;
05075   INEXACT REAL c;
05076   INEXACT REAL abig;
05077   REAL ahi, alo, bhi, blo;
05078   REAL err1, err2, err3;
05079 
05080   Split(b, bhi, blo);
05081   Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
05082   hindex = 0;
05083   if (hh != 0) {
05084     h[hindex++] = hh;
05085   }
05086   for (eindex = 1; eindex < elen; eindex++) {
05087     enow = e[eindex];
05088     Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
05089     Two_Sum(Q, product0, sum, hh);
05090     if (hh != 0) {
05091       h[hindex++] = hh;
05092     }
05093     Fast_Two_Sum(product1, sum, Q, hh);
05094     if (hh != 0) {
05095       h[hindex++] = hh;
05096     }
05097   }
05098   if ((Q != 0.0) || (hindex == 0)) {
05099     h[hindex++] = Q;
05100   }
05101   return hindex;
05102 }
05103 
05104 
05105 
05106 
05107 
05108 
05109 
05110 
05111 
05112 #ifdef ANSI_DECLARATORS
05113 REAL estimate(int elen, REAL *e)
05114 #else 
05115 REAL estimate(elen, e)
05116 int elen;
05117 REAL *e;
05118 #endif 
05119 
05120 {
05121   REAL Q;
05122   int eindex;
05123 
05124   Q = e[0];
05125   for (eindex = 1; eindex < elen; eindex++) {
05126     Q += e[eindex];
05127   }
05128   return Q;
05129 }
05130 
05131 
05132 
05133 
05134 
05135 
05136 
05137 
05138 
05139 
05140 
05141 
05142 
05143 
05144 
05145 
05146 
05147 
05148 
05149 
05150 
05151 #ifdef ANSI_DECLARATORS
05152 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
05153 #else 
05154 REAL counterclockwiseadapt(pa, pb, pc, detsum)
05155 vertex pa;
05156 vertex pb;
05157 vertex pc;
05158 REAL detsum;
05159 #endif 
05160 
05161 {
05162   INEXACT REAL acx, acy, bcx, bcy;
05163   REAL acxtail, acytail, bcxtail, bcytail;
05164   INEXACT REAL detleft, detright;
05165   REAL detlefttail, detrighttail;
05166   REAL det, errbound;
05167   REAL B[4], C1[8], C2[12], D[16];
05168   INEXACT REAL B3;
05169   int C1length, C2length, Dlength;
05170   REAL u[4];
05171   INEXACT REAL u3;
05172   INEXACT REAL s1, t1;
05173   REAL s0, t0;
05174 
05175   INEXACT REAL bvirt;
05176   REAL avirt, bround, around;
05177   INEXACT REAL c;
05178   INEXACT REAL abig;
05179   REAL ahi, alo, bhi, blo;
05180   REAL err1, err2, err3;
05181   INEXACT REAL _i, _j;
05182   REAL _0;
05183 
05184   acx = (REAL) (pa[0] - pc[0]);
05185   bcx = (REAL) (pb[0] - pc[0]);
05186   acy = (REAL) (pa[1] - pc[1]);
05187   bcy = (REAL) (pb[1] - pc[1]);
05188 
05189   Two_Product(acx, bcy, detleft, detlefttail);
05190   Two_Product(acy, bcx, detright, detrighttail);
05191 
05192   Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
05193                B3, B[2], B[1], B[0]);
05194   B[3] = B3;
05195 
05196   det = estimate(4, B);
05197   errbound = ccwerrboundB * detsum;
05198   if ((det >= errbound) || (-det >= errbound)) {
05199     return det;
05200   }
05201 
05202   Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
05203   Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
05204   Two_Diff_Tail(pa[1], pc[1], acy, acytail);
05205   Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
05206 
05207   if ((acxtail == 0.0) && (acytail == 0.0)
05208       && (bcxtail == 0.0) && (bcytail == 0.0)) {
05209     return det;
05210   }
05211 
05212   errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
05213   det += (acx * bcytail + bcy * acxtail)
05214        - (acy * bcxtail + bcx * acytail);
05215   if ((det >= errbound) || (-det >= errbound)) {
05216     return det;
05217   }
05218 
05219   Two_Product(acxtail, bcy, s1, s0);
05220   Two_Product(acytail, bcx, t1, t0);
05221   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05222   u[3] = u3;
05223   C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
05224 
05225   Two_Product(acx, bcytail, s1, s0);
05226   Two_Product(acy, bcxtail, t1, t0);
05227   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05228   u[3] = u3;
05229   C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
05230 
05231   Two_Product(acxtail, bcytail, s1, s0);
05232   Two_Product(acytail, bcxtail, t1, t0);
05233   Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05234   u[3] = u3;
05235   Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
05236 
05237   return(D[Dlength - 1]);
05238 }
05239 
05240 #ifdef ANSI_DECLARATORS
05241 REAL counterclockwise(struct mesh *m, struct behavior *b,
05242                       vertex pa, vertex pb, vertex pc)
05243 #else 
05244 REAL counterclockwise(m, b, pa, pb, pc)
05245 struct mesh *m;
05246 struct behavior *b;
05247 vertex pa;
05248 vertex pb;
05249 vertex pc;
05250 #endif 
05251 
05252 {
05253   REAL detleft, detright, det;
05254   REAL detsum, errbound;
05255 
05256   m->counterclockcount++;
05257 
05258   detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
05259   detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
05260   det = detleft - detright;
05261 
05262   if (b->noexact) {
05263     return det;
05264   }
05265 
05266   if (detleft > 0.0) {
05267     if (detright <= 0.0) {
05268       return det;
05269     } else {
05270       detsum = detleft + detright;
05271     }
05272   } else if (detleft < 0.0) {
05273     if (detright >= 0.0) {
05274       return det;
05275     } else {
05276       detsum = -detleft - detright;
05277     }
05278   } else {
05279     return det;
05280   }
05281 
05282   errbound = ccwerrboundA * detsum;
05283   if ((det >= errbound) || (-det >= errbound)) {
05284     return det;
05285   }
05286 
05287   return counterclockwiseadapt(pa, pb, pc, detsum);
05288 }
05289 
05290 
05291 
05292 
05293 
05294 
05295 
05296 
05297 
05298 
05299 
05300 
05301 
05302 
05303 
05304 
05305 
05306 
05307 
05308 
05309 #ifdef ANSI_DECLARATORS
05310 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
05311 #else 
05312 REAL incircleadapt(pa, pb, pc, pd, permanent)
05313 vertex pa;
05314 vertex pb;
05315 vertex pc;
05316 vertex pd;
05317 REAL permanent;
05318 #endif 
05319 
05320 {
05321   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
05322   REAL det, errbound;
05323 
05324   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05325   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05326   REAL bc[4], ca[4], ab[4];
05327   INEXACT REAL bc3, ca3, ab3;
05328   REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
05329   int axbclen, axxbclen, aybclen, ayybclen, alen;
05330   REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
05331   int bxcalen, bxxcalen, bycalen, byycalen, blen;
05332   REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
05333   int cxablen, cxxablen, cyablen, cyyablen, clen;
05334   REAL abdet[64];
05335   int ablen;
05336   REAL fin1[1152], fin2[1152];
05337   REAL *finnow, *finother, *finswap;
05338   int finlength;
05339 
05340   REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
05341   INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
05342   REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
05343   REAL aa[4], bb[4], cc[4];
05344   INEXACT REAL aa3, bb3, cc3;
05345   INEXACT REAL ti1, tj1;
05346   REAL ti0, tj0;
05347   REAL u[4], v[4];
05348   INEXACT REAL u3, v3;
05349   REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
05350   REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
05351   int temp8len, temp16alen, temp16blen, temp16clen;
05352   int temp32alen, temp32blen, temp48len, temp64len;
05353   REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
05354   int axtbblen, axtcclen, aytbblen, aytcclen;
05355   REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
05356   int bxtaalen, bxtcclen, bytaalen, bytcclen;
05357   REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
05358   int cxtaalen, cxtbblen, cytaalen, cytbblen;
05359   REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
05360   int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
05361   REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
05362   int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
05363   REAL axtbctt[8], aytbctt[8], bxtcatt[8];
05364   REAL bytcatt[8], cxtabtt[8], cytabtt[8];
05365   int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
05366   REAL abt[8], bct[8], cat[8];
05367   int abtlen, bctlen, catlen;
05368   REAL abtt[4], bctt[4], catt[4];
05369   int abttlen, bcttlen, cattlen;
05370   INEXACT REAL abtt3, bctt3, catt3;
05371   REAL negate;
05372 
05373   INEXACT REAL bvirt;
05374   REAL avirt, bround, around;
05375   INEXACT REAL c;
05376   INEXACT REAL abig;
05377   REAL ahi, alo, bhi, blo;
05378   REAL err1, err2, err3;
05379   INEXACT REAL _i, _j;
05380   REAL _0;
05381 
05382   adx = (REAL) (pa[0] - pd[0]);
05383   bdx = (REAL) (pb[0] - pd[0]);
05384   cdx = (REAL) (pc[0] - pd[0]);
05385   ady = (REAL) (pa[1] - pd[1]);
05386   bdy = (REAL) (pb[1] - pd[1]);
05387   cdy = (REAL) (pc[1] - pd[1]);
05388 
05389   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
05390   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
05391   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
05392   bc[3] = bc3;
05393   axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
05394   axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
05395   aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
05396   ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
05397   alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
05398 
05399   Two_Product(cdx, ady, cdxady1, cdxady0);
05400   Two_Product(adx, cdy, adxcdy1, adxcdy0);
05401   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
05402   ca[3] = ca3;
05403   bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
05404   bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
05405   bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
05406   byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
05407   blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
05408 
05409   Two_Product(adx, bdy, adxbdy1, adxbdy0);
05410   Two_Product(bdx, ady, bdxady1, bdxady0);
05411   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
05412   ab[3] = ab3;
05413   cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
05414   cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
05415   cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
05416   cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
05417   clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
05418 
05419   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
05420   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
05421 
05422   det = estimate(finlength, fin1);
05423   errbound = iccerrboundB * permanent;
05424   if ((det >= errbound) || (-det >= errbound)) {
05425     return det;
05426   }
05427 
05428   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
05429   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
05430   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
05431   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
05432   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
05433   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
05434   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
05435       && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
05436     return det;
05437   }
05438 
05439   errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
05440   det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
05441                                      - (bdy * cdxtail + cdx * bdytail))
05442           + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
05443        + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
05444                                      - (cdy * adxtail + adx * cdytail))
05445           + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
05446        + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
05447                                      - (ady * bdxtail + bdx * adytail))
05448           + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
05449   if ((det >= errbound) || (-det >= errbound)) {
05450     return det;
05451   }
05452 
05453   finnow = fin1;
05454   finother = fin2;
05455 
05456   if ((bdxtail != 0.0) || (bdytail != 0.0)
05457       || (cdxtail != 0.0) || (cdytail != 0.0)) {
05458     Square(adx, adxadx1, adxadx0);
05459     Square(ady, adyady1, adyady0);
05460     Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
05461     aa[3] = aa3;
05462   }
05463   if ((cdxtail != 0.0) || (cdytail != 0.0)
05464       || (adxtail != 0.0) || (adytail != 0.0)) {
05465     Square(bdx, bdxbdx1, bdxbdx0);
05466     Square(bdy, bdybdy1, bdybdy0);
05467     Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
05468     bb[3] = bb3;
05469   }
05470   if ((adxtail != 0.0) || (adytail != 0.0)
05471       || (bdxtail != 0.0) || (bdytail != 0.0)) {
05472     Square(cdx, cdxcdx1, cdxcdx0);
05473     Square(cdy, cdycdy1, cdycdy0);
05474     Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
05475     cc[3] = cc3;
05476   }
05477 
05478   if (adxtail != 0.0) {
05479     axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
05480     temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
05481                                           temp16a);
05482 
05483     axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
05484     temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
05485 
05486     axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
05487     temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
05488 
05489     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05490                                             temp16blen, temp16b, temp32a);
05491     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05492                                             temp32alen, temp32a, temp48);
05493     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05494                                             temp48, finother);
05495     finswap = finnow; finnow = finother; finother = finswap;
05496   }
05497   if (adytail != 0.0) {
05498     aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
05499     temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
05500                                           temp16a);
05501 
05502     aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
05503     temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
05504 
05505     aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
05506     temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
05507 
05508     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05509                                             temp16blen, temp16b, temp32a);
05510     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05511                                             temp32alen, temp32a, temp48);
05512     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05513                                             temp48, finother);
05514     finswap = finnow; finnow = finother; finother = finswap;
05515   }
05516   if (bdxtail != 0.0) {
05517     bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
05518     temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
05519                                           temp16a);
05520 
05521     bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
05522     temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
05523 
05524     bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
05525     temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
05526 
05527     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05528                                             temp16blen, temp16b, temp32a);
05529     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05530                                             temp32alen, temp32a, temp48);
05531     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05532                                             temp48, finother);
05533     finswap = finnow; finnow = finother; finother = finswap;
05534   }
05535   if (bdytail != 0.0) {
05536     bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
05537     temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
05538                                           temp16a);
05539 
05540     bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
05541     temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
05542 
05543     bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
05544     temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
05545 
05546     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05547                                             temp16blen, temp16b, temp32a);
05548     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05549                                             temp32alen, temp32a, temp48);
05550     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05551                                             temp48, finother);
05552     finswap = finnow; finnow = finother; finother = finswap;
05553   }
05554   if (cdxtail != 0.0) {
05555     cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
05556     temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
05557                                           temp16a);
05558 
05559     cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
05560     temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
05561 
05562     cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
05563     temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
05564 
05565     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05566                                             temp16blen, temp16b, temp32a);
05567     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05568                                             temp32alen, temp32a, temp48);
05569     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05570                                             temp48, finother);
05571     finswap = finnow; finnow = finother; finother = finswap;
05572   }
05573   if (cdytail != 0.0) {
05574     cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
05575     temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
05576                                           temp16a);
05577 
05578     cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
05579     temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
05580 
05581     cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
05582     temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
05583 
05584     temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05585                                             temp16blen, temp16b, temp32a);
05586     temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05587                                             temp32alen, temp32a, temp48);
05588     finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05589                                             temp48, finother);
05590     finswap = finnow; finnow = finother; finother = finswap;
05591   }
05592 
05593   if ((adxtail != 0.0) || (adytail != 0.0)) {
05594     if ((bdxtail != 0.0) || (bdytail != 0.0)
05595         || (cdxtail != 0.0) || (cdytail != 0.0)) {
05596       Two_Product(bdxtail, cdy, ti1, ti0);
05597       Two_Product(bdx, cdytail, tj1, tj0);
05598       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05599       u[3] = u3;
05600       negate = -bdy;
05601       Two_Product(cdxtail, negate, ti1, ti0);
05602       negate = -bdytail;
05603       Two_Product(cdx, negate, tj1, tj0);
05604       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05605       v[3] = v3;
05606       bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
05607 
05608       Two_Product(bdxtail, cdytail, ti1, ti0);
05609       Two_Product(cdxtail, bdytail, tj1, tj0);
05610       Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
05611       bctt[3] = bctt3;
05612       bcttlen = 4;
05613     } else {
05614       bct[0] = 0.0;
05615       bctlen = 1;
05616       bctt[0] = 0.0;
05617       bcttlen = 1;
05618     }
05619 
05620     if (adxtail != 0.0) {
05621       temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
05622       axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
05623       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
05624                                             temp32a);
05625       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05626                                               temp32alen, temp32a, temp48);
05627       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05628                                               temp48, finother);
05629       finswap = finnow; finnow = finother; finother = finswap;
05630       if (bdytail != 0.0) {
05631         temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
05632         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05633                                               temp16a);
05634         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05635                                                 temp16a, finother);
05636         finswap = finnow; finnow = finother; finother = finswap;
05637       }
05638       if (cdytail != 0.0) {
05639         temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
05640         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05641                                               temp16a);
05642         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05643                                                 temp16a, finother);
05644         finswap = finnow; finnow = finother; finother = finswap;
05645       }
05646 
05647       temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
05648                                             temp32a);
05649       axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
05650       temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
05651                                             temp16a);
05652       temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
05653                                             temp16b);
05654       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05655                                               temp16blen, temp16b, temp32b);
05656       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05657                                               temp32blen, temp32b, temp64);
05658       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05659                                               temp64, finother);
05660       finswap = finnow; finnow = finother; finother = finswap;
05661     }
05662     if (adytail != 0.0) {
05663       temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
05664       aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
05665       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
05666                                             temp32a);
05667       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05668                                               temp32alen, temp32a, temp48);
05669       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05670                                               temp48, finother);
05671       finswap = finnow; finnow = finother; finother = finswap;
05672 
05673 
05674       temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
05675                                             temp32a);
05676       aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
05677       temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
05678                                             temp16a);
05679       temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
05680                                             temp16b);
05681       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05682                                               temp16blen, temp16b, temp32b);
05683       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05684                                               temp32blen, temp32b, temp64);
05685       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05686                                               temp64, finother);
05687       finswap = finnow; finnow = finother; finother = finswap;
05688     }
05689   }
05690   if ((bdxtail != 0.0) || (bdytail != 0.0)) {
05691     if ((cdxtail != 0.0) || (cdytail != 0.0)
05692         || (adxtail != 0.0) || (adytail != 0.0)) {
05693       Two_Product(cdxtail, ady, ti1, ti0);
05694       Two_Product(cdx, adytail, tj1, tj0);
05695       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05696       u[3] = u3;
05697       negate = -cdy;
05698       Two_Product(adxtail, negate, ti1, ti0);
05699       negate = -cdytail;
05700       Two_Product(adx, negate, tj1, tj0);
05701       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05702       v[3] = v3;
05703       catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
05704 
05705       Two_Product(cdxtail, adytail, ti1, ti0);
05706       Two_Product(adxtail, cdytail, tj1, tj0);
05707       Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
05708       catt[3] = catt3;
05709       cattlen = 4;
05710     } else {
05711       cat[0] = 0.0;
05712       catlen = 1;
05713       catt[0] = 0.0;
05714       cattlen = 1;
05715     }
05716 
05717     if (bdxtail != 0.0) {
05718       temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
05719       bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
05720       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
05721                                             temp32a);
05722       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05723                                               temp32alen, temp32a, temp48);
05724       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05725                                               temp48, finother);
05726       finswap = finnow; finnow = finother; finother = finswap;
05727       if (cdytail != 0.0) {
05728         temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
05729         temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05730                                               temp16a);
05731         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05732                                                 temp16a, finother);
05733         finswap = finnow; finnow = finother; finother = finswap;
05734       }
05735       if (adytail != 0.0) {
05736         temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
05737         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05738                                               temp16a);
05739         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05740                                                 temp16a, finother);
05741         finswap = finnow; finnow = finother; finother = finswap;
05742       }
05743 
05744       temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
05745                                             temp32a);
05746       bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
05747       temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
05748                                             temp16a);
05749       temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
05750                                             temp16b);
05751       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05752                                               temp16blen, temp16b, temp32b);
05753       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05754                                               temp32blen, temp32b, temp64);
05755       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05756                                               temp64, finother);
05757       finswap = finnow; finnow = finother; finother = finswap;
05758     }
05759     if (bdytail != 0.0) {
05760       temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
05761       bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
05762       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
05763                                             temp32a);
05764       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05765                                               temp32alen, temp32a, temp48);
05766       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05767                                               temp48, finother);
05768       finswap = finnow; finnow = finother; finother = finswap;
05769 
05770 
05771       temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
05772                                             temp32a);
05773       bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
05774       temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
05775                                             temp16a);
05776       temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
05777                                             temp16b);
05778       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05779                                               temp16blen, temp16b, temp32b);
05780       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05781                                               temp32blen, temp32b, temp64);
05782       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05783                                               temp64, finother);
05784       finswap = finnow; finnow = finother; finother = finswap;
05785     }
05786   }
05787   if ((cdxtail != 0.0) || (cdytail != 0.0)) {
05788     if ((adxtail != 0.0) || (adytail != 0.0)
05789         || (bdxtail != 0.0) || (bdytail != 0.0)) {
05790       Two_Product(adxtail, bdy, ti1, ti0);
05791       Two_Product(adx, bdytail, tj1, tj0);
05792       Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05793       u[3] = u3;
05794       negate = -ady;
05795       Two_Product(bdxtail, negate, ti1, ti0);
05796       negate = -adytail;
05797       Two_Product(bdx, negate, tj1, tj0);
05798       Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05799       v[3] = v3;
05800       abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
05801 
05802       Two_Product(adxtail, bdytail, ti1, ti0);
05803       Two_Product(bdxtail, adytail, tj1, tj0);
05804       Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
05805       abtt[3] = abtt3;
05806       abttlen = 4;
05807     } else {
05808       abt[0] = 0.0;
05809       abtlen = 1;
05810       abtt[0] = 0.0;
05811       abttlen = 1;
05812     }
05813 
05814     if (cdxtail != 0.0) {
05815       temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
05816       cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
05817       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
05818                                             temp32a);
05819       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05820                                               temp32alen, temp32a, temp48);
05821       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05822                                               temp48, finother);
05823       finswap = finnow; finnow = finother; finother = finswap;
05824       if (adytail != 0.0) {
05825         temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
05826         temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05827                                               temp16a);
05828         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05829                                                 temp16a, finother);
05830         finswap = finnow; finnow = finother; finother = finswap;
05831       }
05832       if (bdytail != 0.0) {
05833         temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
05834         temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05835                                               temp16a);
05836         finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05837                                                 temp16a, finother);
05838         finswap = finnow; finnow = finother; finother = finswap;
05839       }
05840 
05841       temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
05842                                             temp32a);
05843       cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
05844       temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
05845                                             temp16a);
05846       temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
05847                                             temp16b);
05848       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05849                                               temp16blen, temp16b, temp32b);
05850       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05851                                               temp32blen, temp32b, temp64);
05852       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05853                                               temp64, finother);
05854       finswap = finnow; finnow = finother; finother = finswap;
05855     }
05856     if (cdytail != 0.0) {
05857       temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
05858       cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
05859       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
05860                                             temp32a);
05861       temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05862                                               temp32alen, temp32a, temp48);
05863       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05864                                               temp48, finother);
05865       finswap = finnow; finnow = finother; finother = finswap;
05866 
05867 
05868       temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
05869                                             temp32a);
05870       cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
05871       temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
05872                                             temp16a);
05873       temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
05874                                             temp16b);
05875       temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05876                                               temp16blen, temp16b, temp32b);
05877       temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05878                                               temp32blen, temp32b, temp64);
05879       finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05880                                               temp64, finother);
05881       finswap = finnow; finnow = finother; finother = finswap;
05882     }
05883   }
05884 
05885   return finnow[finlength - 1];
05886 }
05887 
05888 #ifdef ANSI_DECLARATORS
05889 REAL incircle(struct mesh *m, struct behavior *b,
05890               vertex pa, vertex pb, vertex pc, vertex pd)
05891 #else 
05892 REAL incircle(m, b, pa, pb, pc, pd)
05893 struct mesh *m;
05894 struct behavior *b;
05895 vertex pa;
05896 vertex pb;
05897 vertex pc;
05898 vertex pd;
05899 #endif 
05900 
05901 {
05902   REAL adx, bdx, cdx, ady, bdy, cdy;
05903   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
05904   REAL alift, blift, clift;
05905   REAL det;
05906   REAL permanent, errbound;
05907 
05908   m->incirclecount++;
05909 
05910   adx = pa[0] - pd[0];
05911   bdx = pb[0] - pd[0];
05912   cdx = pc[0] - pd[0];
05913   ady = pa[1] - pd[1];
05914   bdy = pb[1] - pd[1];
05915   cdy = pc[1] - pd[1];
05916 
05917   bdxcdy = bdx * cdy;
05918   cdxbdy = cdx * bdy;
05919   alift = adx * adx + ady * ady;
05920 
05921   cdxady = cdx * ady;
05922   adxcdy = adx * cdy;
05923   blift = bdx * bdx + bdy * bdy;
05924 
05925   adxbdy = adx * bdy;
05926   bdxady = bdx * ady;
05927   clift = cdx * cdx + cdy * cdy;
05928 
05929   det = alift * (bdxcdy - cdxbdy)
05930       + blift * (cdxady - adxcdy)
05931       + clift * (adxbdy - bdxady);
05932 
05933   if (b->noexact) {
05934     return det;
05935   }
05936 
05937   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
05938             + (Absolute(cdxady) + Absolute(adxcdy)) * blift
05939             + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
05940   errbound = iccerrboundA * permanent;
05941   if ((det > errbound) || (-det > errbound)) {
05942     return det;
05943   }
05944 
05945   return incircleadapt(pa, pb, pc, pd, permanent);
05946 }
05947 
05948 
05949 
05950 
05951 
05952 
05953 
05954 
05955 
05956 
05957 
05958 
05959 
05960 
05961 
05962 
05963 
05964 
05965 
05966 
05967 
05968 
05969 
05970 #ifdef ANSI_DECLARATORS
05971 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
05972                    REAL aheight, REAL bheight, REAL cheight, REAL dheight,
05973                    REAL permanent)
05974 #else 
05975 REAL orient3dadapt(pa, pb, pc, pd,
05976                    aheight, bheight, cheight, dheight, permanent)
05977 vertex pa;
05978 vertex pb;
05979 vertex pc;
05980 vertex pd;
05981 REAL aheight;
05982 REAL bheight;
05983 REAL cheight;
05984 REAL dheight;
05985 REAL permanent;
05986 #endif 
05987 
05988 {
05989   INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
05990   REAL det, errbound;
05991 
05992   INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05993   REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05994   REAL bc[4], ca[4], ab[4];
05995   INEXACT REAL bc3, ca3, ab3;
05996   REAL adet[8], bdet[8], cdet[8];
05997   int alen, blen, clen;
05998   REAL abdet[16];
05999   int ablen;
06000   REAL *finnow, *finother, *finswap;
06001   REAL fin1[192], fin2[192];
06002   int finlength;
06003 
06004   REAL adxtail, bdxtail, cdxtail;
06005   REAL adytail, bdytail, cdytail;
06006   REAL adheighttail, bdheighttail, cdheighttail;
06007   INEXACT REAL at_blarge, at_clarge;
06008   INEXACT REAL bt_clarge, bt_alarge;
06009   INEXACT REAL ct_alarge, ct_blarge;
06010   REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
06011   int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
06012   INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
06013   INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
06014   REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
06015   REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
06016   INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
06017   INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
06018   REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
06019   REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
06020   REAL bct[8], cat[8], abt[8];
06021   int bctlen, catlen, abtlen;
06022   INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
06023   INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
06024   REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
06025   REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
06026   REAL u[4], v[12], w[16];
06027   INEXACT REAL u3;
06028   int vlength, wlength;
06029   REAL negate;
06030 
06031   INEXACT REAL bvirt;
06032   REAL avirt, bround, around;
06033   INEXACT REAL c;
06034   INEXACT REAL abig;
06035   REAL ahi, alo, bhi, blo;
06036   REAL err1, err2, err3;
06037   INEXACT REAL _i, _j, _k;
06038   REAL _0;
06039 
06040   adx = (REAL) (pa[0] - pd[0]);
06041   bdx = (REAL) (pb[0] - pd[0]);
06042   cdx = (REAL) (pc[0] - pd[0]);
06043   ady = (REAL) (pa[1] - pd[1]);
06044   bdy = (REAL) (pb[1] - pd[1]);
06045   cdy = (REAL) (pc[1] - pd[1]);
06046   adheight = (REAL) (aheight - dheight);
06047   bdheight = (REAL) (bheight - dheight);
06048   cdheight = (REAL) (cheight - dheight);
06049 
06050   Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
06051   Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
06052   Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
06053   bc[3] = bc3;
06054   alen = scale_expansion_zeroelim(4, bc, adheight, adet);
06055 
06056   Two_Product(cdx, ady, cdxady1, cdxady0);
06057   Two_Product(adx, cdy, adxcdy1, adxcdy0);
06058   Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
06059   ca[3] = ca3;
06060   blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
06061 
06062   Two_Product(adx, bdy, adxbdy1, adxbdy0);
06063   Two_Product(bdx, ady, bdxady1, bdxady0);
06064   Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
06065   ab[3] = ab3;
06066   clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
06067 
06068   ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
06069   finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
06070 
06071   det = estimate(finlength, fin1);
06072   errbound = o3derrboundB * permanent;
06073   if ((det >= errbound) || (-det >= errbound)) {
06074     return det;
06075   }
06076 
06077   Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
06078   Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
06079   Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
06080   Two_Diff_Tail(pa[1], pd[1], ady, adytail);
06081   Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
06082   Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
06083   Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
06084   Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
06085   Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
06086 
06087   if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
06088       (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
06089       (adheighttail == 0.0) &&
06090       (bdheighttail == 0.0) &&
06091       (cdheighttail == 0.0)) {
06092     return det;
06093   }
06094 
06095   errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
06096   det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
06097                       (bdy * cdxtail + cdx * bdytail)) +
06098           adheighttail * (bdx * cdy - bdy * cdx)) +
06099          (bdheight * ((cdx * adytail + ady * cdxtail) -
06100                       (cdy * adxtail + adx * cdytail)) +
06101           bdheighttail * (cdx * ady - cdy * adx)) +
06102          (cdheight * ((adx * bdytail + bdy * adxtail) -
06103                       (ady * bdxtail + bdx * adytail)) +
06104           cdheighttail * (adx * bdy - ady * bdx));
06105   if ((det >= errbound) || (-det >= errbound)) {
06106     return det;
06107   }
06108 
06109   finnow = fin1;
06110   finother = fin2;
06111 
06112   if (adxtail == 0.0) {
06113     if (adytail == 0.0) {
06114       at_b[0] = 0.0;
06115       at_blen = 1;
06116       at_c[0] = 0.0;
06117       at_clen = 1;
06118     } else {
06119       negate = -adytail;
06120       Two_Product(negate, bdx, at_blarge, at_b[0]);
06121       at_b[1] = at_blarge;
06122       at_blen = 2;
06123       Two_Product(adytail, cdx, at_clarge, at_c[0]);
06124       at_c[1] = at_clarge;
06125       at_clen = 2;
06126     }
06127   } else {
06128     if (adytail == 0.0) {
06129       Two_Product(adxtail, bdy, at_blarge, at_b[0]);
06130       at_b[1] = at_blarge;
06131       at_blen = 2;
06132       negate = -adxtail;
06133       Two_Product(negate, cdy, at_clarge, at_c[0]);
06134       at_c[1] = at_clarge;
06135       at_clen = 2;
06136     } else {
06137       Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
06138       Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
06139       Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
06140                    at_blarge, at_b[2], at_b[1], at_b[0]);
06141       at_b[3] = at_blarge;
06142       at_blen = 4;
06143       Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
06144       Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
06145       Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
06146                    at_clarge, at_c[2], at_c[1], at_c[0]);
06147       at_c[3] = at_clarge;
06148       at_clen = 4;
06149     }
06150   }
06151   if (bdxtail == 0.0) {
06152     if (bdytail == 0.0) {
06153       bt_c[0] = 0.0;
06154       bt_clen = 1;
06155       bt_a[0] = 0.0;
06156       bt_alen = 1;
06157     } else {
06158       negate = -bdytail;
06159       Two_Product(negate, cdx, bt_clarge, bt_c[0]);
06160       bt_c[1] = bt_clarge;
06161       bt_clen = 2;
06162       Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
06163       bt_a[1] = bt_alarge;
06164       bt_alen = 2;
06165     }
06166   } else {
06167     if (bdytail == 0.0) {
06168       Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
06169       bt_c[1] = bt_clarge;
06170       bt_clen = 2;
06171       negate = -bdxtail;
06172       Two_Product(negate, ady, bt_alarge, bt_a[0]);
06173       bt_a[1] = bt_alarge;
06174       bt_alen = 2;
06175     } else {
06176       Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
06177       Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
06178       Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
06179                    bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
06180       bt_c[3] = bt_clarge;
06181       bt_clen = 4;
06182       Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
06183       Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
06184       Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
06185                   bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
06186       bt_a[3] = bt_alarge;
06187       bt_alen = 4;
06188     }
06189   }
06190   if (cdxtail == 0.0) {
06191     if (cdytail == 0.0) {
06192       ct_a[0] = 0.0;
06193       ct_alen = 1;
06194       ct_b[0] = 0.0;
06195       ct_blen = 1;
06196     } else {
06197       negate = -cdytail;
06198       Two_Product(negate, adx, ct_alarge, ct_a[0]);
06199       ct_a[1] = ct_alarge;
06200       ct_alen = 2;
06201       Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
06202       ct_b[1] = ct_blarge;
06203       ct_blen = 2;
06204     }
06205   } else {
06206     if (cdytail == 0.0) {
06207       Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
06208       ct_a[1] = ct_alarge;
06209       ct_alen = 2;
06210       negate = -cdxtail;
06211       Two_Product(negate, bdy, ct_blarge, ct_b[0]);
06212       ct_b[1] = ct_blarge;
06213       ct_blen = 2;
06214     } else {
06215       Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
06216       Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
06217       Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
06218                    ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
06219       ct_a[3] = ct_alarge;
06220       ct_alen = 4;
06221       Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
06222       Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
06223       Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
06224                    ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
06225       ct_b[3] = ct_blarge;
06226       ct_blen = 4;
06227     }
06228   }
06229 
06230   bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
06231   wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
06232   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06233                                           finother);
06234   finswap = finnow; finnow = finother; finother = finswap;
06235 
06236   catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
06237   wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
06238   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06239                                           finother);
06240   finswap = finnow; finnow = finother; finother = finswap;
06241 
06242   abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
06243   wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
06244   finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06245                                           finother);
06246   finswap = finnow; finnow = finother; finother = finswap;
06247 
06248   if (adheighttail != 0.0) {
06249     vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
06250     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06251                                             finother);
06252     finswap = finnow; finnow = finother; finother = finswap;
06253   }
06254   if (bdheighttail != 0.0) {
06255     vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
06256     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06257                                             finother);
06258     finswap = finnow; finnow = finother; finother = finswap;
06259   }
06260   if (cdheighttail != 0.0) {
06261     vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
06262     finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06263                                             finother);
06264     finswap = finnow; finnow = finother; finother = finswap;
06265   }
06266 
06267   if (adxtail != 0.0) {
06268     if (bdytail != 0.0) {
06269       Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
06270       Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
06271       u[3] = u3;
06272       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06273                                               finother);
06274       finswap = finnow; finnow = finother; finother = finswap;
06275       if (cdheighttail != 0.0) {
06276         Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
06277                         u3, u[2], u[1], u[0]);
06278         u[3] = u3;
06279         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06280                                                 finother);
06281         finswap = finnow; finnow = finother; finother = finswap;
06282       }
06283     }
06284     if (cdytail != 0.0) {
06285       negate = -adxtail;
06286       Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
06287       Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
06288       u[3] = u3;
06289       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06290                                               finother);
06291       finswap = finnow; finnow = finother; finother = finswap;
06292       if (bdheighttail != 0.0) {
06293         Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
06294                         u3, u[2], u[1], u[0]);
06295         u[3] = u3;
06296         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06297                                                 finother);
06298         finswap = finnow; finnow = finother; finother = finswap;
06299       }
06300     }
06301   }
06302   if (bdxtail != 0.0) {
06303     if (cdytail != 0.0) {
06304       Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
06305       Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
06306       u[3] = u3;
06307       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06308                                               finother);
06309       finswap = finnow; finnow = finother; finother = finswap;
06310       if (adheighttail != 0.0) {
06311         Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
06312                         u3, u[2], u[1], u[0]);
06313         u[3] = u3;
06314         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06315                                                 finother);
06316         finswap = finnow; finnow = finother; finother = finswap;
06317       }
06318     }
06319     if (adytail != 0.0) {
06320       negate = -bdxtail;
06321       Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
06322       Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
06323       u[3] = u3;
06324       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06325                                               finother);
06326       finswap = finnow; finnow = finother; finother = finswap;
06327       if (cdheighttail != 0.0) {
06328         Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
06329                         u3, u[2], u[1], u[0]);
06330         u[3] = u3;
06331         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06332                                                 finother);
06333         finswap = finnow; finnow = finother; finother = finswap;
06334       }
06335     }
06336   }
06337   if (cdxtail != 0.0) {
06338     if (adytail != 0.0) {
06339       Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
06340       Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
06341       u[3] = u3;
06342       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06343                                               finother);
06344       finswap = finnow; finnow = finother; finother = finswap;
06345       if (bdheighttail != 0.0) {
06346         Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
06347                         u3, u[2], u[1], u[0]);
06348         u[3] = u3;
06349         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06350                                                 finother);
06351         finswap = finnow; finnow = finother; finother = finswap;
06352       }
06353     }
06354     if (bdytail != 0.0) {
06355       negate = -cdxtail;
06356       Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
06357       Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
06358       u[3] = u3;
06359       finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06360                                               finother);
06361       finswap = finnow; finnow = finother; finother = finswap;
06362       if (adheighttail != 0.0) {
06363         Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
06364                         u3, u[2], u[1], u[0]);
06365         u[3] = u3;
06366         finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06367                                                 finother);
06368         finswap = finnow; finnow = finother; finother = finswap;
06369       }
06370     }
06371   }
06372 
06373   if (adheighttail != 0.0) {
06374     wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
06375     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06376                                             finother);
06377     finswap = finnow; finnow = finother; finother = finswap;
06378   }
06379   if (bdheighttail != 0.0) {
06380     wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
06381     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06382                                             finother);
06383     finswap = finnow; finnow = finother; finother = finswap;
06384   }
06385   if (cdheighttail != 0.0) {
06386     wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
06387     finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06388                                             finother);
06389     finswap = finnow; finnow = finother; finother = finswap;
06390   }
06391 
06392   return finnow[finlength - 1];
06393 }
06394 
06395 #ifdef ANSI_DECLARATORS
06396 REAL orient3d(struct mesh *m, struct behavior *b,
06397               vertex pa, vertex pb, vertex pc, vertex pd,
06398               REAL aheight, REAL bheight, REAL cheight, REAL dheight)
06399 #else 
06400 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
06401 struct mesh *m;
06402 struct behavior *b;
06403 vertex pa;
06404 vertex pb;
06405 vertex pc;
06406 vertex pd;
06407 REAL aheight;
06408 REAL bheight;
06409 REAL cheight;
06410 REAL dheight;
06411 #endif 
06412 
06413 {
06414   REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06415   REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
06416   REAL det;
06417   REAL permanent, errbound;
06418 
06419   m->orient3dcount++;
06420 
06421   adx = pa[0] - pd[0];
06422   bdx = pb[0] - pd[0];
06423   cdx = pc[0] - pd[0];
06424   ady = pa[1] - pd[1];
06425   bdy = pb[1] - pd[1];
06426   cdy = pc[1] - pd[1];
06427   adheight = aheight - dheight;
06428   bdheight = bheight - dheight;
06429   cdheight = cheight - dheight;
06430 
06431   bdxcdy = bdx * cdy;
06432   cdxbdy = cdx * bdy;
06433 
06434   cdxady = cdx * ady;
06435   adxcdy = adx * cdy;
06436 
06437   adxbdy = adx * bdy;
06438   bdxady = bdx * ady;
06439 
06440   det = adheight * (bdxcdy - cdxbdy) 
06441       + bdheight * (cdxady - adxcdy)
06442       + cdheight * (adxbdy - bdxady);
06443 
06444   if (b->noexact) {
06445     return det;
06446   }
06447 
06448   permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
06449             + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
06450             + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
06451   errbound = o3derrboundA * permanent;
06452   if ((det > errbound) || (-det > errbound)) {
06453     return det;
06454   }
06455 
06456   return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
06457                        permanent);
06458 }
06459 
06460 
06461 
06462 
06463 
06464 
06465 
06466 
06467 
06468 
06469 
06470 
06471 
06472 
06473 
06474 
06475 
06476 
06477 
06478 #ifdef ANSI_DECLARATORS
06479 REAL nonregular(struct mesh *m, struct behavior *b,
06480                 vertex pa, vertex pb, vertex pc, vertex pd)
06481 #else 
06482 REAL nonregular(m, b, pa, pb, pc, pd)
06483 struct mesh *m;
06484 struct behavior *b;
06485 vertex pa;
06486 vertex pb;
06487 vertex pc;
06488 vertex pd;
06489 #endif 
06490 
06491 {
06492   if (b->weighted == 0) {
06493     return incircle(m, b, pa, pb, pc, pd);
06494   } else if (b->weighted == 1) {
06495     return orient3d(m, b, pa, pb, pc, pd,
06496                     pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
06497                     pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
06498                     pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
06499                     pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
06500   } else {
06501     return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
06502   }
06503 }
06504 
06505 
06506 
06507 
06508 
06509 
06510 
06511 
06512 
06513 
06514 
06515 
06516 
06517 
06518 
06519 #ifdef ANSI_DECLARATORS
06520 void findcircumcenter(struct mesh *m, struct behavior *b,
06521                       vertex torg, vertex tdest, vertex tapex,
06522                       vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
06523 #else 
06524 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
06525                       offcenter)
06526 struct mesh *m;
06527 struct behavior *b;
06528 vertex torg;
06529 vertex tdest;
06530 vertex tapex;
06531 vertex circumcenter;
06532 REAL *xi;
06533 REAL *eta;
06534 int offcenter;
06535 #endif 
06536 
06537 {
06538   REAL xdo, ydo, xao, yao;
06539   REAL dodist, aodist, dadist;
06540   REAL denominator;
06541   REAL dx, dy, dxoff, dyoff;
06542 
06543   m->circumcentercount++;
06544 
06545   
06546   xdo = tdest[0] - torg[0];
06547   ydo = tdest[1] - torg[1];
06548   xao = tapex[0] - torg[0];
06549   yao = tapex[1] - torg[1];
06550   dodist = xdo * xdo + ydo * ydo;
06551   aodist = xao * xao + yao * yao;
06552   dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
06553            (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
06554   if (b->noexact) {
06555     denominator = 0.5 / (xdo * yao - xao * ydo);
06556   } else {
06557     
06558     
06559     
06560     denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
06561     
06562     m->counterclockcount--;
06563   }
06564   dx = (yao * dodist - ydo * aodist) * denominator;
06565   dy = (xdo * aodist - xao * dodist) * denominator;
06566 
06567   
06568   
06569   
06570   
06571   
06572   if ((dodist < aodist) && (dodist < dadist)) {
06573     if (offcenter && (b->offconstant > 0.0)) {
06574       
06575       dxoff = 0.5 * xdo - b->offconstant * ydo;
06576       dyoff = 0.5 * ydo + b->offconstant * xdo;
06577       
06578       
06579       if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06580         dx = dxoff;
06581         dy = dyoff;
06582       }
06583     }
06584   } else if (aodist < dadist) {
06585     if (offcenter && (b->offconstant > 0.0)) {
06586       dxoff = 0.5 * xao + b->offconstant * yao;
06587       dyoff = 0.5 * yao - b->offconstant * xao;
06588       
06589       
06590       if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06591         dx = dxoff;
06592         dy = dyoff;
06593       }
06594     }
06595   } else {
06596     if (offcenter && (b->offconstant > 0.0)) {
06597       dxoff = 0.5 * (tapex[0] - tdest[0]) -
06598               b->offconstant * (tapex[1] - tdest[1]);
06599       dyoff = 0.5 * (tapex[1] - tdest[1]) +
06600               b->offconstant * (tapex[0] - tdest[0]);
06601       
06602       
06603       if (dxoff * dxoff + dyoff * dyoff <
06604           (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
06605         dx = xdo + dxoff;
06606         dy = ydo + dyoff;
06607       }
06608     }
06609   }
06610 
06611   circumcenter[0] = torg[0] + dx;
06612   circumcenter[1] = torg[1] + dy;
06613 
06614   
06615   
06616   
06617   
06618   
06619   *xi = (yao * dx - xao * dy) * (2.0 * denominator);
06620   *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
06621 }
06622 
06625 
06626 
06627 
06628 
06629 
06630 
06631 
06632 
06633 #ifdef ANSI_DECLARATORS
06634 void triangleinit(struct mesh *m)
06635 #else 
06636 void triangleinit(m)
06637 struct mesh *m;
06638 #endif 
06639 
06640 {
06641   poolzero(&m->vertices);
06642   poolzero(&m->triangles);
06643   poolzero(&m->subsegs);
06644   poolzero(&m->viri);
06645   poolzero(&m->badsubsegs);
06646   poolzero(&m->badtriangles);
06647   poolzero(&m->flipstackers);
06648   poolzero(&m->splaynodes);
06649 
06650   m->recenttri.tri = (triangle *) NULL; 
06651   m->undeads = 0;                       
06652   m->samples = 1;         
06653   m->checksegments = 0;   
06654   m->checkquality = 0;     
06655   m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
06656   m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
06657   randomseed = 1;
06658 
06659   exactinit();                     
06660 }
06661 
06662 
06663 
06664 
06665 
06666 
06667 
06668 
06669 
06670 
06671 
06672 #ifdef ANSI_DECLARATORS
06673 unsigned long randomnation(unsigned int choices)
06674 #else 
06675 unsigned long randomnation(choices)
06676 unsigned int choices;
06677 #endif 
06678 
06679 {
06680   randomseed = (randomseed * 1366l + 150889l) % 714025l;
06681   return randomseed / (714025l / choices + 1);
06682 }
06683 
06684 
06688 
06689 
06690 
06691 
06692 
06693 
06694 #ifndef REDUCED
06695 
06696 #ifdef ANSI_DECLARATORS
06697 void checkmesh(struct mesh *m, struct behavior *b)
06698 #else 
06699 void checkmesh(m, b)
06700 struct mesh *m;
06701 struct behavior *b;
06702 #endif 
06703 
06704 {
06705   struct otri triangleloop;
06706   struct otri oppotri, oppooppotri;
06707   vertex triorg, tridest, triapex;
06708   vertex oppoorg, oppodest;
06709   int horrors;
06710   int saveexact;
06711   triangle ptr;                         
06712 
06713   
06714   saveexact = b->noexact;
06715   b->noexact = 0;
06716   if (!b->quiet) {
06717     printf("  Checking consistency of mesh...\n");
06718   }
06719   horrors = 0;
06720   
06721   traversalinit(&m->triangles);
06722   triangleloop.tri = triangletraverse(m);
06723   while (triangleloop.tri != (triangle *) NULL) {
06724     
06725     for (triangleloop.orient = 0; triangleloop.orient < 3;
06726          triangleloop.orient++) {
06727       org(triangleloop, triorg);
06728       dest(triangleloop, tridest);
06729       if (triangleloop.orient == 0) {       
06730         
06731         apex(triangleloop, triapex);
06732         if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
06733           printf("  !! !! Inverted ");
06734           printtriangle(m, b, &triangleloop);
06735           horrors++;
06736         }
06737       }
06738       
06739       sym(triangleloop, oppotri);
06740       if (oppotri.tri != m->dummytri) {
06741         
06742         sym(oppotri, oppooppotri);
06743         if ((triangleloop.tri != oppooppotri.tri)
06744             || (triangleloop.orient != oppooppotri.orient)) {
06745           printf("  !! !! Asymmetric triangle-triangle bond:\n");
06746           if (triangleloop.tri == oppooppotri.tri) {
06747             printf("   (Right triangle, wrong orientation)\n");
06748           }
06749           printf("    First ");
06750           printtriangle(m, b, &triangleloop);
06751           printf("    Second (nonreciprocating) ");
06752           printtriangle(m, b, &oppotri);
06753           horrors++;
06754         }
06755         
06756         
06757         org(oppotri, oppoorg);
06758         dest(oppotri, oppodest);
06759         if ((triorg != oppodest) || (tridest != oppoorg)) {
06760           printf("  !! !! Mismatched edge coordinates between two triangles:\n"
06761                  );
06762           printf("    First mismatched ");
06763           printtriangle(m, b, &triangleloop);
06764           printf("    Second mismatched ");
06765           printtriangle(m, b, &oppotri);
06766           horrors++;
06767         }
06768       }
06769     }
06770     triangleloop.tri = triangletraverse(m);
06771   }
06772   if (horrors == 0) {
06773     if (!b->quiet) {
06774       printf("  In my studied opinion, the mesh appears to be consistent.\n");
06775     }
06776   } else if (horrors == 1) {
06777     printf("  !! !! !! !! Precisely one festering wound discovered.\n");
06778   } else {
06779     printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
06780   }
06781   
06782   b->noexact = saveexact;
06783 }
06784 
06785 #endif 
06786 
06787 
06788 
06789 
06790 
06791 
06792 
06793 #ifndef REDUCED
06794 
06795 #ifdef ANSI_DECLARATORS
06796 void checkdelaunay(struct mesh *m, struct behavior *b)
06797 #else 
06798 void checkdelaunay(m, b)
06799 struct mesh *m;
06800 struct behavior *b;
06801 #endif 
06802 
06803 {
06804   struct otri triangleloop;
06805   struct otri oppotri;
06806   struct osub opposubseg;
06807   vertex triorg, tridest, triapex;
06808   vertex oppoapex;
06809   int shouldbedelaunay;
06810   int horrors;
06811   int saveexact;
06812   triangle ptr;                         
06813   subseg sptr;                      
06814 
06815   
06816   saveexact = b->noexact;
06817   b->noexact = 0;
06818   if (!b->quiet) {
06819     printf("  Checking Delaunay property of mesh...\n");
06820   }
06821   horrors = 0;
06822   
06823   traversalinit(&m->triangles);
06824   triangleloop.tri = triangletraverse(m);
06825   while (triangleloop.tri != (triangle *) NULL) {
06826     
06827     for (triangleloop.orient = 0; triangleloop.orient < 3;
06828          triangleloop.orient++) {
06829       org(triangleloop, triorg);
06830       dest(triangleloop, tridest);
06831       apex(triangleloop, triapex);
06832       sym(triangleloop, oppotri);
06833       apex(oppotri, oppoapex);
06834       
06835       
06836       
06837       shouldbedelaunay = (oppotri.tri != m->dummytri) &&
06838             !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
06839             (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
06840             (triorg != m->infvertex3) &&
06841             (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
06842             (tridest != m->infvertex3) &&
06843             (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
06844             (triapex != m->infvertex3) &&
06845             (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
06846             (oppoapex != m->infvertex3);
06847       if (m->checksegments && shouldbedelaunay) {
06848         
06849         
06850         tspivot(triangleloop, opposubseg);
06851         if (opposubseg.ss != m->dummysub){
06852           shouldbedelaunay = 0;
06853         }
06854       }
06855       if (shouldbedelaunay) {
06856         if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
06857           if (!b->weighted) {
06858             printf("  !! !! Non-Delaunay pair of triangles:\n");
06859             printf("    First non-Delaunay ");
06860             printtriangle(m, b, &triangleloop);
06861             printf("    Second non-Delaunay ");
06862           } else {
06863             printf("  !! !! Non-regular pair of triangles:\n");
06864             printf("    First non-regular ");
06865             printtriangle(m, b, &triangleloop);
06866             printf("    Second non-regular ");
06867           }
06868           printtriangle(m, b, &oppotri);
06869           horrors++;
06870         }
06871       }
06872     }
06873     triangleloop.tri = triangletraverse(m);
06874   }
06875   if (horrors == 0) {
06876     if (!b->quiet) {
06877       printf(
06878   "  By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
06879     }
06880   } else if (horrors == 1) {
06881     printf(
06882          "  !! !! !! !! Precisely one terrifying transgression identified.\n");
06883   } else {
06884     printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
06885   }
06886   
06887   b->noexact = saveexact;
06888 }
06889 
06890 #endif 
06891 
06892 
06893 
06894 
06895 
06896 
06897 
06898 
06899 
06900 
06901 
06902 
06903 #ifndef CDT_ONLY
06904 
06905 #ifdef ANSI_DECLARATORS
06906 void enqueuebadtriang(struct mesh *m, struct behavior *b,
06907                       struct badtriang *badtri)
06908 #else 
06909 void enqueuebadtriang(m, b, badtri)
06910 struct mesh *m;
06911 struct behavior *b;
06912 struct badtriang *badtri;
06913 #endif 
06914 
06915 {
06916   REAL length, multiplier;
06917   int exponent, expincrement;
06918   int queuenumber;
06919   int posexponent;
06920   int i;
06921 
06922   if (b->verbose > 2) {
06923     printf("  Queueing bad triangle:\n");
06924     printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
06925            badtri->triangorg[0], badtri->triangorg[1],
06926            badtri->triangdest[0], badtri->triangdest[1],
06927            badtri->triangapex[0], badtri->triangapex[1]);
06928   }
06929 
06930   
06931   
06932   if (badtri->key >= 1.0) {
06933     length = badtri->key;
06934     posexponent = 1;
06935   } else {
06936     
06937     
06938     length = 1.0 / badtri->key;
06939     posexponent = 0;
06940   }
06941   
06942   
06943   exponent = 0;
06944   while (length > 2.0) {
06945     
06946     expincrement = 1;
06947     multiplier = 0.5;
06948     while (length * multiplier * multiplier > 1.0) {
06949       expincrement *= 2;
06950       multiplier *= multiplier;
06951     }
06952     
06953     exponent += expincrement;
06954     length *= multiplier;
06955   }
06956   
06957   exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
06958   
06959   
06960   
06961   if (posexponent) {
06962     queuenumber = 2047 - exponent;
06963   } else {
06964     queuenumber = 2048 + exponent;
06965   }
06966 
06967   
06968   if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
06969     
06970     
06971     if (queuenumber > m->firstnonemptyq) {
06972       
06973       m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
06974       m->firstnonemptyq = queuenumber;
06975     } else {
06976       
06977       
06978       i = queuenumber + 1;
06979       while (m->queuefront[i] == (struct badtriang *) NULL) {
06980         i++;
06981       }
06982       
06983       m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
06984       m->nextnonemptyq[i] = queuenumber;
06985     }
06986     
06987     m->queuefront[queuenumber] = badtri;
06988   } else {
06989     
06990     m->queuetail[queuenumber]->nexttriang = badtri;
06991   }
06992   
06993   m->queuetail[queuenumber] = badtri;
06994   
06995   badtri->nexttriang = (struct badtriang *) NULL;
06996 }
06997 
06998 #endif 
06999 
07000 
07001 
07002 
07003 
07004 
07005 
07006 
07007 
07008 
07009 #ifndef CDT_ONLY
07010 
07011 #ifdef ANSI_DECLARATORS
07012 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
07013                    REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
07014 #else 
07015 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
07016 struct mesh *m;
07017 struct behavior *b;
07018 struct otri *enqtri;
07019 REAL minedge;
07020 vertex enqapex;
07021 vertex enqorg;
07022 vertex enqdest;
07023 #endif 
07024 
07025 {
07026   struct badtriang *newbad;
07027 
07028   
07029   newbad = (struct badtriang *) poolalloc(&m->badtriangles);
07030   newbad->poortri = encode(*enqtri);
07031   newbad->key = minedge;
07032   newbad->triangapex = enqapex;
07033   newbad->triangorg = enqorg;
07034   newbad->triangdest = enqdest;
07035   enqueuebadtriang(m, b, newbad);
07036 }
07037 
07038 #endif 
07039 
07040 
07041 
07042 
07043 
07044 
07045 
07046 #ifndef CDT_ONLY
07047 
07048 #ifdef ANSI_DECLARATORS
07049 struct badtriang *dequeuebadtriang(struct mesh *m)
07050 #else 
07051 struct badtriang *dequeuebadtriang(m)
07052 struct mesh *m;
07053 #endif 
07054 
07055 {
07056   struct badtriang *result;
07057 
07058   
07059   if (m->firstnonemptyq < 0) {
07060     return (struct badtriang *) NULL;
07061   }
07062   
07063   result = m->queuefront[m->firstnonemptyq];
07064   
07065   m->queuefront[m->firstnonemptyq] = result->nexttriang;
07066   
07067   
07068   if (result == m->queuetail[m->firstnonemptyq]) {
07069     m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
07070   }
07071   return result;
07072 }
07073 
07074 #endif 
07075 
07076 
07077 
07078 
07079 
07080 
07081 
07082 
07083 
07084 
07085 
07086 
07087 
07088 
07089 
07090 
07091 
07092 
07093 
07094 
07095 
07096 
07097 
07098 
07099 #ifndef CDT_ONLY
07100 
07101 #ifdef ANSI_DECLARATORS
07102 int checkseg4encroach(struct mesh *m, struct behavior *b,
07103                       struct osub *testsubseg)
07104 #else 
07105 int checkseg4encroach(m, b, testsubseg)
07106 struct mesh *m;
07107 struct behavior *b;
07108 struct osub *testsubseg;
07109 #endif 
07110 
07111 {
07112   struct otri neighbortri;
07113   struct osub testsym;
07114   struct badsubseg *encroachedseg;
07115   REAL dotproduct;
07116   int encroached;
07117   int sides;
07118   vertex eorg, edest, eapex;
07119   triangle ptr;                     
07120 
07121   encroached = 0;
07122   sides = 0;
07123 
07124   sorg(*testsubseg, eorg);
07125   sdest(*testsubseg, edest);
07126   
07127   stpivot(*testsubseg, neighbortri);
07128   
07129   if (neighbortri.tri != m->dummytri) {
07130     sides++;
07131     
07132     apex(neighbortri, eapex);
07133     
07134     
07135     
07136     
07137     
07138     dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07139                  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07140     if (dotproduct < 0.0) {
07141       if (b->conformdel ||
07142           (dotproduct * dotproduct >=
07143            (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07144            ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07145             (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07146            ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07147             (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07148         encroached = 1;
07149       }
07150     }
07151   }
07152   
07153   ssym(*testsubseg, testsym);
07154   stpivot(testsym, neighbortri);
07155   
07156   if (neighbortri.tri != m->dummytri) {
07157     sides++;
07158     
07159     apex(neighbortri, eapex);
07160     
07161     
07162     dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07163                  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07164     if (dotproduct < 0.0) {
07165       if (b->conformdel ||
07166           (dotproduct * dotproduct >=
07167            (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07168            ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07169             (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07170            ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07171             (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07172         encroached += 2;
07173       }
07174     }
07175   }
07176 
07177   if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
07178     if (b->verbose > 2) {
07179       printf(
07180         "  Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
07181         eorg[0], eorg[1], edest[0], edest[1]);
07182     }
07183     
07184     
07185     encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
07186     if (encroached == 1) {
07187       encroachedseg->encsubseg = sencode(*testsubseg);
07188       encroachedseg->subsegorg = eorg;
07189       encroachedseg->subsegdest = edest;
07190     } else {
07191       encroachedseg->encsubseg = sencode(testsym);
07192       encroachedseg->subsegorg = edest;
07193       encroachedseg->subsegdest = eorg;
07194     }
07195   }
07196 
07197   return encroached;
07198 }
07199 
07200 #endif 
07201 
07202 
07203 
07204 
07205 
07206 
07207 
07208 
07209 
07210 
07211 
07212 #ifndef CDT_ONLY
07213 
07214 #ifdef ANSI_DECLARATORS
07215 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
07216 #else 
07217 void testtriangle(m, b, testtri)
07218 struct mesh *m;
07219 struct behavior *b;
07220 struct otri *testtri;
07221 #endif 
07222 
07223 {
07224   struct otri tri1, tri2;
07225   struct osub testsub;
07226   vertex torg, tdest, tapex;
07227   vertex base1, base2;
07228   vertex org1, dest1, org2, dest2;
07229   vertex joinvertex;
07230   REAL dxod, dyod, dxda, dyda, dxao, dyao;
07231   REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
07232   REAL apexlen, orglen, destlen, minedge;
07233   REAL angle;
07234   REAL area;
07235   REAL dist1, dist2;
07236   subseg sptr;                      
07237   triangle ptr;           
07238 
07239   org(*testtri, torg);
07240   dest(*testtri, tdest);
07241   apex(*testtri, tapex);
07242   dxod = torg[0] - tdest[0];
07243   dyod = torg[1] - tdest[1];
07244   dxda = tdest[0] - tapex[0];
07245   dyda = tdest[1] - tapex[1];
07246   dxao = tapex[0] - torg[0];
07247   dyao = tapex[1] - torg[1];
07248   dxod2 = dxod * dxod;
07249   dyod2 = dyod * dyod;
07250   dxda2 = dxda * dxda;
07251   dyda2 = dyda * dyda;
07252   dxao2 = dxao * dxao;
07253   dyao2 = dyao * dyao;
07254   
07255   apexlen = dxod2 + dyod2;
07256   orglen = dxda2 + dyda2;
07257   destlen = dxao2 + dyao2;
07258 
07259   if ((apexlen < orglen) && (apexlen < destlen)) {
07260     
07261     minedge = apexlen;
07262     
07263     angle = dxda * dxao + dyda * dyao;
07264     angle = angle * angle / (orglen * destlen);
07265     base1 = torg;
07266     base2 = tdest;
07267     otricopy(*testtri, tri1);
07268   } else if (orglen < destlen) {
07269     
07270     minedge = orglen;
07271     
07272     angle = dxod * dxao + dyod * dyao;
07273     angle = angle * angle / (apexlen * destlen);
07274     base1 = tdest;
07275     base2 = tapex;
07276     lnext(*testtri, tri1);
07277   } else {
07278     
07279     minedge = destlen;
07280     
07281     angle = dxod * dxda + dyod * dyda;
07282     angle = angle * angle / (apexlen * orglen);
07283     base1 = tapex;
07284     base2 = torg;
07285     lprev(*testtri, tri1);
07286   }
07287 
07288   if (b->vararea || b->fixedarea || b->usertest) {
07289     
07290     area = 0.5 * (dxod * dyda - dyod * dxda);
07291     if (b->fixedarea && (area > b->maxarea)) {
07292       
07293       enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07294       return;
07295     }
07296 
07297     
07298     if ((b->vararea) && (area > areabound(*testtri)) &&
07299         (areabound(*testtri) > 0.0)) {
07300       
07301       enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07302       return;
07303     }
07304 
07305     if (b->usertest) {
07306       
07307       if (triunsuitable(torg, tdest, tapex, area)) {
07308         enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07309         return;
07310       }
07311     }
07312   }
07313 
07314   
07315   if (angle > b->goodangle) {
07316     
07317     
07318     
07319     
07320     
07321     
07322     
07323     
07324     
07325     if ((vertextype(base1) == SEGMENTVERTEX) &&
07326         (vertextype(base2) == SEGMENTVERTEX)) {
07327       
07328       
07329       tspivot(tri1, testsub);
07330       if (testsub.ss == m->dummysub) {
07331         
07332         otricopy(tri1, tri2);
07333         do {
07334           oprevself(tri1);
07335           tspivot(tri1, testsub);
07336         } while (testsub.ss == m->dummysub);
07337         
07338         segorg(testsub, org1);
07339         segdest(testsub, dest1);
07340         
07341         do {
07342           dnextself(tri2);
07343           tspivot(tri2, testsub);
07344         } while (testsub.ss == m->dummysub);
07345         
07346         segorg(testsub, org2);
07347         segdest(testsub, dest2);
07348         
07349         joinvertex = (vertex) NULL;
07350         if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
07351           joinvertex = dest1;
07352         } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
07353           joinvertex = org1;
07354         }
07355         if (joinvertex != (vertex) NULL) {
07356           
07357           
07358           dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
07359                    (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
07360           dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
07361                    (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
07362           
07363           if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
07364             
07365             return;
07366           }
07367         }
07368       }
07369     }
07370 
07371     
07372     enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07373   }
07374 }
07375 
07376 #endif 
07377 
07380 
07381 
07382 
07386 
07387 
07388 
07389 
07390 
07391 
07392 
07393 
07394 
07395 
07396 
07397 
07398 
07399 
07400 #ifdef ANSI_DECLARATORS
07401 void makevertexmap(struct mesh *m, struct behavior *b)
07402 #else 
07403 void makevertexmap(m, b)
07404 struct mesh *m;
07405 struct behavior *b;
07406 #endif 
07407 
07408 {
07409   struct otri triangleloop;
07410   vertex triorg;
07411 
07412   if (b->verbose) {
07413     printf("    Constructing mapping from vertices to triangles.\n");
07414   }
07415   traversalinit(&m->triangles);
07416   triangleloop.tri = triangletraverse(m);
07417   while (triangleloop.tri != (triangle *) NULL) {
07418     
07419     for (triangleloop.orient = 0; triangleloop.orient < 3;
07420          triangleloop.orient++) {
07421       org(triangleloop, triorg);
07422       setvertex2tri(triorg, encode(triangleloop));
07423     }
07424     triangleloop.tri = triangletraverse(m);
07425   }
07426 }
07427 
07428 
07429 
07430 
07431 
07432 
07433 
07434 
07435 
07436 
07437 
07438 
07439 
07440 
07441 
07442 
07443 
07444 
07445 
07446 
07447 
07448 
07449 
07450 
07451 
07452 
07453 
07454 
07455 
07456 
07457 
07458 
07459 
07460 
07461 
07462 
07463 
07464 
07465 
07466 
07467 
07468 
07469 
07470 
07471 
07472 
07473 
07474 
07475 
07476 
07477 
07478 
07479 
07480 
07481 
07482 
07483 
07484 
07485 
07486 
07487 
07488 
07489 
07490 
07491 
07492 
07493 
07494 
07495 #ifdef ANSI_DECLARATORS
07496 enum locateresult preciselocate(struct mesh *m, struct behavior *b,
07497                                 vertex searchpoint, struct otri *searchtri,
07498                                 int stopatsubsegment)
07499 #else 
07500 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
07501 struct mesh *m;
07502 struct behavior *b;
07503 vertex searchpoint;
07504 struct otri *searchtri;
07505 int stopatsubsegment;
07506 #endif 
07507 
07508 {
07509   struct otri backtracktri;
07510   struct osub checkedge;
07511   vertex forg, fdest, fapex;
07512   REAL orgorient, destorient;
07513   int moveleft;
07514   triangle ptr;                         
07515   subseg sptr;                      
07516 
07517   if (b->verbose > 2) {
07518     printf("  Searching for point (%.12g, %.12g).\n",
07519            searchpoint[0], searchpoint[1]);
07520   }
07521   
07522   org(*searchtri, forg);
07523   dest(*searchtri, fdest);
07524   apex(*searchtri, fapex);
07525   while (1) {
07526     if (b->verbose > 2) {
07527       printf("    At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07528              forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
07529     }
07530     
07531     if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
07532       lprevself(*searchtri);
07533       return ONVERTEX;
07534     }
07535     
07536     
07537     destorient = counterclockwise(m, b, forg, fapex, searchpoint);
07538     
07539     
07540     orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
07541     if (destorient > 0.0) {
07542       if (orgorient > 0.0) {
07543         
07544         
07545         
07546         
07547         
07548         moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
07549                    (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
07550       } else {
07551         moveleft = 1;
07552       }
07553     } else {
07554       if (orgorient > 0.0) {
07555         moveleft = 0;
07556       } else {
07557         
07558         
07559         if (destorient == 0.0) {
07560           lprevself(*searchtri);
07561           return ONEDGE;
07562         }
07563         if (orgorient == 0.0) {
07564           lnextself(*searchtri);
07565           return ONEDGE;
07566         }
07567         return INTRIANGLE;
07568       }
07569     }
07570 
07571     
07572     
07573     
07574     if (moveleft) {
07575       lprev(*searchtri, backtracktri);
07576       fdest = fapex;
07577     } else {
07578       lnext(*searchtri, backtracktri);
07579       forg = fapex;
07580     }
07581     sym(backtracktri, *searchtri);
07582 
07583     if (m->checksegments && stopatsubsegment) {
07584       
07585       tspivot(backtracktri, checkedge);
07586       if (checkedge.ss != m->dummysub) {
07587         
07588         otricopy(backtracktri, *searchtri);
07589         return OUTSIDE;
07590       }
07591     }
07592     
07593     if (searchtri->tri == m->dummytri) {
07594       
07595       otricopy(backtracktri, *searchtri);
07596       return OUTSIDE;
07597     }
07598 
07599     apex(*searchtri, fapex);
07600   }
07601 }
07602 
07603 
07604 
07605 
07606 
07607 
07608 
07609 
07610 
07611 
07612 
07613 
07614 
07615 
07616 
07617 
07618 
07619 
07620 
07621 
07622 
07623 
07624 
07625 
07626 
07627 
07628 
07629 
07630 
07631 
07632 
07633 
07634 
07635 
07636 
07637 
07638 
07639 #ifdef ANSI_DECLARATORS
07640 enum locateresult locate(struct mesh *m, struct behavior *b,
07641                          vertex searchpoint, struct otri *searchtri)
07642 #else 
07643 enum locateresult locate(m, b, searchpoint, searchtri)
07644 struct mesh *m;
07645 struct behavior *b;
07646 vertex searchpoint;
07647 struct otri *searchtri;
07648 #endif 
07649 
07650 {
07651   VOID **sampleblock;
07652   char *firsttri;
07653   struct otri sampletri;
07654   vertex torg, tdest;
07655   unsigned long alignptr;
07656   REAL searchdist, dist;
07657   REAL ahead;
07658   long samplesperblock, totalsamplesleft, samplesleft;
07659   long population, totalpopulation;
07660   triangle ptr;                         
07661 
07662   if (b->verbose > 2) {
07663     printf("  Randomly sampling for a triangle near point (%.12g, %.12g).\n",
07664            searchpoint[0], searchpoint[1]);
07665   }
07666   
07667   
07668   org(*searchtri, torg);
07669   searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07670                (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07671   if (b->verbose > 2) {
07672     printf("    Boundary triangle has origin (%.12g, %.12g).\n",
07673            torg[0], torg[1]);
07674   }
07675 
07676   
07677   
07678   if (m->recenttri.tri != (triangle *) NULL) {
07679     if (!deadtri(m->recenttri.tri)) {
07680       org(m->recenttri, torg);
07681       if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07682         otricopy(m->recenttri, *searchtri);
07683         return ONVERTEX;
07684       }
07685       dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07686              (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07687       if (dist < searchdist) {
07688         otricopy(m->recenttri, *searchtri);
07689         searchdist = dist;
07690         if (b->verbose > 2) {
07691           printf("    Choosing recent triangle with origin (%.12g, %.12g).\n",
07692                  torg[0], torg[1]);
07693         }
07694       }
07695     }
07696   }
07697 
07698   
07699   
07700   
07701   
07702   while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
07703          m->triangles.items) {
07704     m->samples++;
07705   }
07706 
07707   
07708   
07709   
07710   
07711   samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
07712   
07713   
07714   samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
07715                 m->triangles.maxitems + 1;
07716   totalsamplesleft = m->samples;
07717   population = m->triangles.itemsfirstblock;
07718   totalpopulation = m->triangles.maxitems;
07719   sampleblock = m->triangles.firstblock;
07720   sampletri.orient = 0;
07721   while (totalsamplesleft > 0) {
07722     
07723     if (population > totalpopulation) {
07724       population = totalpopulation;
07725     }
07726     
07727     alignptr = (unsigned long) (sampleblock + 1);
07728     firsttri = (char *) (alignptr +
07729                          (unsigned long) m->triangles.alignbytes -
07730                          (alignptr %
07731                           (unsigned long) m->triangles.alignbytes));
07732 
07733     
07734     do {
07735       sampletri.tri = (triangle *) (firsttri +
07736                                     (randomnation((unsigned int) population) *
07737                                      m->triangles.itembytes));
07738       if (!deadtri(sampletri.tri)) {
07739         org(sampletri, torg);
07740         dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07741                (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07742         if (dist < searchdist) {
07743           otricopy(sampletri, *searchtri);
07744           searchdist = dist;
07745           if (b->verbose > 2) {
07746             printf("    Choosing triangle with origin (%.12g, %.12g).\n",
07747                    torg[0], torg[1]);
07748           }
07749         }
07750       }
07751 
07752       samplesleft--;
07753       totalsamplesleft--;
07754     } while ((samplesleft > 0) && (totalsamplesleft > 0));
07755 
07756     if (totalsamplesleft > 0) {
07757       sampleblock = (VOID **) *sampleblock;
07758       samplesleft = samplesperblock;
07759       totalpopulation -= population;
07760       population = TRIPERBLOCK;
07761     }
07762   }
07763 
07764   
07765   org(*searchtri, torg);
07766   dest(*searchtri, tdest);
07767   
07768   if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07769     return ONVERTEX;
07770   }
07771   if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
07772     lnextself(*searchtri);
07773     return ONVERTEX;
07774   }
07775   
07776   ahead = counterclockwise(m, b, torg, tdest, searchpoint);
07777   if (ahead < 0.0) {
07778     
07779     
07780     symself(*searchtri);
07781   } else if (ahead == 0.0) {
07782     
07783     if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
07784         ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
07785       return ONEDGE;
07786     }
07787   }
07788   return preciselocate(m, b, searchpoint, searchtri, 0);
07789 }
07790 
07793 
07794 
07795 
07799 
07800 
07801 
07802 
07803 
07804 
07805 
07806 
07807 
07808 
07809 
07810 #ifdef ANSI_DECLARATORS
07811 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
07812                   int subsegmark)
07813 #else 
07814 void insertsubseg(m, b, tri, subsegmark)
07815 struct mesh *m;
07816 struct behavior *b;
07817 struct otri *tri;             
07818 int subsegmark;                            
07819 #endif 
07820 
07821 {
07822   struct otri oppotri;
07823   struct osub newsubseg;
07824   vertex triorg, tridest;
07825   triangle ptr;                         
07826   subseg sptr;                      
07827 
07828   org(*tri, triorg);
07829   dest(*tri, tridest);
07830   
07831   if (vertexmark(triorg) == 0) {
07832     setvertexmark(triorg, subsegmark);
07833   }
07834   if (vertexmark(tridest) == 0) {
07835     setvertexmark(tridest, subsegmark);
07836   }
07837   
07838   tspivot(*tri, newsubseg);
07839   if (newsubseg.ss == m->dummysub) {
07840     
07841     makesubseg(m, &newsubseg);
07842     setsorg(newsubseg, tridest);
07843     setsdest(newsubseg, triorg);
07844     setsegorg(newsubseg, tridest);
07845     setsegdest(newsubseg, triorg);
07846     
07847     
07848     
07849     
07850     tsbond(*tri, newsubseg);
07851     sym(*tri, oppotri);
07852     ssymself(newsubseg);
07853     tsbond(oppotri, newsubseg);
07854     setmark(newsubseg, subsegmark);
07855     if (b->verbose > 2) {
07856       printf("  Inserting new ");
07857       printsubseg(m, b, &newsubseg);
07858     }
07859   } else {
07860     if (mark(newsubseg) == 0) {
07861       setmark(newsubseg, subsegmark);
07862     }
07863   }
07864 }
07865 
07866 
07867 
07868 
07869 
07870 
07871 
07872 
07873 
07874 
07875 
07876 
07877 
07878 
07879 
07880 
07881 
07882 
07883 
07884 
07885 
07886 
07887 
07888 
07889 
07890 
07891 
07892 
07893 
07894 
07895 
07896 
07897 
07898 
07899 
07900 
07901 
07902 
07903 
07904 
07905 
07906 
07907 
07908 
07909 
07910 
07911 
07912 
07913 
07914 #ifdef ANSI_DECLARATORS
07915 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
07916 #else 
07917 void flip(m, b, flipedge)
07918 struct mesh *m;
07919 struct behavior *b;
07920 struct otri *flipedge;                    
07921 #endif 
07922 
07923 {
07924   struct otri botleft, botright;
07925   struct otri topleft, topright;
07926   struct otri top;
07927   struct otri botlcasing, botrcasing;
07928   struct otri toplcasing, toprcasing;
07929   struct osub botlsubseg, botrsubseg;
07930   struct osub toplsubseg, toprsubseg;
07931   vertex leftvertex, rightvertex, botvertex;
07932   vertex farvertex;
07933   triangle ptr;                         
07934   subseg sptr;                      
07935 
07936   
07937   org(*flipedge, rightvertex);
07938   dest(*flipedge, leftvertex);
07939   apex(*flipedge, botvertex);
07940   sym(*flipedge, top);
07941 #ifdef SELF_CHECK
07942   if (top.tri == m->dummytri) {
07943     printf("Internal error in flip():  Attempt to flip on boundary.\n");
07944     lnextself(*flipedge);
07945     return;
07946   }
07947   if (m->checksegments) {
07948     tspivot(*flipedge, toplsubseg);
07949     if (toplsubseg.ss != m->dummysub) {
07950       printf("Internal error in flip():  Attempt to flip a segment.\n");
07951       lnextself(*flipedge);
07952       return;
07953     }
07954   }
07955 #endif 
07956   apex(top, farvertex);
07957 
07958   
07959   lprev(top, topleft);
07960   sym(topleft, toplcasing);
07961   lnext(top, topright);
07962   sym(topright, toprcasing);
07963   lnext(*flipedge, botleft);
07964   sym(botleft, botlcasing);
07965   lprev(*flipedge, botright);
07966   sym(botright, botrcasing);
07967   
07968   bond(topleft, botlcasing);
07969   bond(botleft, botrcasing);
07970   bond(botright, toprcasing);
07971   bond(topright, toplcasing);
07972 
07973   if (m->checksegments) {
07974     
07975     tspivot(topleft, toplsubseg);
07976     tspivot(botleft, botlsubseg);
07977     tspivot(botright, botrsubseg);
07978     tspivot(topright, toprsubseg);
07979     if (toplsubseg.ss == m->dummysub) {
07980       tsdissolve(topright);
07981     } else {
07982       tsbond(topright, toplsubseg);
07983     }
07984     if (botlsubseg.ss == m->dummysub) {
07985       tsdissolve(topleft);
07986     } else {
07987       tsbond(topleft, botlsubseg);
07988     }
07989     if (botrsubseg.ss == m->dummysub) {
07990       tsdissolve(botleft);
07991     } else {
07992       tsbond(botleft, botrsubseg);
07993     }
07994     if (toprsubseg.ss == m->dummysub) {
07995       tsdissolve(botright);
07996     } else {
07997       tsbond(botright, toprsubseg);
07998     }
07999   }
08000 
08001   
08002   setorg(*flipedge, farvertex);
08003   setdest(*flipedge, botvertex);
08004   setapex(*flipedge, rightvertex);
08005   setorg(top, botvertex);
08006   setdest(top, farvertex);
08007   setapex(top, leftvertex);
08008   if (b->verbose > 2) {
08009     printf("  Edge flip results in left ");
08010     printtriangle(m, b, &top);
08011     printf("  and right ");
08012     printtriangle(m, b, flipedge);
08013   }
08014 }
08015 
08016 
08017 
08018 
08019 
08020 
08021 
08022 
08023 
08024 
08025 
08026 
08027 
08028 
08029 
08030 
08031 
08032 
08033 
08034 
08035 
08036 
08037 
08038 
08039 
08040 
08041 
08042 
08043 
08044 
08045 
08046 
08047 
08048 
08049 #ifdef ANSI_DECLARATORS
08050 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
08051 #else 
08052 void unflip(m, b, flipedge)
08053 struct mesh *m;
08054 struct behavior *b;
08055 struct otri *flipedge;                    
08056 #endif 
08057 
08058 {
08059   struct otri botleft, botright;
08060   struct otri topleft, topright;
08061   struct otri top;
08062   struct otri botlcasing, botrcasing;
08063   struct otri toplcasing, toprcasing;
08064   struct osub botlsubseg, botrsubseg;
08065   struct osub toplsubseg, toprsubseg;
08066   vertex leftvertex, rightvertex, botvertex;
08067   vertex farvertex;
08068   triangle ptr;                         
08069   subseg sptr;                      
08070 
08071   
08072   org(*flipedge, rightvertex);
08073   dest(*flipedge, leftvertex);
08074   apex(*flipedge, botvertex);
08075   sym(*flipedge, top);
08076 #ifdef SELF_CHECK
08077   if (top.tri == m->dummytri) {
08078     printf("Internal error in unflip():  Attempt to flip on boundary.\n");
08079     lnextself(*flipedge);
08080     return;
08081   }
08082   if (m->checksegments) {
08083     tspivot(*flipedge, toplsubseg);
08084     if (toplsubseg.ss != m->dummysub) {
08085       printf("Internal error in unflip():  Attempt to flip a subsegment.\n");
08086       lnextself(*flipedge);
08087       return;
08088     }
08089   }
08090 #endif 
08091   apex(top, farvertex);
08092 
08093   
08094   lprev(top, topleft);
08095   sym(topleft, toplcasing);
08096   lnext(top, topright);
08097   sym(topright, toprcasing);
08098   lnext(*flipedge, botleft);
08099   sym(botleft, botlcasing);
08100   lprev(*flipedge, botright);
08101   sym(botright, botrcasing);
08102   
08103   bond(topleft, toprcasing);
08104   bond(botleft, toplcasing);
08105   bond(botright, botlcasing);
08106   bond(topright, botrcasing);
08107 
08108   if (m->checksegments) {
08109     
08110     tspivot(topleft, toplsubseg);
08111     tspivot(botleft, botlsubseg);
08112     tspivot(botright, botrsubseg);
08113     tspivot(topright, toprsubseg);
08114     if (toplsubseg.ss == m->dummysub) {
08115       tsdissolve(botleft);
08116     } else {
08117       tsbond(botleft, toplsubseg);
08118     }
08119     if (botlsubseg.ss == m->dummysub) {
08120       tsdissolve(botright);
08121     } else {
08122       tsbond(botright, botlsubseg);
08123     }
08124     if (botrsubseg.ss == m->dummysub) {
08125       tsdissolve(topright);
08126     } else {
08127       tsbond(topright, botrsubseg);
08128     }
08129     if (toprsubseg.ss == m->dummysub) {
08130       tsdissolve(topleft);
08131     } else {
08132       tsbond(topleft, toprsubseg);
08133     }
08134   }
08135 
08136   
08137   setorg(*flipedge, botvertex);
08138   setdest(*flipedge, farvertex);
08139   setapex(*flipedge, leftvertex);
08140   setorg(top, farvertex);
08141   setdest(top, botvertex);
08142   setapex(top, rightvertex);
08143   if (b->verbose > 2) {
08144     printf("  Edge unflip results in left ");
08145     printtriangle(m, b, flipedge);
08146     printf("  and right ");
08147     printtriangle(m, b, &top);
08148   }
08149 }
08150 
08151 
08152 
08153 
08154 
08155 
08156 
08157 
08158 
08159 
08160 
08161 
08162 
08163 
08164 
08165 
08166 
08167 
08168 
08169 
08170 
08171 
08172 
08173 
08174 
08175 
08176 
08177 
08178 
08179 
08180 
08181 
08182 
08183 
08184 
08185 
08186 
08187 
08188 
08189 
08190 
08191 
08192 
08193 
08194 
08195 
08196 
08197 
08198 #ifdef ANSI_DECLARATORS
08199 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
08200                                      vertex newvertex, struct otri *searchtri,
08201                                      struct osub *splitseg,
08202                                      int segmentflaws, int triflaws)
08203 #else 
08204 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
08205                                      segmentflaws, triflaws)
08206 struct mesh *m;
08207 struct behavior *b;
08208 vertex newvertex;
08209 struct otri *searchtri;
08210 struct osub *splitseg;
08211 int segmentflaws;
08212 int triflaws;
08213 #endif 
08214 
08215 {
08216   struct otri horiz;
08217   struct otri top;
08218   struct otri botleft, botright;
08219   struct otri topleft, topright;
08220   struct otri newbotleft, newbotright;
08221   struct otri newtopright;
08222   struct otri botlcasing, botrcasing;
08223   struct otri toplcasing, toprcasing;
08224   struct otri testtri;
08225   struct osub botlsubseg, botrsubseg;
08226   struct osub toplsubseg, toprsubseg;
08227   struct osub brokensubseg;
08228   struct osub checksubseg;
08229   struct osub rightsubseg;
08230   struct osub newsubseg;
08231   struct badsubseg *encroached;
08232   struct flipstacker *newflip;
08233   vertex first;
08234   vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
08235   vertex segmentorg, segmentdest;
08236   REAL attrib;
08237   REAL area;
08238   enum insertvertexresult success;
08239   enum locateresult intersect;
08240   int doflip;
08241   int mirrorflag;
08242   int enq;
08243   int i;
08244   triangle ptr;                         
08245   subseg sptr;         
08246 
08247   if (b->verbose > 1) {
08248     printf("  Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
08249   }
08250 
08251   if (splitseg == (struct osub *) NULL) {
08252     
08253     
08254     if (searchtri->tri == m->dummytri) {
08255       
08256       horiz.tri = m->dummytri;
08257       horiz.orient = 0;
08258       symself(horiz);
08259       
08260       intersect = locate(m, b, newvertex, &horiz);
08261     } else {
08262       
08263       otricopy(*searchtri, horiz);
08264       intersect = preciselocate(m, b, newvertex, &horiz, 1);
08265     }
08266   } else {
08267     
08268     
08269     otricopy(*searchtri, horiz);
08270     intersect = ONEDGE;
08271   }
08272 
08273   if (intersect == ONVERTEX) {
08274     
08275     
08276     otricopy(horiz, *searchtri);
08277     otricopy(horiz, m->recenttri);
08278     return DUPLICATEVERTEX;
08279   }
08280   if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
08281     
08282     if (m->checksegments && (splitseg == (struct osub *) NULL)) {
08283       
08284       tspivot(horiz, brokensubseg);
08285       if (brokensubseg.ss != m->dummysub) {
08286         
08287         if (segmentflaws) {
08288           enq = b->nobisect != 2;
08289           if (enq && (b->nobisect == 1)) {
08290             
08291             
08292             sym(horiz, testtri);
08293             enq = testtri.tri != m->dummytri;
08294           }
08295           if (enq) {
08296             
08297             encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
08298             encroached->encsubseg = sencode(brokensubseg);
08299             sorg(brokensubseg, encroached->subsegorg);
08300             sdest(brokensubseg, encroached->subsegdest);
08301             if (b->verbose > 2) {
08302               printf(
08303           "  Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
08304                      encroached->subsegorg[0], encroached->subsegorg[1],
08305                      encroached->subsegdest[0], encroached->subsegdest[1]);
08306             }
08307           }
08308         }
08309         
08310         
08311         otricopy(horiz, *searchtri);
08312         otricopy(horiz, m->recenttri);
08313         return VIOLATINGVERTEX;
08314       }
08315     }
08316 
08317     
08318     
08319     lprev(horiz, botright);
08320     sym(botright, botrcasing);
08321     sym(horiz, topright);
08322     
08323     mirrorflag = topright.tri != m->dummytri;
08324     if (mirrorflag) {
08325       lnextself(topright);
08326       sym(topright, toprcasing);
08327       maketriangle(m, b, &newtopright);
08328     } else {
08329       
08330       m->hullsize++;
08331     }
08332     maketriangle(m, b, &newbotright);
08333 
08334     
08335     org(horiz, rightvertex);
08336     dest(horiz, leftvertex);
08337     apex(horiz, botvertex);
08338     setorg(newbotright, botvertex);
08339     setdest(newbotright, rightvertex);
08340     setapex(newbotright, newvertex);
08341     setorg(horiz, newvertex);
08342     for (i = 0; i < m->eextras; i++) {
08343       
08344       setelemattribute(newbotright, i, elemattribute(botright, i));
08345     }
08346     if (b->vararea) {
08347       
08348       setareabound(newbotright, areabound(botright));
08349     }
08350     if (mirrorflag) {
08351       dest(topright, topvertex);
08352       setorg(newtopright, rightvertex);
08353       setdest(newtopright, topvertex);
08354       setapex(newtopright, newvertex);
08355       setorg(topright, newvertex);
08356       for (i = 0; i < m->eextras; i++) {
08357         
08358         setelemattribute(newtopright, i, elemattribute(topright, i));
08359       }
08360       if (b->vararea) {
08361         
08362         setareabound(newtopright, areabound(topright));
08363       }
08364     }
08365 
08366     
08367     
08368     if (m->checksegments) {
08369       tspivot(botright, botrsubseg);
08370       if (botrsubseg.ss != m->dummysub) {
08371         tsdissolve(botright);
08372         tsbond(newbotright, botrsubseg);
08373       }
08374       if (mirrorflag) {
08375         tspivot(topright, toprsubseg);
08376         if (toprsubseg.ss != m->dummysub) {
08377           tsdissolve(topright);
08378           tsbond(newtopright, toprsubseg);
08379         }
08380       }
08381     }
08382 
08383     
08384     bond(newbotright, botrcasing);
08385     lprevself(newbotright);
08386     bond(newbotright, botright);
08387     lprevself(newbotright);
08388     if (mirrorflag) {
08389       bond(newtopright, toprcasing);
08390       lnextself(newtopright);
08391       bond(newtopright, topright);
08392       lnextself(newtopright);
08393       bond(newtopright, newbotright);
08394     }
08395 
08396     if (splitseg != (struct osub *) NULL) {
08397       
08398       setsdest(*splitseg, newvertex);
08399       segorg(*splitseg, segmentorg);
08400       segdest(*splitseg, segmentdest);
08401       ssymself(*splitseg);
08402       spivot(*splitseg, rightsubseg);
08403       insertsubseg(m, b, &newbotright, mark(*splitseg));
08404       tspivot(newbotright, newsubseg);
08405       setsegorg(newsubseg, segmentorg);
08406       setsegdest(newsubseg, segmentdest);
08407       sbond(*splitseg, newsubseg);
08408       ssymself(newsubseg);
08409       sbond(newsubseg, rightsubseg);
08410       ssymself(*splitseg);
08411       
08412       
08413       if (vertexmark(newvertex) == 0) {
08414         setvertexmark(newvertex, mark(*splitseg));
08415       }
08416     }
08417 
08418     if (m->checkquality) {
08419       poolrestart(&m->flipstackers);
08420       m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08421       m->lastflip->flippedtri = encode(horiz);
08422       m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
08423     }
08424 
08425 #ifdef SELF_CHECK
08426     if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08427       printf("Internal error in insertvertex():\n");
08428       printf(
08429             "  Clockwise triangle prior to edge vertex insertion (bottom).\n");
08430     }
08431     if (mirrorflag) {
08432       if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
08433         printf("Internal error in insertvertex():\n");
08434         printf("  Clockwise triangle prior to edge vertex insertion (top).\n");
08435       }
08436       if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
08437         printf("Internal error in insertvertex():\n");
08438         printf(
08439             "  Clockwise triangle after edge vertex insertion (top right).\n");
08440       }
08441       if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
08442         printf("Internal error in insertvertex():\n");
08443         printf(
08444             "  Clockwise triangle after edge vertex insertion (top left).\n");
08445       }
08446     }
08447     if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08448       printf("Internal error in insertvertex():\n");
08449       printf(
08450           "  Clockwise triangle after edge vertex insertion (bottom left).\n");
08451     }
08452     if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08453       printf("Internal error in insertvertex():\n");
08454       printf(
08455         "  Clockwise triangle after edge vertex insertion (bottom right).\n");
08456     }
08457 #endif 
08458     if (b->verbose > 2) {
08459       printf("  Updating bottom left ");
08460       printtriangle(m, b, &botright);
08461       if (mirrorflag) {
08462         printf("  Updating top left ");
08463         printtriangle(m, b, &topright);
08464         printf("  Creating top right ");
08465         printtriangle(m, b, &newtopright);
08466       }
08467       printf("  Creating bottom right ");
08468       printtriangle(m, b, &newbotright);
08469     }
08470 
08471     
08472     
08473     lnextself(horiz);
08474   } else {
08475     
08476     lnext(horiz, botleft);
08477     lprev(horiz, botright);
08478     sym(botleft, botlcasing);
08479     sym(botright, botrcasing);
08480     maketriangle(m, b, &newbotleft);
08481     maketriangle(m, b, &newbotright);
08482 
08483     
08484     org(horiz, rightvertex);
08485     dest(horiz, leftvertex);
08486     apex(horiz, botvertex);
08487     setorg(newbotleft, leftvertex);
08488     setdest(newbotleft, botvertex);
08489     setapex(newbotleft, newvertex);
08490     setorg(newbotright, botvertex);
08491     setdest(newbotright, rightvertex);
08492     setapex(newbotright, newvertex);
08493     setapex(horiz, newvertex);
08494     for (i = 0; i < m->eextras; i++) {
08495       
08496       attrib = elemattribute(horiz, i);
08497       setelemattribute(newbotleft, i, attrib);
08498       setelemattribute(newbotright, i, attrib);
08499     }
08500     if (b->vararea) {
08501       
08502       area = areabound(horiz);
08503       setareabound(newbotleft, area);
08504       setareabound(newbotright, area);
08505     }
08506 
08507     
08508     
08509     if (m->checksegments) {
08510       tspivot(botleft, botlsubseg);
08511       if (botlsubseg.ss != m->dummysub) {
08512         tsdissolve(botleft);
08513         tsbond(newbotleft, botlsubseg);
08514       }
08515       tspivot(botright, botrsubseg);
08516       if (botrsubseg.ss != m->dummysub) {
08517         tsdissolve(botright);
08518         tsbond(newbotright, botrsubseg);
08519       }
08520     }
08521 
08522     
08523     bond(newbotleft, botlcasing);
08524     bond(newbotright, botrcasing);
08525     lnextself(newbotleft);
08526     lprevself(newbotright);
08527     bond(newbotleft, newbotright);
08528     lnextself(newbotleft);
08529     bond(botleft, newbotleft);
08530     lprevself(newbotright);
08531     bond(botright, newbotright);
08532 
08533     if (m->checkquality) {
08534       poolrestart(&m->flipstackers);
08535       m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08536       m->lastflip->flippedtri = encode(horiz);
08537       m->lastflip->prevflip = (struct flipstacker *) NULL;
08538     }
08539 
08540 #ifdef SELF_CHECK
08541     if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08542       printf("Internal error in insertvertex():\n");
08543       printf("  Clockwise triangle prior to vertex insertion.\n");
08544     }
08545     if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
08546       printf("Internal error in insertvertex():\n");
08547       printf("  Clockwise triangle after vertex insertion (top).\n");
08548     }
08549     if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08550       printf("Internal error in insertvertex():\n");
08551       printf("  Clockwise triangle after vertex insertion (left).\n");
08552     }
08553     if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08554       printf("Internal error in insertvertex():\n");
08555       printf("  Clockwise triangle after vertex insertion (right).\n");
08556     }
08557 #endif 
08558     if (b->verbose > 2) {
08559       printf("  Updating top ");
08560       printtriangle(m, b, &horiz);
08561       printf("  Creating left ");
08562       printtriangle(m, b, &newbotleft);
08563       printf("  Creating right ");
08564       printtriangle(m, b, &newbotright);
08565     }
08566   }
08567 
08568   
08569   
08570   success = SUCCESSFULVERTEX;
08571   
08572   
08573   
08574   
08575   org(horiz, first);
08576   rightvertex = first;
08577   dest(horiz, leftvertex);
08578   
08579   while (1) {
08580     
08581     doflip = 1;
08582 
08583     if (m->checksegments) {
08584       
08585       tspivot(horiz, checksubseg);
08586       if (checksubseg.ss != m->dummysub) {
08587         
08588         doflip = 0;
08589 #ifndef CDT_ONLY
08590         if (segmentflaws) {
08591           
08592           if (checkseg4encroach(m, b, &checksubseg)) {
08593             success = ENCROACHINGVERTEX;
08594           }
08595         }
08596 #endif 
08597       }
08598     }
08599 
08600     if (doflip) {
08601       
08602       sym(horiz, top);
08603       if (top.tri == m->dummytri) {
08604         
08605         doflip = 0;
08606       } else {
08607         
08608         apex(top, farvertex);
08609         
08610         
08611         
08612         
08613         
08614         if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
08615             (leftvertex == m->infvertex3)) {
08616           
08617           
08618           
08619           
08620           doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
08621                    > 0.0;
08622         } else if ((rightvertex == m->infvertex1) ||
08623                    (rightvertex == m->infvertex2) ||
08624                    (rightvertex == m->infvertex3)) {
08625           
08626           
08627           
08628           
08629           doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
08630                    > 0.0;
08631         } else if ((farvertex == m->infvertex1) ||
08632                    (farvertex == m->infvertex2) ||
08633                    (farvertex == m->infvertex3)) {
08634           
08635           
08636           doflip = 0;
08637         } else {
08638           
08639           doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
08640                             farvertex) > 0.0;
08641         }
08642         if (doflip) {
08643           
08644           
08645           
08646           lprev(top, topleft);
08647           sym(topleft, toplcasing);
08648           lnext(top, topright);
08649           sym(topright, toprcasing);
08650           lnext(horiz, botleft);
08651           sym(botleft, botlcasing);
08652           lprev(horiz, botright);
08653           sym(botright, botrcasing);
08654           
08655           bond(topleft, botlcasing);
08656           bond(botleft, botrcasing);
08657           bond(botright, toprcasing);
08658           bond(topright, toplcasing);
08659           if (m->checksegments) {
08660             
08661             tspivot(topleft, toplsubseg);
08662             tspivot(botleft, botlsubseg);
08663             tspivot(botright, botrsubseg);
08664             tspivot(topright, toprsubseg);
08665             if (toplsubseg.ss == m->dummysub) {
08666               tsdissolve(topright);
08667             } else {
08668               tsbond(topright, toplsubseg);
08669             }
08670             if (botlsubseg.ss == m->dummysub) {
08671               tsdissolve(topleft);
08672             } else {
08673               tsbond(topleft, botlsubseg);
08674             }
08675             if (botrsubseg.ss == m->dummysub) {
08676               tsdissolve(botleft);
08677             } else {
08678               tsbond(botleft, botrsubseg);
08679             }
08680             if (toprsubseg.ss == m->dummysub) {
08681               tsdissolve(botright);
08682             } else {
08683               tsbond(botright, toprsubseg);
08684             }
08685           }
08686           
08687           setorg(horiz, farvertex);
08688           setdest(horiz, newvertex);
08689           setapex(horiz, rightvertex);
08690           setorg(top, newvertex);
08691           setdest(top, farvertex);
08692           setapex(top, leftvertex);
08693           for (i = 0; i < m->eextras; i++) {
08694             
08695             attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
08696             setelemattribute(top, i, attrib);
08697             setelemattribute(horiz, i, attrib);
08698           }
08699           if (b->vararea) {
08700             if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
08701               area = -1.0;
08702             } else {
08703               
08704               
08705               
08706               area = 0.5 * (areabound(top) + areabound(horiz));
08707             }
08708             setareabound(top, area);
08709             setareabound(horiz, area);
08710           }
08711 
08712           if (m->checkquality) {
08713             newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08714             newflip->flippedtri = encode(horiz);
08715             newflip->prevflip = m->lastflip;
08716             m->lastflip = newflip;
08717           }
08718 
08719 #ifdef SELF_CHECK
08720           if (newvertex != (vertex) NULL) {
08721             if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
08722                 0.0) {
08723               printf("Internal error in insertvertex():\n");
08724               printf("  Clockwise triangle prior to edge flip (bottom).\n");
08725             }
08726             
08727             
08728             
08729 
08730 
08731 
08732 
08733 
08734 
08735 
08736             if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
08737                 0.0) {
08738               printf("Internal error in insertvertex():\n");
08739               printf("  Clockwise triangle after edge flip (left).\n");
08740             }
08741             if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
08742                 0.0) {
08743               printf("Internal error in insertvertex():\n");
08744               printf("  Clockwise triangle after edge flip (right).\n");
08745             }
08746           }
08747 #endif 
08748           if (b->verbose > 2) {
08749             printf("  Edge flip results in left ");
08750             lnextself(topleft);
08751             printtriangle(m, b, &topleft);
08752             printf("  and right ");
08753             printtriangle(m, b, &horiz);
08754           }
08755           
08756           
08757           
08758           lprevself(horiz);
08759           leftvertex = farvertex;
08760         }
08761       }
08762     }
08763     if (!doflip) {
08764       
08765 #ifndef CDT_ONLY
08766       if (triflaws) {
08767         
08768         testtriangle(m, b, &horiz);
08769       }
08770 #endif 
08771       
08772       lnextself(horiz);
08773       sym(horiz, testtri);
08774       
08775       
08776       
08777       if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
08778         
08779         lnext(horiz, *searchtri);
08780         lnext(horiz, m->recenttri);
08781         return success;
08782       }
08783       
08784       lnext(testtri, horiz);
08785       rightvertex = leftvertex;
08786       dest(horiz, leftvertex);
08787     }
08788   }
08789 }
08790 
08791 
08792 
08793 
08794 
08795 
08796 
08797 
08798 
08799 
08800 
08801 
08802 
08803 
08804 
08805 
08806 
08807 
08808 
08809 
08810 
08811 
08812 
08813 
08814 
08815 
08816 
08817 
08818 
08819 
08820 
08821 
08822 
08823 
08824 
08825 
08826 
08827 
08828 
08829 
08830 
08831 
08832 
08833 
08834 
08835 
08836 
08837 
08838 
08839 
08840 
08841 
08842 
08843 
08844 
08845 
08846 
08847 
08848 
08849 
08850 
08851 
08852 
08853 
08854 
08855 #ifdef ANSI_DECLARATORS
08856 void triangulatepolygon(struct mesh *m, struct behavior *b,
08857                         struct otri *firstedge, struct otri *lastedge,
08858                         int edgecount, int doflip, int triflaws)
08859 #else 
08860 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
08861 struct mesh *m;
08862 struct behavior *b;
08863 struct otri *firstedge;
08864 struct otri *lastedge;
08865 int edgecount;
08866 int doflip;
08867 int triflaws;
08868 #endif 
08869 
08870 {
08871   struct otri testtri;
08872   struct otri besttri;
08873   struct otri tempedge;
08874   vertex leftbasevertex, rightbasevertex;
08875   vertex testvertex;
08876   vertex bestvertex;
08877   int bestnumber;
08878   int i;
08879   triangle ptr;   
08880 
08881   
08882   apex(*lastedge, leftbasevertex);
08883   dest(*firstedge, rightbasevertex);
08884   if (b->verbose > 2) {
08885     printf("  Triangulating interior polygon at edge\n");
08886     printf("    (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
08887            leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
08888   }
08889   
08890   onext(*firstedge, besttri);
08891   dest(besttri, bestvertex);
08892   otricopy(besttri, testtri);
08893   bestnumber = 1;
08894   for (i = 2; i <= edgecount - 2; i++) {
08895     onextself(testtri);
08896     dest(testtri, testvertex);
08897     
08898     if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
08899                  testvertex) > 0.0) {
08900       otricopy(testtri, besttri);
08901       bestvertex = testvertex;
08902       bestnumber = i;
08903     }
08904   }
08905   if (b->verbose > 2) {
08906     printf("    Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
08907            bestvertex[1]);
08908   }
08909   if (bestnumber > 1) {
08910     
08911     oprev(besttri, tempedge);
08912     triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
08913                        triflaws);
08914   }
08915   if (bestnumber < edgecount - 2) {
08916     
08917     sym(besttri, tempedge);
08918     triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
08919                        triflaws);
08920     
08921     sym(tempedge, besttri);
08922   }
08923   if (doflip) {
08924     
08925     flip(m, b, &besttri);
08926 #ifndef CDT_ONLY
08927     if (triflaws) {
08928       
08929       sym(besttri, testtri);
08930       testtriangle(m, b, &testtri);
08931     }
08932 #endif 
08933   }
08934   
08935   otricopy(besttri, *lastedge);
08936 }
08937 
08938 
08939 
08940 
08941 
08942 
08943 
08944 
08945 
08946 
08947 
08948 
08949 
08950 
08951 
08952 #ifndef CDT_ONLY
08953 
08954 #ifdef ANSI_DECLARATORS
08955 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
08956 #else 
08957 void deletevertex(m, b, deltri)
08958 struct mesh *m;
08959 struct behavior *b;
08960 struct otri *deltri;
08961 #endif 
08962 
08963 {
08964   struct otri countingtri;
08965   struct otri firstedge, lastedge;
08966   struct otri deltriright;
08967   struct otri lefttri, righttri;
08968   struct otri leftcasing, rightcasing;
08969   struct osub leftsubseg, rightsubseg;
08970   vertex delvertex;
08971   vertex neworg;
08972   int edgecount;
08973   triangle ptr;   
08974   subseg sptr;                      
08975 
08976   org(*deltri, delvertex);
08977   if (b->verbose > 1) {
08978     printf("  Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
08979   }
08980   vertexdealloc(m, delvertex);
08981 
08982   
08983   onext(*deltri, countingtri);
08984   edgecount = 1;
08985   while (!otriequal(*deltri, countingtri)) {
08986 #ifdef SELF_CHECK
08987     if (countingtri.tri == m->dummytri) {
08988       printf("Internal error in deletevertex():\n");
08989       printf("  Attempt to delete boundary vertex.\n");
08990       internalerror();
08991     }
08992 #endif 
08993     edgecount++;
08994     onextself(countingtri);
08995   }
08996 
08997 #ifdef SELF_CHECK
08998   if (edgecount < 3) {
08999     printf("Internal error in deletevertex():\n  Vertex has degree %d.\n",
09000            edgecount);
09001     internalerror();
09002   }
09003 #endif 
09004   if (edgecount > 3) {
09005     
09006     
09007     
09008     onext(*deltri, firstedge);
09009     oprev(*deltri, lastedge);
09010     triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
09011                        !b->nobisect);
09012   }
09013   
09014   lprev(*deltri, deltriright);
09015   dnext(*deltri, lefttri);
09016   sym(lefttri, leftcasing);
09017   oprev(deltriright, righttri);
09018   sym(righttri, rightcasing);
09019   bond(*deltri, leftcasing);
09020   bond(deltriright, rightcasing);
09021   tspivot(lefttri, leftsubseg);
09022   if (leftsubseg.ss != m->dummysub) {
09023     tsbond(*deltri, leftsubseg);
09024   }
09025   tspivot(righttri, rightsubseg);
09026   if (rightsubseg.ss != m->dummysub) {
09027     tsbond(deltriright, rightsubseg);
09028   }
09029 
09030   
09031   org(lefttri, neworg);
09032   setorg(*deltri, neworg);
09033   if (!b->nobisect) {
09034     testtriangle(m, b, deltri);
09035   }
09036 
09037   
09038   triangledealloc(m, lefttri.tri);
09039   triangledealloc(m, righttri.tri);
09040 }
09041 
09042 #endif 
09043 
09044 
09045 
09046 
09047 
09048 
09049 
09050 
09051 
09052 
09053 
09054 
09055 #ifndef CDT_ONLY
09056 
09057 #ifdef ANSI_DECLARATORS
09058 void undovertex(struct mesh *m, struct behavior *b)
09059 #else 
09060 void undovertex(m, b)
09061 struct mesh *m;
09062 struct behavior *b;
09063 #endif 
09064 
09065 {
09066   struct otri fliptri;
09067   struct otri botleft, botright, topright;
09068   struct otri botlcasing, botrcasing, toprcasing;
09069   struct otri gluetri;
09070   struct osub botlsubseg, botrsubseg, toprsubseg;
09071   vertex botvertex, rightvertex;
09072   triangle ptr;                         
09073   subseg sptr;                      
09074 
09075   
09076   
09077   while (m->lastflip != (struct flipstacker *) NULL) {
09078     
09079     decode(m->lastflip->flippedtri, fliptri);
09080 
09081     
09082     
09083     
09084     
09085     if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
09086       
09087       
09088       dprev(fliptri, botleft);
09089       lnextself(botleft);
09090       onext(fliptri, botright);
09091       lprevself(botright);
09092       sym(botleft, botlcasing);
09093       sym(botright, botrcasing);
09094       dest(botleft, botvertex);
09095 
09096       setapex(fliptri, botvertex);
09097       lnextself(fliptri);
09098       bond(fliptri, botlcasing);
09099       tspivot(botleft, botlsubseg);
09100       tsbond(fliptri, botlsubseg);
09101       lnextself(fliptri);
09102       bond(fliptri, botrcasing);
09103       tspivot(botright, botrsubseg);
09104       tsbond(fliptri, botrsubseg);
09105 
09106       
09107       triangledealloc(m, botleft.tri);
09108       triangledealloc(m, botright.tri);
09109     } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
09110       
09111       
09112       lprev(fliptri, gluetri);
09113       sym(gluetri, botright);
09114       lnextself(botright);
09115       sym(botright, botrcasing);
09116       dest(botright, rightvertex);
09117 
09118       setorg(fliptri, rightvertex);
09119       bond(gluetri, botrcasing);
09120       tspivot(botright, botrsubseg);
09121       tsbond(gluetri, botrsubseg);
09122 
09123       
09124       triangledealloc(m, botright.tri);
09125 
09126       sym(fliptri, gluetri);
09127       if (gluetri.tri != m->dummytri) {
09128         lnextself(gluetri);
09129         dnext(gluetri, topright);
09130         sym(topright, toprcasing);
09131 
09132         setorg(gluetri, rightvertex);
09133         bond(gluetri, toprcasing);
09134         tspivot(topright, toprsubseg);
09135         tsbond(gluetri, toprsubseg);
09136 
09137         
09138         triangledealloc(m, topright.tri);
09139       }
09140 
09141       
09142       m->lastflip->prevflip = (struct flipstacker *) NULL;
09143     } else {
09144       
09145       unflip(m, b, &fliptri);
09146     }
09147 
09148     
09149     m->lastflip = m->lastflip->prevflip;
09150   }
09151 }
09152 
09153 #endif 
09154 
09157 
09158 
09159 
09163 
09164 
09165 
09166 
09167 
09168 
09169 
09170 
09171 
09172 
09173 
09174 
09175 
09176 
09177 
09178 
09179 
09180 
09181 
09182 
09183 
09184 
09185 
09186 
09187 
09188 
09189 
09190 
09191 
09192 
09193 
09194 
09195 
09196 
09197 
09198 
09199 
09200 
09201 
09202 
09203 
09204 #ifdef ANSI_DECLARATORS
09205 void vertexsort(vertex *sortarray, int arraysize)
09206 #else 
09207 void vertexsort(sortarray, arraysize)
09208 vertex *sortarray;
09209 int arraysize;
09210 #endif 
09211 
09212 {
09213   int left, right;
09214   int pivot;
09215   REAL pivotx, pivoty;
09216   vertex temp;
09217 
09218   if (arraysize == 2) {
09219     
09220     if ((sortarray[0][0] > sortarray[1][0]) ||
09221         ((sortarray[0][0] == sortarray[1][0]) &&
09222          (sortarray[0][1] > sortarray[1][1]))) {
09223       temp = sortarray[1];
09224       sortarray[1] = sortarray[0];
09225       sortarray[0] = temp;
09226     }
09227     return;
09228   }
09229   
09230   pivot = (int) randomnation((unsigned int) arraysize);
09231   pivotx = sortarray[pivot][0];
09232   pivoty = sortarray[pivot][1];
09233   
09234   left = -1;
09235   right = arraysize;
09236   while (left < right) {
09237     
09238     do {
09239       left++;
09240     } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
09241                                  ((sortarray[left][0] == pivotx) &&
09242                                   (sortarray[left][1] < pivoty))));
09243     
09244     do {
09245       right--;
09246     } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
09247                                  ((sortarray[right][0] == pivotx) &&
09248                                   (sortarray[right][1] > pivoty))));
09249     if (left < right) {
09250       
09251       temp = sortarray[left];
09252       sortarray[left] = sortarray[right];
09253       sortarray[right] = temp;
09254     }
09255   }
09256   if (left > 1) {
09257     
09258     vertexsort(sortarray, left);
09259   }
09260   if (right < arraysize - 2) {
09261     
09262     vertexsort(&sortarray[right + 1], arraysize - right - 1);
09263   }
09264 }
09265 
09266 
09267 
09268 
09269 
09270 
09271 
09272 
09273 
09274 
09275 
09276 
09277 
09278 #ifdef ANSI_DECLARATORS
09279 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
09280 #else 
09281 void vertexmedian(sortarray, arraysize, median, axis)
09282 vertex *sortarray;
09283 int arraysize;
09284 int median;
09285 int axis;
09286 #endif 
09287 
09288 {
09289   int left, right;
09290   int pivot;
09291   REAL pivot1, pivot2;
09292   vertex temp;
09293 
09294   if (arraysize == 2) {
09295     
09296     if ((sortarray[0][axis] > sortarray[1][axis]) ||
09297         ((sortarray[0][axis] == sortarray[1][axis]) &&
09298          (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
09299       temp = sortarray[1];
09300       sortarray[1] = sortarray[0];
09301       sortarray[0] = temp;
09302     }
09303     return;
09304   }
09305   
09306   pivot = (int) randomnation((unsigned int) arraysize);
09307   pivot1 = sortarray[pivot][axis];
09308   pivot2 = sortarray[pivot][1 - axis];
09309   
09310   left = -1;
09311   right = arraysize;
09312   while (left < right) {
09313     
09314     do {
09315       left++;
09316     } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
09317                                  ((sortarray[left][axis] == pivot1) &&
09318                                   (sortarray[left][1 - axis] < pivot2))));
09319     
09320     do {
09321       right--;
09322     } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
09323                                  ((sortarray[right][axis] == pivot1) &&
09324                                   (sortarray[right][1 - axis] > pivot2))));
09325     if (left < right) {
09326       
09327       temp = sortarray[left];
09328       sortarray[left] = sortarray[right];
09329       sortarray[right] = temp;
09330     }
09331   }
09332   
09333   
09334   if (left > median) {
09335     
09336     vertexmedian(sortarray, left, median, axis);
09337   }
09338   if (right < median - 1) {
09339     
09340     vertexmedian(&sortarray[right + 1], arraysize - right - 1,
09341                  median - right - 1, axis);
09342   }
09343 }
09344 
09345 
09346 
09347 
09348 
09349 
09350 
09351 
09352 
09353 
09354 
09355 
09356 #ifdef ANSI_DECLARATORS
09357 void alternateaxes(vertex *sortarray, int arraysize, int axis)
09358 #else 
09359 void alternateaxes(sortarray, arraysize, axis)
09360 vertex *sortarray;
09361 int arraysize;
09362 int axis;
09363 #endif 
09364 
09365 {
09366   int divider;
09367 
09368   divider = arraysize >> 1;
09369   if (arraysize <= 3) {
09370     
09371     
09372     axis = 0;
09373   }
09374   
09375   vertexmedian(sortarray, arraysize, divider, axis);
09376   
09377   if (arraysize - divider >= 2) {
09378     if (divider >= 2) {
09379       alternateaxes(sortarray, divider, 1 - axis);
09380     }
09381     alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
09382   }
09383 }
09384 
09385 
09386 
09387 
09388 
09389 
09390 
09391 
09392 
09393 
09394 
09395 
09396 
09397 
09398 
09399 
09400 
09401 
09402 
09403 
09404 
09405 
09406 
09407 
09408 
09409 
09410 
09411 
09412 
09413 
09414 
09415 
09416 
09417 
09418 
09419 
09420 #ifdef ANSI_DECLARATORS
09421 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
09422                 struct otri *innerleft, struct otri *innerright,
09423                 struct otri *farright, int axis)
09424 #else 
09425 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
09426 struct mesh *m;
09427 struct behavior *b;
09428 struct otri *farleft;
09429 struct otri *innerleft;
09430 struct otri *innerright;
09431 struct otri *farright;
09432 int axis;
09433 #endif 
09434 
09435 {
09436   struct otri leftcand, rightcand;
09437   struct otri baseedge;
09438   struct otri nextedge;
09439   struct otri sidecasing, topcasing, outercasing;
09440   struct otri checkedge;
09441   vertex innerleftdest;
09442   vertex innerrightorg;
09443   vertex innerleftapex, innerrightapex;
09444   vertex farleftpt, farrightpt;
09445   vertex farleftapex, farrightapex;
09446   vertex lowerleft, lowerright;
09447   vertex upperleft, upperright;
09448   vertex nextapex;
09449   vertex checkvertex;
09450   int changemade;
09451   int badedge;
09452   int leftfinished, rightfinished;
09453   triangle ptr;                         
09454 
09455   dest(*innerleft, innerleftdest);
09456   apex(*innerleft, innerleftapex);
09457   org(*innerright, innerrightorg);
09458   apex(*innerright, innerrightapex);
09459   
09460   if (b->dwyer && (axis == 1)) {
09461     org(*farleft, farleftpt);
09462     apex(*farleft, farleftapex);
09463     dest(*farright, farrightpt);
09464     apex(*farright, farrightapex);
09465     
09466     
09467     
09468     while (farleftapex[1] < farleftpt[1]) {
09469       lnextself(*farleft);
09470       symself(*farleft);
09471       farleftpt = farleftapex;
09472       apex(*farleft, farleftapex);
09473     }
09474     sym(*innerleft, checkedge);
09475     apex(checkedge, checkvertex);
09476     while (checkvertex[1] > innerleftdest[1]) {
09477       lnext(checkedge, *innerleft);
09478       innerleftapex = innerleftdest;
09479       innerleftdest = checkvertex;
09480       sym(*innerleft, checkedge);
09481       apex(checkedge, checkvertex);
09482     }
09483     while (innerrightapex[1] < innerrightorg[1]) {
09484       lnextself(*innerright);
09485       symself(*innerright);
09486       innerrightorg = innerrightapex;
09487       apex(*innerright, innerrightapex);
09488     }
09489     sym(*farright, checkedge);
09490     apex(checkedge, checkvertex);
09491     while (checkvertex[1] > farrightpt[1]) {
09492       lnext(checkedge, *farright);
09493       farrightapex = farrightpt;
09494       farrightpt = checkvertex;
09495       sym(*farright, checkedge);
09496       apex(checkedge, checkvertex);
09497     }
09498   }
09499   
09500   do {
09501     changemade = 0;
09502     
09503     if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
09504         0.0) {
09505       lprevself(*innerleft);
09506       symself(*innerleft);
09507       innerleftdest = innerleftapex;
09508       apex(*innerleft, innerleftapex);
09509       changemade = 1;
09510     }
09511     
09512     if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
09513         0.0) {
09514       lnextself(*innerright);
09515       symself(*innerright);
09516       innerrightorg = innerrightapex;
09517       apex(*innerright, innerrightapex);
09518       changemade = 1;
09519     }
09520   } while (changemade);
09521   
09522   sym(*innerleft, leftcand);
09523   sym(*innerright, rightcand);
09524   
09525   maketriangle(m, b, &baseedge);
09526   
09527   bond(baseedge, *innerleft);
09528   lnextself(baseedge);
09529   bond(baseedge, *innerright);
09530   lnextself(baseedge);
09531   setorg(baseedge, innerrightorg);
09532   setdest(baseedge, innerleftdest);
09533   
09534   if (b->verbose > 2) {
09535     printf("  Creating base bounding ");
09536     printtriangle(m, b, &baseedge);
09537   }
09538   
09539   org(*farleft, farleftpt);
09540   if (innerleftdest == farleftpt) {
09541     lnext(baseedge, *farleft);
09542   }
09543   dest(*farright, farrightpt);
09544   if (innerrightorg == farrightpt) {
09545     lprev(baseedge, *farright);
09546   }
09547   
09548   lowerleft = innerleftdest;
09549   lowerright = innerrightorg;
09550   
09551   apex(leftcand, upperleft);
09552   apex(rightcand, upperright);
09553   
09554   while (1) {
09555     
09556     
09557     
09558     
09559     leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
09560                    0.0;
09561     rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
09562                  <= 0.0;
09563     if (leftfinished && rightfinished) {
09564       
09565       maketriangle(m, b, &nextedge);
09566       setorg(nextedge, lowerleft);
09567       setdest(nextedge, lowerright);
09568       
09569       
09570       bond(nextedge, baseedge);
09571       lnextself(nextedge);
09572       bond(nextedge, rightcand);
09573       lnextself(nextedge);
09574       bond(nextedge, leftcand);
09575       if (b->verbose > 2) {
09576         printf("  Creating top bounding ");
09577         printtriangle(m, b, &nextedge);
09578       }
09579       
09580       if (b->dwyer && (axis == 1)) {
09581         org(*farleft, farleftpt);
09582         apex(*farleft, farleftapex);
09583         dest(*farright, farrightpt);
09584         apex(*farright, farrightapex);
09585         sym(*farleft, checkedge);
09586         apex(checkedge, checkvertex);
09587         
09588         
09589         
09590         while (checkvertex[0] < farleftpt[0]) {
09591           lprev(checkedge, *farleft);
09592           farleftapex = farleftpt;
09593           farleftpt = checkvertex;
09594           sym(*farleft, checkedge);
09595           apex(checkedge, checkvertex);
09596         }
09597         while (farrightapex[0] > farrightpt[0]) {
09598           lprevself(*farright);
09599           symself(*farright);
09600           farrightpt = farrightapex;
09601           apex(*farright, farrightapex);
09602         }
09603       }
09604       return;
09605     }
09606     
09607     if (!leftfinished) {
09608       
09609       lprev(leftcand, nextedge);
09610       symself(nextedge);
09611       apex(nextedge, nextapex);
09612       
09613       
09614       if (nextapex != (vertex) NULL) {
09615         
09616         badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
09617                   0.0;
09618         while (badedge) {
09619           
09620           
09621           lnextself(nextedge);
09622           sym(nextedge, topcasing);
09623           lnextself(nextedge);
09624           sym(nextedge, sidecasing);
09625           bond(nextedge, topcasing);
09626           bond(leftcand, sidecasing);
09627           lnextself(leftcand);
09628           sym(leftcand, outercasing);
09629           lprevself(nextedge);
09630           bond(nextedge, outercasing);
09631           
09632           setorg(leftcand, lowerleft);
09633           setdest(leftcand, NULL);
09634           setapex(leftcand, nextapex);
09635           setorg(nextedge, NULL);
09636           setdest(nextedge, upperleft);
09637           setapex(nextedge, nextapex);
09638           
09639           upperleft = nextapex;
09640           
09641           otricopy(sidecasing, nextedge);
09642           apex(nextedge, nextapex);
09643           if (nextapex != (vertex) NULL) {
09644             
09645             badedge = incircle(m, b, lowerleft, lowerright, upperleft,
09646                                nextapex) > 0.0;
09647           } else {
09648             
09649             badedge = 0;
09650           }
09651         }
09652       }
09653     }
09654     
09655     if (!rightfinished) {
09656       
09657       lnext(rightcand, nextedge);
09658       symself(nextedge);
09659       apex(nextedge, nextapex);
09660       
09661       
09662       if (nextapex != (vertex) NULL) {
09663         
09664         badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
09665                   0.0;
09666         while (badedge) {
09667           
09668           
09669           lprevself(nextedge);
09670           sym(nextedge, topcasing);
09671           lprevself(nextedge);
09672           sym(nextedge, sidecasing);
09673           bond(nextedge, topcasing);
09674           bond(rightcand, sidecasing);
09675           lprevself(rightcand);
09676           sym(rightcand, outercasing);
09677           lnextself(nextedge);
09678           bond(nextedge, outercasing);
09679           
09680           setorg(rightcand, NULL);
09681           setdest(rightcand, lowerright);
09682           setapex(rightcand, nextapex);
09683           setorg(nextedge, upperright);
09684           setdest(nextedge, NULL);
09685           setapex(nextedge, nextapex);
09686           
09687           upperright = nextapex;
09688           
09689           otricopy(sidecasing, nextedge);
09690           apex(nextedge, nextapex);
09691           if (nextapex != (vertex) NULL) {
09692             
09693             badedge = incircle(m, b, lowerleft, lowerright, upperright,
09694                                nextapex) > 0.0;
09695           } else {
09696             
09697             badedge = 0;
09698           }
09699         }
09700       }
09701     }
09702     if (leftfinished || (!rightfinished &&
09703            (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
09704             0.0))) {
09705       
09706       
09707       bond(baseedge, rightcand);
09708       lprev(rightcand, baseedge);
09709       setdest(baseedge, lowerleft);
09710       lowerright = upperright;
09711       sym(baseedge, rightcand);
09712       apex(rightcand, upperright);
09713     } else {
09714       
09715       
09716       bond(baseedge, leftcand);
09717       lnext(leftcand, baseedge);
09718       setorg(baseedge, lowerright);
09719       lowerleft = upperleft;
09720       sym(baseedge, leftcand);
09721       apex(leftcand, upperleft);
09722     }
09723     if (b->verbose > 2) {
09724       printf("  Connecting ");
09725       printtriangle(m, b, &baseedge);
09726     }
09727   }
09728 }
09729 
09730 
09731 
09732 
09733 
09734 
09735 
09736 
09737 
09738 
09739 
09740 
09741 
09742 
09743 
09744 
09745 
09746 
09747 #ifdef ANSI_DECLARATORS
09748 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
09749                     int vertices, int axis,
09750                     struct otri *farleft, struct otri *farright)
09751 #else 
09752 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
09753 struct mesh *m;
09754 struct behavior *b;
09755 vertex *sortarray;
09756 int vertices;
09757 int axis;
09758 struct otri *farleft;
09759 struct otri *farright;
09760 #endif 
09761 
09762 {
09763   struct otri midtri, tri1, tri2, tri3;
09764   struct otri innerleft, innerright;
09765   REAL area;
09766   int divider;
09767 
09768   if (b->verbose > 2) {
09769     printf("  Triangulating %d vertices.\n", vertices);
09770   }
09771   if (vertices == 2) {
09772     
09773     
09774     maketriangle(m, b, farleft);
09775     setorg(*farleft, sortarray[0]);
09776     setdest(*farleft, sortarray[1]);
09777     
09778     maketriangle(m, b, farright);
09779     setorg(*farright, sortarray[1]);
09780     setdest(*farright, sortarray[0]);
09781     
09782     bond(*farleft, *farright);
09783     lprevself(*farleft);
09784     lnextself(*farright);
09785     bond(*farleft, *farright);
09786     lprevself(*farleft);
09787     lnextself(*farright);
09788     bond(*farleft, *farright);
09789     if (b->verbose > 2) {
09790       printf("  Creating ");
09791       printtriangle(m, b, farleft);
09792       printf("  Creating ");
09793       printtriangle(m, b, farright);
09794     }
09795     
09796     lprev(*farright, *farleft);
09797     return;
09798   } else if (vertices == 3) {
09799     
09800     
09801     
09802     maketriangle(m, b, &midtri);
09803     maketriangle(m, b, &tri1);
09804     maketriangle(m, b, &tri2);
09805     maketriangle(m, b, &tri3);
09806     area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
09807     if (area == 0.0) {
09808       
09809       setorg(midtri, sortarray[0]);
09810       setdest(midtri, sortarray[1]);
09811       setorg(tri1, sortarray[1]);
09812       setdest(tri1, sortarray[0]);
09813       setorg(tri2, sortarray[2]);
09814       setdest(tri2, sortarray[1]);
09815       setorg(tri3, sortarray[1]);
09816       setdest(tri3, sortarray[2]);
09817       
09818       bond(midtri, tri1);
09819       bond(tri2, tri3);
09820       lnextself(midtri);
09821       lprevself(tri1);
09822       lnextself(tri2);
09823       lprevself(tri3);
09824       bond(midtri, tri3);
09825       bond(tri1, tri2);
09826       lnextself(midtri);
09827       lprevself(tri1);
09828       lnextself(tri2);
09829       lprevself(tri3);
09830       bond(midtri, tri1);
09831       bond(tri2, tri3);
09832       
09833       otricopy(tri1, *farleft);
09834       
09835       otricopy(tri2, *farright);
09836     } else {
09837       
09838       
09839       setorg(midtri, sortarray[0]);
09840       setdest(tri1, sortarray[0]);
09841       setorg(tri3, sortarray[0]);
09842       
09843       if (area > 0.0) {
09844         
09845         setdest(midtri, sortarray[1]);
09846         setorg(tri1, sortarray[1]);
09847         setdest(tri2, sortarray[1]);
09848         setapex(midtri, sortarray[2]);
09849         setorg(tri2, sortarray[2]);
09850         setdest(tri3, sortarray[2]);
09851       } else {
09852         
09853         setdest(midtri, sortarray[2]);
09854         setorg(tri1, sortarray[2]);
09855         setdest(tri2, sortarray[2]);
09856         setapex(midtri, sortarray[1]);
09857         setorg(tri2, sortarray[1]);
09858         setdest(tri3, sortarray[1]);
09859       }
09860       
09861       bond(midtri, tri1);
09862       lnextself(midtri);
09863       bond(midtri, tri2);
09864       lnextself(midtri);
09865       bond(midtri, tri3);
09866       lprevself(tri1);
09867       lnextself(tri2);
09868       bond(tri1, tri2);
09869       lprevself(tri1);
09870       lprevself(tri3);
09871       bond(tri1, tri3);
09872       lnextself(tri2);
09873       lprevself(tri3);
09874       bond(tri2, tri3);
09875       
09876       otricopy(tri1, *farleft);
09877       
09878       if (area > 0.0) {
09879         otricopy(tri2, *farright);
09880       } else {
09881         lnext(*farleft, *farright);
09882       }
09883     }
09884     if (b->verbose > 2) {
09885       printf("  Creating ");
09886       printtriangle(m, b, &midtri);
09887       printf("  Creating ");
09888       printtriangle(m, b, &tri1);
09889       printf("  Creating ");
09890       printtriangle(m, b, &tri2);
09891       printf("  Creating ");
09892       printtriangle(m, b, &tri3);
09893     }
09894     return;
09895   } else {
09896     
09897     divider = vertices >> 1;
09898     
09899     divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
09900     divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
09901                    &innerright, farright);
09902     if (b->verbose > 1) {
09903       printf("  Joining triangulations with %d and %d vertices.\n", divider,
09904              vertices - divider);
09905     }
09906     
09907     mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
09908   }
09909 }
09910 
09911 #ifdef ANSI_DECLARATORS
09912 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
09913 #else 
09914 long removeghosts(m, b, startghost)
09915 struct mesh *m;
09916 struct behavior *b;
09917 struct otri *startghost;
09918 #endif 
09919 
09920 {
09921   struct otri searchedge;
09922   struct otri dissolveedge;
09923   struct otri deadtriangle;
09924   vertex markorg;
09925   long hullsize;
09926   triangle ptr;                         
09927 
09928   if (b->verbose) {
09929     printf("  Removing ghost triangles.\n");
09930   }
09931   
09932   lprev(*startghost, searchedge);
09933   symself(searchedge);
09934   m->dummytri[0] = encode(searchedge);
09935   
09936   otricopy(*startghost, dissolveedge);
09937   hullsize = 0;
09938   do {
09939     hullsize++;
09940     lnext(dissolveedge, deadtriangle);
09941     lprevself(dissolveedge);
09942     symself(dissolveedge);
09943     
09944     
09945     if (!b->poly) {
09946       
09947       if (dissolveedge.tri != m->dummytri) {
09948         org(dissolveedge, markorg);
09949         if (vertexmark(markorg) == 0) {
09950           setvertexmark(markorg, 1);
09951         }
09952       }
09953     }
09954     
09955     dissolve(dissolveedge);
09956     
09957     sym(deadtriangle, dissolveedge);
09958     
09959     triangledealloc(m, deadtriangle.tri);
09960   } while (!otriequal(dissolveedge, *startghost));
09961   return hullsize;
09962 }
09963 
09964 
09965 
09966 
09967 
09968 
09969 
09970 
09971 
09972 
09973 
09974 #ifdef ANSI_DECLARATORS
09975 long divconqdelaunay(struct mesh *m, struct behavior *b)
09976 #else 
09977 long divconqdelaunay(m, b)
09978 struct mesh *m;
09979 struct behavior *b;
09980 #endif 
09981 
09982 {
09983   vertex *sortarray;
09984   struct otri hullleft, hullright;
09985   int divider;
09986   int i, j;
09987 
09988   if (b->verbose) {
09989     printf("  Sorting vertices.\n");
09990   }
09991 
09992   
09993   sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
09994   traversalinit(&m->vertices);
09995   for (i = 0; i < m->invertices; i++) {
09996     sortarray[i] = vertextraverse(m);
09997   }
09998   
09999   vertexsort(sortarray, m->invertices);
10000   
10001   i = 0;
10002   for (j = 1; j < m->invertices; j++) {
10003     if ((sortarray[i][0] == sortarray[j][0])
10004         && (sortarray[i][1] == sortarray[j][1])) {
10005       if (!b->quiet) {
10006         printf(
10007 "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10008                sortarray[j][0], sortarray[j][1]);
10009       }
10010       setvertextype(sortarray[j], UNDEADVERTEX);
10011       m->undeads++;
10012     } else {
10013       i++;
10014       sortarray[i] = sortarray[j];
10015     }
10016   }
10017   i++;
10018   if (b->dwyer) {
10019     
10020     divider = i >> 1;
10021     if (i - divider >= 2) {
10022       if (divider >= 2) {
10023         alternateaxes(sortarray, divider, 1);
10024       }
10025       alternateaxes(&sortarray[divider], i - divider, 1);
10026     }
10027   }
10028 
10029   if (b->verbose) {
10030     printf("  Forming triangulation.\n");
10031   }
10032 
10033   
10034   divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10035   trifree((VOID *) sortarray);
10036 
10037   return removeghosts(m, b, &hullleft);
10038 }
10039 
10042 
10043 
10044 
10048 
10049 
10050 
10051 
10052 
10053 
10054 
10055 
10056 
10057 
10058 
10059 #ifndef REDUCED
10060 
10061 #ifdef ANSI_DECLARATORS
10062 void boundingbox(struct mesh *m, struct behavior *b)
10063 #else 
10064 void boundingbox(m, b)
10065 struct mesh *m;
10066 struct behavior *b;
10067 #endif 
10068 
10069 {
10070   struct otri inftri;          
10071   REAL width;
10072 
10073   if (b->verbose) {
10074     printf("  Creating triangular bounding box.\n");
10075   }
10076   
10077   width = m->xmax - m->xmin;
10078   if (m->ymax - m->ymin > width) {
10079     width = m->ymax - m->ymin;
10080   }
10081   if (width == 0.0) {
10082     width = 1.0;
10083   }
10084   
10085   m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10086   m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10087   m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10088   m->infvertex1[0] = m->xmin - 50.0 * width;
10089   m->infvertex1[1] = m->ymin - 40.0 * width;
10090   m->infvertex2[0] = m->xmax + 50.0 * width;
10091   m->infvertex2[1] = m->ymin - 40.0 * width;
10092   m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10093   m->infvertex3[1] = m->ymax + 60.0 * width;
10094 
10095   
10096   maketriangle(m, b, &inftri);
10097   setorg(inftri, m->infvertex1);
10098   setdest(inftri, m->infvertex2);
10099   setapex(inftri, m->infvertex3);
10100   
10101   
10102   m->dummytri[0] = (triangle) inftri.tri;
10103   if (b->verbose > 2) {
10104     printf("  Creating ");
10105     printtriangle(m, b, &inftri);
10106   }
10107 }
10108 
10109 #endif 
10110 
10111 
10112 
10113 
10114 
10115 
10116 
10117 
10118 
10119 
10120 
10121 
10122 
10123 
10124 
10125 #ifndef REDUCED
10126 
10127 #ifdef ANSI_DECLARATORS
10128 long removebox(struct mesh *m, struct behavior *b)
10129 #else 
10130 long removebox(m, b)
10131 struct mesh *m;
10132 struct behavior *b;
10133 #endif 
10134 
10135 {
10136   struct otri deadtriangle;
10137   struct otri searchedge;
10138   struct otri checkedge;
10139   struct otri nextedge, finaledge, dissolveedge;
10140   vertex markorg;
10141   long hullsize;
10142   triangle ptr;                         
10143 
10144   if (b->verbose) {
10145     printf("  Removing triangular bounding box.\n");
10146   }
10147   
10148   nextedge.tri = m->dummytri;
10149   nextedge.orient = 0;
10150   symself(nextedge);
10151   
10152   lprev(nextedge, finaledge);
10153   lnextself(nextedge);
10154   symself(nextedge);
10155   
10156   
10157   lprev(nextedge, searchedge);
10158   symself(searchedge);
10159   
10160   
10161   lnext(nextedge, checkedge);
10162   symself(checkedge);
10163   if (checkedge.tri == m->dummytri) {
10164     
10165     
10166     
10167     lprevself(searchedge);
10168     symself(searchedge);
10169   }
10170   
10171   
10172   m->dummytri[0] = encode(searchedge);
10173   hullsize = -2l;
10174   while (!otriequal(nextedge, finaledge)) {
10175     hullsize++;
10176     lprev(nextedge, dissolveedge);
10177     symself(dissolveedge);
10178     
10179     
10180     if (!b->poly) {
10181       
10182       
10183       
10184       
10185       if (dissolveedge.tri != m->dummytri) {
10186         org(dissolveedge, markorg);
10187         if (vertexmark(markorg) == 0) {
10188           setvertexmark(markorg, 1);
10189         }
10190       }
10191     }
10192     
10193     dissolve(dissolveedge);
10194     lnext(nextedge, deadtriangle);
10195     sym(deadtriangle, nextedge);
10196     
10197     triangledealloc(m, deadtriangle.tri);
10198     
10199     if (nextedge.tri == m->dummytri) {
10200       
10201       otricopy(dissolveedge, nextedge);
10202     }
10203   }
10204   triangledealloc(m, finaledge.tri);
10205 
10206   trifree((VOID *) m->infvertex1);  
10207   trifree((VOID *) m->infvertex2);
10208   trifree((VOID *) m->infvertex3);
10209 
10210   return hullsize;
10211 }
10212 
10213 #endif 
10214 
10215 
10216 
10217 
10218 
10219 
10220 
10221 
10222 
10223 
10224 #ifndef REDUCED
10225 
10226 #ifdef ANSI_DECLARATORS
10227 long incrementaldelaunay(struct mesh *m, struct behavior *b)
10228 #else 
10229 long incrementaldelaunay(m, b)
10230 struct mesh *m;
10231 struct behavior *b;
10232 #endif 
10233 
10234 {
10235   struct otri starttri;
10236   vertex vertexloop;
10237 
10238   
10239   boundingbox(m, b);
10240   if (b->verbose) {
10241     printf("  Incrementally inserting vertices.\n");
10242   }
10243   traversalinit(&m->vertices);
10244   vertexloop = vertextraverse(m);
10245   while (vertexloop != (vertex) NULL) {
10246     starttri.tri = m->dummytri;
10247     if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10248         == DUPLICATEVERTEX) {
10249       if (!b->quiet) {
10250         printf(
10251 "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10252                vertexloop[0], vertexloop[1]);
10253       }
10254       setvertextype(vertexloop, UNDEADVERTEX);
10255       m->undeads++;
10256     }
10257     vertexloop = vertextraverse(m);
10258   }
10259   
10260   return removebox(m, b);
10261 }
10262 
10263 #endif 
10264 
10267 
10268 
10269 
10273 #ifndef REDUCED
10274 
10275 #ifdef ANSI_DECLARATORS
10276 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10277 #else 
10278 void eventheapinsert(heap, heapsize, newevent)
10279 struct event **heap;
10280 int heapsize;
10281 struct event *newevent;
10282 #endif 
10283 
10284 {
10285   REAL eventx, eventy;
10286   int eventnum;
10287   int parent;
10288   int notdone;
10289 
10290   eventx = newevent->xkey;
10291   eventy = newevent->ykey;
10292   eventnum = heapsize;
10293   notdone = eventnum > 0;
10294   while (notdone) {
10295     parent = (eventnum - 1) >> 1;
10296     if ((heap[parent]->ykey < eventy) ||
10297         ((heap[parent]->ykey == eventy)
10298          && (heap[parent]->xkey <= eventx))) {
10299       notdone = 0;
10300     } else {
10301       heap[eventnum] = heap[parent];
10302       heap[eventnum]->heapposition = eventnum;
10303 
10304       eventnum = parent;
10305       notdone = eventnum > 0;
10306     }
10307   }
10308   heap[eventnum] = newevent;
10309   newevent->heapposition = eventnum;
10310 }
10311 
10312 #endif 
10313 
10314 #ifndef REDUCED
10315 
10316 #ifdef ANSI_DECLARATORS
10317 void eventheapify(struct event **heap, int heapsize, int eventnum)
10318 #else 
10319 void eventheapify(heap, heapsize, eventnum)
10320 struct event **heap;
10321 int heapsize;
10322 int eventnum;
10323 #endif 
10324 
10325 {
10326   struct event *thisevent;
10327   REAL eventx, eventy;
10328   int leftchild, rightchild;
10329   int smallest;
10330   int notdone;
10331 
10332   thisevent = heap[eventnum];
10333   eventx = thisevent->xkey;
10334   eventy = thisevent->ykey;
10335   leftchild = 2 * eventnum + 1;
10336   notdone = leftchild < heapsize;
10337   while (notdone) {
10338     if ((heap[leftchild]->ykey < eventy) ||
10339         ((heap[leftchild]->ykey == eventy)
10340          && (heap[leftchild]->xkey < eventx))) {
10341       smallest = leftchild;
10342     } else {
10343       smallest = eventnum;
10344     }
10345     rightchild = leftchild + 1;
10346     if (rightchild < heapsize) {
10347       if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10348           ((heap[rightchild]->ykey == heap[smallest]->ykey)
10349            && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10350         smallest = rightchild;
10351       }
10352     }
10353     if (smallest == eventnum) {
10354       notdone = 0;
10355     } else {
10356       heap[eventnum] = heap[smallest];
10357       heap[eventnum]->heapposition = eventnum;
10358       heap[smallest] = thisevent;
10359       thisevent->heapposition = smallest;
10360 
10361       eventnum = smallest;
10362       leftchild = 2 * eventnum + 1;
10363       notdone = leftchild < heapsize;
10364     }
10365   }
10366 }
10367 
10368 #endif 
10369 
10370 #ifndef REDUCED
10371 
10372 #ifdef ANSI_DECLARATORS
10373 void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10374 #else 
10375 void eventheapdelete(heap, heapsize, eventnum)
10376 struct event **heap;
10377 int heapsize;
10378 int eventnum;
10379 #endif 
10380 
10381 {
10382   struct event *moveevent;
10383   REAL eventx, eventy;
10384   int parent;
10385   int notdone;
10386 
10387   moveevent = heap[heapsize - 1];
10388   if (eventnum > 0) {
10389     eventx = moveevent->xkey;
10390     eventy = moveevent->ykey;
10391     do {
10392       parent = (eventnum - 1) >> 1;
10393       if ((heap[parent]->ykey < eventy) ||
10394           ((heap[parent]->ykey == eventy)
10395            && (heap[parent]->xkey <= eventx))) {
10396         notdone = 0;
10397       } else {
10398         heap[eventnum] = heap[parent];
10399         heap[eventnum]->heapposition = eventnum;
10400 
10401         eventnum = parent;
10402         notdone = eventnum > 0;
10403       }
10404     } while (notdone);
10405   }
10406   heap[eventnum] = moveevent;
10407   moveevent->heapposition = eventnum;
10408   eventheapify(heap, heapsize - 1, eventnum);
10409 }
10410 
10411 #endif 
10412 
10413 #ifndef REDUCED
10414 
10415 #ifdef ANSI_DECLARATORS
10416 void createeventheap(struct mesh *m, struct event ***eventheap,
10417                      struct event **events, struct event **freeevents)
10418 #else 
10419 void createeventheap(m, eventheap, events, freeevents)
10420 struct mesh *m;
10421 struct event ***eventheap;
10422 struct event **events;
10423 struct event **freeevents;
10424 #endif 
10425 
10426 {
10427   vertex thisvertex;
10428   int maxevents;
10429   int i;
10430 
10431   maxevents = (3 * m->invertices) / 2;
10432   *eventheap = (struct event **) trimalloc(maxevents *
10433                                            (int) sizeof(struct event *));
10434   *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10435   traversalinit(&m->vertices);
10436   for (i = 0; i < m->invertices; i++) {
10437     thisvertex = vertextraverse(m);
10438     (*events)[i].eventptr = (VOID *) thisvertex;
10439     (*events)[i].xkey = thisvertex[0];
10440     (*events)[i].ykey = thisvertex[1];
10441     eventheapinsert(*eventheap, i, *events + i);
10442   }
10443   *freeevents = (struct event *) NULL;
10444   for (i = maxevents - 1; i >= m->invertices; i--) {
10445     (*events)[i].eventptr = (VOID *) *freeevents;
10446     *freeevents = *events + i;
10447   }
10448 }
10449 
10450 #endif 
10451 
10452 #ifndef REDUCED
10453 
10454 #ifdef ANSI_DECLARATORS
10455 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10456 #else 
10457 int rightofhyperbola(m, fronttri, newsite)
10458 struct mesh *m;
10459 struct otri *fronttri;
10460 vertex newsite;
10461 #endif 
10462 
10463 {
10464   vertex leftvertex, rightvertex;
10465   REAL dxa, dya, dxb, dyb;
10466 
10467   m->hyperbolacount++;
10468 
10469   dest(*fronttri, leftvertex);
10470   apex(*fronttri, rightvertex);
10471   if ((leftvertex[1] < rightvertex[1]) ||
10472       ((leftvertex[1] == rightvertex[1]) &&
10473        (leftvertex[0] < rightvertex[0]))) {
10474     if (newsite[0] >= rightvertex[0]) {
10475       return 1;
10476     }
10477   } else {
10478     if (newsite[0] <= leftvertex[0]) {
10479       return 0;
10480     }
10481   }
10482   dxa = leftvertex[0] - newsite[0];
10483   dya = leftvertex[1] - newsite[1];
10484   dxb = rightvertex[0] - newsite[0];
10485   dyb = rightvertex[1] - newsite[1];
10486   return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10487 }
10488 
10489 #endif 
10490 
10491 #ifndef REDUCED
10492 
10493 #ifdef ANSI_DECLARATORS
10494 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10495 #else 
10496 REAL circletop(m, pa, pb, pc, ccwabc)
10497 struct mesh *m;
10498 vertex pa;
10499 vertex pb;
10500 vertex pc;
10501 REAL ccwabc;
10502 #endif 
10503 
10504 {
10505   REAL xac, yac, xbc, ybc, xab, yab;
10506   REAL aclen2, bclen2, ablen2;
10507 
10508   m->circletopcount++;
10509 
10510   xac = pa[0] - pc[0];
10511   yac = pa[1] - pc[1];
10512   xbc = pb[0] - pc[0];
10513   ybc = pb[1] - pc[1];
10514   xab = pa[0] - pb[0];
10515   yab = pa[1] - pb[1];
10516   aclen2 = xac * xac + yac * yac;
10517   bclen2 = xbc * xbc + ybc * ybc;
10518   ablen2 = xab * xab + yab * yab;
10519   return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10520                / (2.0 * ccwabc);
10521 }
10522 
10523 #endif 
10524 
10525 #ifndef REDUCED
10526 
10527 #ifdef ANSI_DECLARATORS
10528 void check4deadevent(struct otri *checktri, struct event **freeevents,
10529                      struct event **eventheap, int *heapsize)
10530 #else 
10531 void check4deadevent(checktri, freeevents, eventheap, heapsize)
10532 struct otri *checktri;
10533 struct event **freeevents;
10534 struct event **eventheap;
10535 int *heapsize;
10536 #endif 
10537 
10538 {
10539   struct event *deadevent;
10540   vertex eventvertex;
10541   int eventnum;
10542 
10543   org(*checktri, eventvertex);
10544   if (eventvertex != (vertex) NULL) {
10545     deadevent = (struct event *) eventvertex;
10546     eventnum = deadevent->heapposition;
10547     deadevent->eventptr = (VOID *) *freeevents;
10548     *freeevents = deadevent;
10549     eventheapdelete(eventheap, *heapsize, eventnum);
10550     (*heapsize)--;
10551     setorg(*checktri, NULL);
10552   }
10553 }
10554 
10555 #endif 
10556 
10557 #ifndef REDUCED
10558 
10559 #ifdef ANSI_DECLARATORS
10560 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10561                         vertex searchpoint, struct otri *searchtri)
10562 #else 
10563 struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10564 struct mesh *m;
10565 struct splaynode *splaytree;
10566 vertex searchpoint;
10567 struct otri *searchtri;
10568 #endif 
10569 
10570 {
10571   struct splaynode *child, *grandchild;
10572   struct splaynode *lefttree, *righttree;
10573   struct splaynode *leftright;
10574   vertex checkvertex;
10575   int rightofroot, rightofchild;
10576 
10577   if (splaytree == (struct splaynode *) NULL) {
10578     return (struct splaynode *) NULL;
10579   }
10580   dest(splaytree->keyedge, checkvertex);
10581   if (checkvertex == splaytree->keydest) {
10582     rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10583     if (rightofroot) {
10584       otricopy(splaytree->keyedge, *searchtri);
10585       child = splaytree->rchild;
10586     } else {
10587       child = splaytree->lchild;
10588     }
10589     if (child == (struct splaynode *) NULL) {
10590       return splaytree;
10591     }
10592     dest(child->keyedge, checkvertex);
10593     if (checkvertex != child->keydest) {
10594       child = splay(m, child, searchpoint, searchtri);
10595       if (child == (struct splaynode *) NULL) {
10596         if (rightofroot) {
10597           splaytree->rchild = (struct splaynode *) NULL;
10598         } else {
10599           splaytree->lchild = (struct splaynode *) NULL;
10600         }
10601         return splaytree;
10602       }
10603     }
10604     rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10605     if (rightofchild) {
10606       otricopy(child->keyedge, *searchtri);
10607       grandchild = splay(m, child->rchild, searchpoint, searchtri);
10608       child->rchild = grandchild;
10609     } else {
10610       grandchild = splay(m, child->lchild, searchpoint, searchtri);
10611       child->lchild = grandchild;
10612     }
10613     if (grandchild == (struct splaynode *) NULL) {
10614       if (rightofroot) {
10615         splaytree->rchild = child->lchild;
10616         child->lchild = splaytree;
10617       } else {
10618         splaytree->lchild = child->rchild;
10619         child->rchild = splaytree;
10620       }
10621       return child;
10622     }
10623     if (rightofchild) {
10624       if (rightofroot) {
10625         splaytree->rchild = child->lchild;
10626         child->lchild = splaytree;
10627       } else {
10628         splaytree->lchild = grandchild->rchild;
10629         grandchild->rchild = splaytree;
10630       }
10631       child->rchild = grandchild->lchild;
10632       grandchild->lchild = child;
10633     } else {
10634       if (rightofroot) {
10635         splaytree->rchild = grandchild->lchild;
10636         grandchild->lchild = splaytree;
10637       } else {
10638         splaytree->lchild = child->rchild;
10639         child->rchild = splaytree;
10640       }
10641       child->lchild = grandchild->rchild;
10642       grandchild->rchild = child;
10643     }
10644     return grandchild;
10645   } else {
10646     lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10647     righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10648 
10649     pooldealloc(&m->splaynodes, (VOID *) splaytree);
10650     if (lefttree == (struct splaynode *) NULL) {
10651       return righttree;
10652     } else if (righttree == (struct splaynode *) NULL) {
10653       return lefttree;
10654     } else if (lefttree->rchild == (struct splaynode *) NULL) {
10655       lefttree->rchild = righttree->lchild;
10656       righttree->lchild = lefttree;
10657       return righttree;
10658     } else if (righttree->lchild == (struct splaynode *) NULL) {
10659       righttree->lchild = lefttree->rchild;
10660       lefttree->rchild = righttree;
10661       return lefttree;
10662     } else {
10663 
10664       leftright = lefttree->rchild;
10665       while (leftright->rchild != (struct splaynode *) NULL) {
10666         leftright = leftright->rchild;
10667       }
10668       leftright->rchild = righttree;
10669       return lefttree;
10670     }
10671   }
10672 }
10673 
10674 #endif 
10675 
10676 #ifndef REDUCED
10677 
10678 #ifdef ANSI_DECLARATORS
10679 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10680                               struct otri *newkey, vertex searchpoint)
10681 #else 
10682 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10683 struct mesh *m;
10684 struct splaynode *splayroot;
10685 struct otri *newkey;
10686 vertex searchpoint;
10687 #endif 
10688 
10689 {
10690   struct splaynode *newsplaynode;
10691 
10692   newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10693   otricopy(*newkey, newsplaynode->keyedge);
10694   dest(*newkey, newsplaynode->keydest);
10695   if (splayroot == (struct splaynode *) NULL) {
10696     newsplaynode->lchild = (struct splaynode *) NULL;
10697     newsplaynode->rchild = (struct splaynode *) NULL;
10698   } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10699     newsplaynode->lchild = splayroot;
10700     newsplaynode->rchild = splayroot->rchild;
10701     splayroot->rchild = (struct splaynode *) NULL;
10702   } else {
10703     newsplaynode->lchild = splayroot->lchild;
10704     newsplaynode->rchild = splayroot;
10705     splayroot->lchild = (struct splaynode *) NULL;
10706   }
10707   return newsplaynode;
10708 }
10709 
10710 #endif 
10711 
10712 #ifndef REDUCED
10713 
10714 #ifdef ANSI_DECLARATORS
10715 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10716                                   struct splaynode *splayroot,
10717                                   struct otri *newkey,
10718                                   vertex pa, vertex pb, vertex pc, REAL topy)
10719 #else 
10720 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10721 struct mesh *m;
10722 struct behavior *b;
10723 struct splaynode *splayroot;
10724 struct otri *newkey;
10725 vertex pa;
10726 vertex pb;
10727 vertex pc;
10728 REAL topy;
10729 #endif 
10730 
10731 {
10732   REAL ccwabc;
10733   REAL xac, yac, xbc, ybc;
10734   REAL aclen2, bclen2;
10735   REAL searchpoint[2];
10736   struct otri dummytri;
10737 
10738   ccwabc = counterclockwise(m, b, pa, pb, pc);
10739   xac = pa[0] - pc[0];
10740   yac = pa[1] - pc[1];
10741   xbc = pb[0] - pc[0];
10742   ybc = pb[1] - pc[1];
10743   aclen2 = xac * xac + yac * yac;
10744   bclen2 = xbc * xbc + ybc * ybc;
10745   searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10746   searchpoint[1] = topy;
10747   return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10748                      newkey, (vertex) searchpoint);
10749 }
10750 
10751 #endif 
10752 
10753 #ifndef REDUCED
10754 
10755 #ifdef ANSI_DECLARATORS
10756 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10757                               struct otri *bottommost, vertex searchvertex,
10758                               struct otri *searchtri, int *farright)
10759 #else 
10760 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10761                               searchtri, farright)
10762 struct mesh *m;
10763 struct splaynode *splayroot;
10764 struct otri *bottommost;
10765 vertex searchvertex;
10766 struct otri *searchtri;
10767 int *farright;
10768 #endif 
10769 
10770 {
10771   int farrightflag;
10772   triangle ptr;                       
10773 
10774   otricopy(*bottommost, *searchtri);
10775   splayroot = splay(m, splayroot, searchvertex, searchtri);
10776 
10777   farrightflag = 0;
10778   while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10779     onextself(*searchtri);
10780     farrightflag = otriequal(*searchtri, *bottommost);
10781   }
10782   *farright = farrightflag;
10783   return splayroot;
10784 }
10785 
10786 #endif 
10787 
10788 #ifndef REDUCED
10789 
10790 #ifdef ANSI_DECLARATORS
10791 long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10792 #else 
10793 long sweeplinedelaunay(m, b)
10794 struct mesh *m;
10795 struct behavior *b;
10796 #endif 
10797 
10798 {
10799   struct event **eventheap;
10800   struct event *events;
10801   struct event *freeevents;
10802   struct event *nextevent;
10803   struct event *newevent;
10804   struct splaynode *splayroot;
10805   struct otri bottommost;
10806   struct otri searchtri;
10807   struct otri fliptri;
10808   struct otri lefttri, righttri, farlefttri, farrighttri;
10809   struct otri inserttri;
10810   vertex firstvertex, secondvertex;
10811   vertex nextvertex, lastvertex;
10812   vertex connectvertex;
10813   vertex leftvertex, midvertex, rightvertex;
10814   REAL lefttest, righttest;
10815   int heapsize;
10816   int check4events, farrightflag;
10817   triangle ptr;   
10818 
10819   poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10820            SPLAYNODEPERBLOCK, 0);
10821   splayroot = (struct splaynode *) NULL;
10822 
10823   if (b->verbose) {
10824     printf("  Placing vertices in event heap.\n");
10825   }
10826   createeventheap(m, &eventheap, &events, &freeevents);
10827   heapsize = m->invertices;
10828 
10829   if (b->verbose) {
10830     printf("  Forming triangulation.\n");
10831   }
10832   maketriangle(m, b, &lefttri);
10833   maketriangle(m, b, &righttri);
10834   bond(lefttri, righttri);
10835   lnextself(lefttri);
10836   lprevself(righttri);
10837   bond(lefttri, righttri);
10838   lnextself(lefttri);
10839   lprevself(righttri);
10840   bond(lefttri, righttri);
10841   firstvertex = (vertex) eventheap[0]->eventptr;
10842   eventheap[0]->eventptr = (VOID *) freeevents;
10843   freeevents = eventheap[0];
10844   eventheapdelete(eventheap, heapsize, 0);
10845   heapsize--;
10846   do {
10847     if (heapsize == 0) {
10848       printf("Error:  Input vertices are all identical.\n");
10849       triexit(1);
10850     }
10851     secondvertex = (vertex) eventheap[0]->eventptr;
10852     eventheap[0]->eventptr = (VOID *) freeevents;
10853     freeevents = eventheap[0];
10854     eventheapdelete(eventheap, heapsize, 0);
10855     heapsize--;
10856     if ((firstvertex[0] == secondvertex[0]) &&
10857         (firstvertex[1] == secondvertex[1])) {
10858       if (!b->quiet) {
10859         printf(
10860 "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10861                secondvertex[0], secondvertex[1]);
10862       }
10863       setvertextype(secondvertex, UNDEADVERTEX);
10864       m->undeads++;
10865     }
10866   } while ((firstvertex[0] == secondvertex[0]) &&
10867            (firstvertex[1] == secondvertex[1]));
10868   setorg(lefttri, firstvertex);
10869   setdest(lefttri, secondvertex);
10870   setorg(righttri, secondvertex);
10871   setdest(righttri, firstvertex);
10872   lprev(lefttri, bottommost);
10873   lastvertex = secondvertex;
10874   while (heapsize > 0) {
10875     nextevent = eventheap[0];
10876     eventheapdelete(eventheap, heapsize, 0);
10877     heapsize--;
10878     check4events = 1;
10879     if (nextevent->xkey < m->xmin) {
10880       decode(nextevent->eventptr, fliptri);
10881       oprev(fliptri, farlefttri);
10882       check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10883       onext(fliptri, farrighttri);
10884       check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10885 
10886       if (otriequal(farlefttri, bottommost)) {
10887         lprev(fliptri, bottommost);
10888       }
10889       flip(m, b, &fliptri);
10890       setapex(fliptri, NULL);
10891       lprev(fliptri, lefttri);
10892       lnext(fliptri, righttri);
10893       sym(lefttri, farlefttri);
10894 
10895       if (randomnation(SAMPLERATE) == 0) {
10896         symself(fliptri);
10897         dest(fliptri, leftvertex);
10898         apex(fliptri, midvertex);
10899         org(fliptri, rightvertex);
10900         splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10901                                     midvertex, rightvertex, nextevent->ykey);
10902       }
10903     } else {
10904       nextvertex = (vertex) nextevent->eventptr;
10905       if ((nextvertex[0] == lastvertex[0]) &&
10906           (nextvertex[1] == lastvertex[1])) {
10907         if (!b->quiet) {
10908           printf(
10909 "Warning:  A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10910                  nextvertex[0], nextvertex[1]);
10911         }
10912         setvertextype(nextvertex, UNDEADVERTEX);
10913         m->undeads++;
10914         check4events = 0;
10915       } else {
10916         lastvertex = nextvertex;
10917 
10918         splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10919                                 &searchtri, &farrightflag);
10920 
10921 
10922 
10923 
10924 
10925 
10926 
10927 
10928 
10929         check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10930 
10931         otricopy(searchtri, farrighttri);
10932         sym(searchtri, farlefttri);
10933         maketriangle(m, b, &lefttri);
10934         maketriangle(m, b, &righttri);
10935         dest(farrighttri, connectvertex);
10936         setorg(lefttri, connectvertex);
10937         setdest(lefttri, nextvertex);
10938         setorg(righttri, nextvertex);
10939         setdest(righttri, connectvertex);
10940         bond(lefttri, righttri);
10941         lnextself(lefttri);
10942         lprevself(righttri);
10943         bond(lefttri, righttri);
10944         lnextself(lefttri);
10945         lprevself(righttri);
10946         bond(lefttri, farlefttri);
10947         bond(righttri, farrighttri);
10948         if (!farrightflag && otriequal(farrighttri, bottommost)) {
10949           otricopy(lefttri, bottommost);
10950         }
10951 
10952         if (randomnation(SAMPLERATE) == 0) {
10953           splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10954         } else if (randomnation(SAMPLERATE) == 0) {
10955           lnext(righttri, inserttri);
10956           splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10957         }
10958       }
10959     }
10960     nextevent->eventptr = (VOID *) freeevents;
10961     freeevents = nextevent;
10962 
10963     if (check4events) {
10964       apex(farlefttri, leftvertex);
10965       dest(lefttri, midvertex);
10966       apex(lefttri, rightvertex);
10967       lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10968       if (lefttest > 0.0) {
10969         newevent = freeevents;
10970         freeevents = (struct event *) freeevents->eventptr;
10971         newevent->xkey = m->xminextreme;
10972         newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10973                                    lefttest);
10974         newevent->eventptr = (VOID *) encode(lefttri);
10975         eventheapinsert(eventheap, heapsize, newevent);
10976         heapsize++;
10977         setorg(lefttri, newevent);
10978       }
10979       apex(righttri, leftvertex);
10980       org(righttri, midvertex);
10981       apex(farrighttri, rightvertex);
10982       righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10983       if (righttest > 0.0) {
10984         newevent = freeevents;
10985         freeevents = (struct event *) freeevents->eventptr;
10986         newevent->xkey = m->xminextreme;
10987         newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10988                                    righttest);
10989         newevent->eventptr = (VOID *) encode(farrighttri);
10990         eventheapinsert(eventheap, heapsize, newevent);
10991         heapsize++;
10992         setorg(farrighttri, newevent);
10993       }
10994     }
10995   }
10996 
10997   pooldeinit(&m->splaynodes);
10998   lprevself(bottommost);
10999   return removeghosts(m, b, &bottommost);
11000 }
11001 
11002 #endif 
11003 
11006 
11007 
11008 
11012 
11013 
11014 
11015 
11016 
11017 
11018 #ifdef ANSI_DECLARATORS
11019 long delaunay(struct mesh *m, struct behavior *b)
11020 #else 
11021 long delaunay(m, b)
11022 struct mesh *m;
11023 struct behavior *b;
11024 #endif 
11025 
11026 {
11027   long hulledges;
11028 
11029   m->eextras = 0;
11030   initializetrisubpools(m, b);
11031 
11032 #ifdef REDUCED
11033   if (!b->quiet) {
11034     printf(
11035       "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11036   }
11037   hulledges = divconqdelaunay(m, b);
11038 #else 
11039   if (!b->quiet) {
11040     printf("Constructing Delaunay triangulation ");
11041     if (b->incremental) {
11042       printf("by incremental method.\n");
11043     } else if (b->sweepline) {
11044       printf("by sweepline method.\n");
11045     } else {
11046       printf("by divide-and-conquer method.\n");
11047     }
11048   }
11049   if (b->incremental) {
11050     hulledges = incrementaldelaunay(m, b);
11051   } else if (b->sweepline) {
11052     hulledges = sweeplinedelaunay(m, b);
11053   } else {
11054     hulledges = divconqdelaunay(m, b);
11055   }
11056 #endif 
11057 
11058   if (m->triangles.items == 0) {
11059     
11060     return 0l;
11061   } else {
11062     return hulledges;
11063   }
11064 }
11065 
11066 
11067 
11068 
11069 
11070 
11071 
11072 
11073 
11074 
11075 
11076 
11077 
11078 
11079 
11080 
11081 
11082 
11083 
11084 
11085 
11086 
11087 
11088 
11089 
11090 
11091 #ifndef CDT_ONLY
11092 
11093 #ifdef TRILIBRARY
11094 
11095 #ifdef ANSI_DECLARATORS
11096 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11097                 REAL *triangleattriblist, REAL *trianglearealist,
11098                 int elements, int corners, int attribs,
11099                 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11100 #else 
11101 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11102                 elements, corners, attribs, segmentlist, segmentmarkerlist,
11103                 numberofsegments)
11104 struct mesh *m;
11105 struct behavior *b;
11106 int *trianglelist;
11107 REAL *triangleattriblist;
11108 REAL *trianglearealist;
11109 int elements;
11110 int corners;
11111 int attribs;
11112 int *segmentlist;
11113 int *segmentmarkerlist;
11114 int numberofsegments;
11115 #endif 
11116 
11117 #else 
11118 
11119 #ifdef ANSI_DECLARATORS
11120 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11121                  char *areafilename, char *polyfilename, FILE *polyfile)
11122 #else 
11123 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11124 struct mesh *m;
11125 struct behavior *b;
11126 char *elefilename;
11127 char *areafilename;
11128 char *polyfilename;
11129 FILE *polyfile;
11130 #endif 
11131 
11132 #endif 
11133 
11134 {
11135 #ifdef TRILIBRARY
11136   int vertexindex;
11137   int attribindex;
11138 #else 
11139   FILE *elefile;
11140   FILE *areafile;
11141   char inputline[INPUTLINESIZE];
11142   char *stringptr;
11143   int areaelements;
11144 #endif 
11145   struct otri triangleloop;
11146   struct otri triangleleft;
11147   struct otri checktri;
11148   struct otri checkleft;
11149   struct otri checkneighbor;
11150   struct osub subsegloop;
11151   triangle *vertexarray;
11152   triangle *prevlink;
11153   triangle nexttri;
11154   vertex tdest, tapex;
11155   vertex checkdest, checkapex;
11156   vertex shorg;
11157   vertex killvertex;
11158   vertex segmentorg, segmentdest;
11159   REAL area;
11160   int corner[3];
11161   int end[2];
11162   int killvertexindex;
11163   int incorners;
11164   int segmentmarkers;
11165   int boundmarker;
11166   int aroundvertex;
11167   long hullsize;
11168   int notfound;
11169   long elementnumber, segmentnumber;
11170   int i, j;
11171   triangle ptr;                         
11172 
11173 #ifdef TRILIBRARY
11174   m->inelements = elements;
11175   incorners = corners;
11176   if (incorners < 3) {
11177     printf("Error:  Triangles must have at least 3 vertices.\n");
11178     triexit(1);
11179   }
11180   m->eextras = attribs;
11181 #else 
11182   
11183   if (!b->quiet) {
11184     printf("Opening %s.\n", elefilename);
11185   }
11186   elefile = fopen(elefilename, "r");
11187   if (elefile == (FILE *) NULL) {
11188     printf("  Error:  Cannot access file %s.\n", elefilename);
11189     triexit(1);
11190   }
11191   
11192   
11193   stringptr = readline(inputline, elefile, elefilename);
11194   m->inelements = (int) strtol(stringptr, &stringptr, 0);
11195   stringptr = findfield(stringptr);
11196   if (*stringptr == '\0') {
11197     incorners = 3;
11198   } else {
11199     incorners = (int) strtol(stringptr, &stringptr, 0);
11200     if (incorners < 3) {
11201       printf("Error:  Triangles in %s must have at least 3 vertices.\n",
11202              elefilename);
11203       triexit(1);
11204     }
11205   }
11206   stringptr = findfield(stringptr);
11207   if (*stringptr == '\0') {
11208     m->eextras = 0;
11209   } else {
11210     m->eextras = (int) strtol(stringptr, &stringptr, 0);
11211   }
11212 #endif 
11213 
11214   initializetrisubpools(m, b);
11215 
11216   
11217   for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11218     maketriangle(m, b, &triangleloop);
11219     
11220     triangleloop.tri[3] = (triangle) triangleloop.tri;
11221   }
11222 
11223   segmentmarkers = 0;
11224   if (b->poly) {
11225 #ifdef TRILIBRARY
11226     m->insegments = numberofsegments;
11227     segmentmarkers = segmentmarkerlist != (int *) NULL;
11228 #else 
11229     
11230     
11231     stringptr = readline(inputline, polyfile, b->inpolyfilename);
11232     m->insegments = (int) strtol(stringptr, &stringptr, 0);
11233     stringptr = findfield(stringptr);
11234     if (*stringptr != '\0') {
11235       segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11236     }
11237 #endif 
11238 
11239     
11240     for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11241       makesubseg(m, &subsegloop);
11242       
11243       subsegloop.ss[2] = (subseg) subsegloop.ss;
11244     }
11245   }
11246 
11247 #ifdef TRILIBRARY
11248   vertexindex = 0;
11249   attribindex = 0;
11250 #else 
11251   if (b->vararea) {
11252     
11253     if (!b->quiet) {
11254       printf("Opening %s.\n", areafilename);
11255     }
11256     areafile = fopen(areafilename, "r");
11257     if (areafile == (FILE *) NULL) {
11258       printf("  Error:  Cannot access file %s.\n", areafilename);
11259       triexit(1);
11260     }
11261     stringptr = readline(inputline, areafile, areafilename);
11262     areaelements = (int) strtol(stringptr, &stringptr, 0);
11263     if (areaelements != m->inelements) {
11264       printf("Error:  %s and %s disagree on number of triangles.\n",
11265              elefilename, areafilename);
11266       triexit(1);
11267     }
11268   }
11269 #endif 
11270 
11271   if (!b->quiet) {
11272     printf("Reconstructing mesh.\n");
11273   }
11274   
11275   
11276   
11277   vertexarray = (triangle *) trimalloc(m->vertices.items *
11278                                        (int) sizeof(triangle));
11279   
11280   for (i = 0; i < m->vertices.items; i++) {
11281     vertexarray[i] = (triangle) m->dummytri;
11282   }
11283 
11284   if (b->verbose) {
11285     printf("  Assembling triangles.\n");
11286   }
11287   
11288   
11289   traversalinit(&m->triangles);
11290   triangleloop.tri = triangletraverse(m);
11291   elementnumber = b->firstnumber;
11292   while (triangleloop.tri != (triangle *) NULL) {
11293 #ifdef TRILIBRARY
11294     
11295     for (j = 0; j < 3; j++) {
11296       corner[j] = trianglelist[vertexindex++];
11297       if ((corner[j] < b->firstnumber) ||
11298           (corner[j] >= b->firstnumber + m->invertices)) {
11299         printf("Error:  Triangle %ld has an invalid vertex index.\n",
11300                elementnumber);
11301         triexit(1);
11302       }
11303     }
11304 #else 
11305     
11306     stringptr = readline(inputline, elefile, elefilename);
11307     for (j = 0; j < 3; j++) {
11308       stringptr = findfield(stringptr);
11309       if (*stringptr == '\0') {
11310         printf("Error:  Triangle %ld is missing vertex %d in %s.\n",
11311                elementnumber, j + 1, elefilename);
11312         triexit(1);
11313       } else {
11314         corner[j] = (int) strtol(stringptr, &stringptr, 0);
11315         if ((corner[j] < b->firstnumber) ||
11316             (corner[j] >= b->firstnumber + m->invertices)) {
11317           printf("Error:  Triangle %ld has an invalid vertex index.\n",
11318                  elementnumber);
11319           triexit(1);
11320         }
11321       }
11322     }
11323 #endif 
11324 
11325     
11326     for (j = 3; j < incorners; j++) {
11327 #ifdef TRILIBRARY
11328       killvertexindex = trianglelist[vertexindex++];
11329 #else 
11330       stringptr = findfield(stringptr);
11331       if (*stringptr != '\0') {
11332         killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11333 #endif 
11334         if ((killvertexindex >= b->firstnumber) &&
11335             (killvertexindex < b->firstnumber + m->invertices)) {
11336           
11337           killvertex = getvertex(m, b, killvertexindex);
11338           if (vertextype(killvertex) != DEADVERTEX) {
11339             vertexdealloc(m, killvertex);
11340           }
11341         }
11342 #ifndef TRILIBRARY
11343       }
11344 #endif 
11345     }
11346 
11347     
11348     for (j = 0; j < m->eextras; j++) {
11349 #ifdef TRILIBRARY
11350       setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11351 #else 
11352       stringptr = findfield(stringptr);
11353       if (*stringptr == '\0') {
11354         setelemattribute(triangleloop, j, 0);
11355       } else {
11356         setelemattribute(triangleloop, j,
11357                          (REAL) strtod(stringptr, &stringptr));
11358       }
11359 #endif 
11360     }
11361 
11362     if (b->vararea) {
11363 #ifdef TRILIBRARY
11364       area = trianglearealist[elementnumber - b->firstnumber];
11365 #else 
11366       
11367       stringptr = readline(inputline, areafile, areafilename);
11368       stringptr = findfield(stringptr);
11369       if (*stringptr == '\0') {
11370         area = -1.0;                      
11371       } else {
11372         area = (REAL) strtod(stringptr, &stringptr);
11373       }
11374 #endif 
11375       setareabound(triangleloop, area);
11376     }
11377 
11378     
11379     triangleloop.orient = 0;
11380     setorg(triangleloop, getvertex(m, b, corner[0]));
11381     setdest(triangleloop, getvertex(m, b, corner[1]));
11382     setapex(triangleloop, getvertex(m, b, corner[2]));
11383     
11384     for (triangleloop.orient = 0; triangleloop.orient < 3;
11385          triangleloop.orient++) {
11386       
11387       aroundvertex = corner[triangleloop.orient];
11388       
11389       nexttri = vertexarray[aroundvertex - b->firstnumber];
11390       
11391       triangleloop.tri[6 + triangleloop.orient] = nexttri;
11392       
11393       vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11394       decode(nexttri, checktri);
11395       if (checktri.tri != m->dummytri) {
11396         dest(triangleloop, tdest);
11397         apex(triangleloop, tapex);
11398         
11399         do {
11400           dest(checktri, checkdest);
11401           apex(checktri, checkapex);
11402           if (tapex == checkdest) {
11403             
11404             lprev(triangleloop, triangleleft);
11405             bond(triangleleft, checktri);
11406           }
11407           if (tdest == checkapex) {
11408             
11409             lprev(checktri, checkleft);
11410             bond(triangleloop, checkleft);
11411           }
11412           
11413           nexttri = checktri.tri[6 + checktri.orient];
11414           decode(nexttri, checktri);
11415         } while (checktri.tri != m->dummytri);
11416       }
11417     }
11418     triangleloop.tri = triangletraverse(m);
11419     elementnumber++;
11420   }
11421 
11422 #ifdef TRILIBRARY
11423   vertexindex = 0;
11424 #else 
11425   fclose(elefile);
11426   if (b->vararea) {
11427     fclose(areafile);
11428   }
11429 #endif 
11430 
11431   hullsize = 0;                      
11432   if (b->poly) {
11433     if (b->verbose) {
11434       printf("  Marking segments in triangulation.\n");
11435     }
11436     
11437     
11438     boundmarker = 0;
11439     traversalinit(&m->subsegs);
11440     subsegloop.ss = subsegtraverse(m);
11441     segmentnumber = b->firstnumber;
11442     while (subsegloop.ss != (subseg *) NULL) {
11443 #ifdef TRILIBRARY
11444       end[0] = segmentlist[vertexindex++];
11445       end[1] = segmentlist[vertexindex++];
11446       if (segmentmarkers) {
11447         boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11448       }
11449 #else 
11450       
11451       stringptr = readline(inputline, polyfile, b->inpolyfilename);
11452       
11453       stringptr = findfield(stringptr);
11454       if (*stringptr == '\0') {
11455         printf("Error:  Segment %ld has no endpoints in %s.\n", segmentnumber,
11456                polyfilename);
11457         triexit(1);
11458       } else {
11459         end[0] = (int) strtol(stringptr, &stringptr, 0);
11460       }
11461       stringptr = findfield(stringptr);
11462       if (*stringptr == '\0') {
11463         printf("Error:  Segment %ld is missing its second endpoint in %s.\n",
11464                segmentnumber, polyfilename);
11465         triexit(1);
11466       } else {
11467         end[1] = (int) strtol(stringptr, &stringptr, 0);
11468       }
11469       if (segmentmarkers) {
11470         stringptr = findfield(stringptr);
11471         if (*stringptr == '\0') {
11472           boundmarker = 0;
11473         } else {
11474           boundmarker = (int) strtol(stringptr, &stringptr, 0);
11475         }
11476       }
11477 #endif 
11478       for (j = 0; j < 2; j++) {
11479         if ((end[j] < b->firstnumber) ||
11480             (end[j] >= b->firstnumber + m->invertices)) {
11481           printf("Error:  Segment %ld has an invalid vertex index.\n", 
11482                  segmentnumber);
11483           triexit(1);
11484         }
11485       }
11486 
11487       
11488       subsegloop.ssorient = 0;
11489       segmentorg = getvertex(m, b, end[0]);
11490       segmentdest = getvertex(m, b, end[1]);
11491       setsorg(subsegloop, segmentorg);
11492       setsdest(subsegloop, segmentdest);
11493       setsegorg(subsegloop, segmentorg);
11494       setsegdest(subsegloop, segmentdest);
11495       setmark(subsegloop, boundmarker);
11496       
11497       for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11498            subsegloop.ssorient++) {
11499         
11500         aroundvertex = end[1 - subsegloop.ssorient];
11501         
11502         prevlink = &vertexarray[aroundvertex - b->firstnumber];
11503         nexttri = vertexarray[aroundvertex - b->firstnumber];
11504         decode(nexttri, checktri);
11505         sorg(subsegloop, shorg);
11506         notfound = 1;
11507         
11508         
11509         
11510         
11511         
11512         
11513         
11514         while (notfound && (checktri.tri != m->dummytri)) {
11515           dest(checktri, checkdest);
11516           if (shorg == checkdest) {
11517             
11518             *prevlink = checktri.tri[6 + checktri.orient];
11519             
11520             tsbond(checktri, subsegloop);
11521             
11522             sym(checktri, checkneighbor);
11523             if (checkneighbor.tri == m->dummytri) {
11524               
11525               
11526               
11527               insertsubseg(m, b, &checktri, 1);
11528               hullsize++;
11529             }
11530             notfound = 0;
11531           }
11532           
11533           prevlink = &checktri.tri[6 + checktri.orient];
11534           nexttri = checktri.tri[6 + checktri.orient];
11535           decode(nexttri, checktri);
11536         }
11537       }
11538       subsegloop.ss = subsegtraverse(m);
11539       segmentnumber++;
11540     }
11541   }
11542 
11543   
11544   
11545   for (i = 0; i < m->vertices.items; i++) {
11546     
11547     nexttri = vertexarray[i];
11548     decode(nexttri, checktri);
11549     while (checktri.tri != m->dummytri) {
11550       
11551       
11552       nexttri = checktri.tri[6 + checktri.orient];
11553       
11554       tsdissolve(checktri);
11555       sym(checktri, checkneighbor);
11556       if (checkneighbor.tri == m->dummytri) {
11557         insertsubseg(m, b, &checktri, 1);
11558         hullsize++;
11559       }
11560       decode(nexttri, checktri);
11561     }
11562   }
11563 
11564   trifree((VOID *) vertexarray);
11565   return hullsize;
11566 }
11567 
11568 #endif 
11569 
11572 
11573 
11574 
11578 
11579 
11580 
11581 
11582 
11583 
11584 
11585 
11586 
11587 
11588 
11589 
11590 
11591 
11592 
11593 
11594 
11595 #ifdef ANSI_DECLARATORS
11596 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11597                                        struct otri *searchtri,
11598                                        vertex searchpoint)
11599 #else 
11600 enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11601 struct mesh *m;
11602 struct behavior *b;
11603 struct otri *searchtri;
11604 vertex searchpoint;
11605 #endif 
11606 
11607 {
11608   struct otri checktri;
11609   vertex startvertex;
11610   vertex leftvertex, rightvertex;
11611   REAL leftccw, rightccw;
11612   int leftflag, rightflag;
11613   triangle ptr;           
11614 
11615   org(*searchtri, startvertex);
11616   dest(*searchtri, rightvertex);
11617   apex(*searchtri, leftvertex);
11618   
11619   leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11620   leftflag = leftccw > 0.0;
11621   
11622   rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11623   rightflag = rightccw > 0.0;
11624   if (leftflag && rightflag) {
11625     
11626     
11627     onext(*searchtri, checktri);
11628     if (checktri.tri == m->dummytri) {
11629       leftflag = 0;
11630     } else {
11631       rightflag = 0;
11632     }
11633   }
11634   while (leftflag) {
11635     
11636     onextself(*searchtri);
11637     if (searchtri->tri == m->dummytri) {
11638       printf("Internal error in finddirection():  Unable to find a\n");
11639       printf("  triangle leading from (%.12g, %.12g) to", startvertex[0],
11640              startvertex[1]);
11641       printf("  (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11642       internalerror();
11643     }
11644     apex(*searchtri, leftvertex);
11645     rightccw = leftccw;
11646     leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11647     leftflag = leftccw > 0.0;
11648   }
11649   while (rightflag) {
11650     
11651     oprevself(*searchtri);
11652     if (searchtri->tri == m->dummytri) {
11653       printf("Internal error in finddirection():  Unable to find a\n");
11654       printf("  triangle leading from (%.12g, %.12g) to", startvertex[0],
11655              startvertex[1]);
11656       printf("  (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11657       internalerror();
11658     }
11659     dest(*searchtri, rightvertex);
11660     leftccw = rightccw;
11661     rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11662     rightflag = rightccw > 0.0;
11663   }
11664   if (leftccw == 0.0) {
11665     return LEFTCOLLINEAR;
11666   } else if (rightccw == 0.0) {
11667     return RIGHTCOLLINEAR;
11668   } else {
11669     return WITHIN;
11670   }
11671 }
11672 
11673 
11674 
11675 
11676 
11677 
11678 
11679 
11680 
11681 
11682 
11683 
11684 
11685 
11686 
11687 
11688 
11689 
11690 #ifdef ANSI_DECLARATORS
11691 void segmentintersection(struct mesh *m, struct behavior *b,
11692                          struct otri *splittri, struct osub *splitsubseg,
11693                          vertex endpoint2)
11694 #else 
11695 void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11696 struct mesh *m;
11697 struct behavior *b;
11698 struct otri *splittri;
11699 struct osub *splitsubseg;
11700 vertex endpoint2;
11701 #endif 
11702 
11703 {
11704   struct osub opposubseg;
11705   vertex endpoint1;
11706   vertex torg, tdest;
11707   vertex leftvertex, rightvertex;
11708   vertex newvertex;
11709   enum insertvertexresult success;
11710   enum finddirectionresult collinear;
11711   REAL ex, ey;
11712   REAL tx, ty;
11713   REAL etx, ety;
11714   REAL split, denom;
11715   int i;
11716   triangle ptr;                       
11717   subseg sptr;                        
11718 
11719   
11720   apex(*splittri, endpoint1);
11721   org(*splittri, torg);
11722   dest(*splittri, tdest);
11723   
11724   tx = tdest[0] - torg[0];
11725   ty = tdest[1] - torg[1];
11726   ex = endpoint2[0] - endpoint1[0];
11727   ey = endpoint2[1] - endpoint1[1];
11728   etx = torg[0] - endpoint2[0];
11729   ety = torg[1] - endpoint2[1];
11730   denom = ty * ex - tx * ey;
11731   if (denom == 0.0) {
11732     printf("Internal error in segmentintersection():");
11733     printf("  Attempt to find intersection of parallel segments.\n");
11734     internalerror();
11735   }
11736   split = (ey * etx - ex * ety) / denom;
11737   
11738   newvertex = (vertex) poolalloc(&m->vertices);
11739   
11740   for (i = 0; i < 2 + m->nextras; i++) {
11741     newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11742   }
11743   setvertexmark(newvertex, mark(*splitsubseg));
11744   setvertextype(newvertex, INPUTVERTEX);
11745   if (b->verbose > 1) {
11746     printf(
11747   "  Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11748            torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11749   }
11750   
11751   success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11752   if (success != SUCCESSFULVERTEX) {
11753     printf("Internal error in segmentintersection():\n");
11754     printf("  Failure to split a segment.\n");
11755     internalerror();
11756   }
11757   
11758   setvertex2tri(newvertex, encode(*splittri));
11759   if (m->steinerleft > 0) {
11760     m->steinerleft--;
11761   }
11762 
11763   
11764   ssymself(*splitsubseg);
11765   spivot(*splitsubseg, opposubseg);
11766   sdissolve(*splitsubseg);
11767   sdissolve(opposubseg);
11768   do {
11769     setsegorg(*splitsubseg, newvertex);
11770     snextself(*splitsubseg);
11771   } while (splitsubseg->ss != m->dummysub);
11772   do {
11773     setsegorg(opposubseg, newvertex);
11774     snextself(opposubseg);
11775   } while (opposubseg.ss != m->dummysub);
11776 
11777   
11778   
11779   collinear = finddirection(m, b, splittri, endpoint1);
11780   dest(*splittri, rightvertex);
11781   apex(*splittri, leftvertex);
11782   if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11783     onextself(*splittri);
11784   } else if ((rightvertex[0] != endpoint1[0]) ||
11785              (rightvertex[1] != endpoint1[1])) {
11786     printf("Internal error in segmentintersection():\n");
11787     printf("  Topological inconsistency after splitting a segment.\n");
11788     internalerror();
11789   }
11790   
11791 }
11792 
11793 
11794 
11795 
11796 
11797 
11798 
11799 
11800 
11801 
11802 
11803 
11804 
11805 
11806 
11807 
11808 
11809 
11810 
11811 
11812 
11813 
11814 
11815 
11816 
11817 #ifdef ANSI_DECLARATORS
11818 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11819                  vertex endpoint2, int newmark)
11820 #else 
11821 int scoutsegment(m, b, searchtri, endpoint2, newmark)
11822 struct mesh *m;
11823 struct behavior *b;
11824 struct otri *searchtri;
11825 vertex endpoint2;
11826 int newmark;
11827 #endif 
11828 
11829 {
11830   struct otri crosstri;
11831   struct osub crosssubseg;
11832   vertex leftvertex, rightvertex;
11833   enum finddirectionresult collinear;
11834   subseg sptr;                      
11835 
11836   collinear = finddirection(m, b, searchtri, endpoint2);
11837   dest(*searchtri, rightvertex);
11838   apex(*searchtri, leftvertex);
11839   if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11840       ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11841     
11842     if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11843       lprevself(*searchtri);
11844     }
11845     
11846     insertsubseg(m, b, searchtri, newmark);
11847     return 1;
11848   } else if (collinear == LEFTCOLLINEAR) {
11849     
11850     
11851     lprevself(*searchtri);
11852     insertsubseg(m, b, searchtri, newmark);
11853     
11854     return scoutsegment(m, b, searchtri, endpoint2, newmark);
11855   } else if (collinear == RIGHTCOLLINEAR) {
11856     
11857     insertsubseg(m, b, searchtri, newmark);
11858     
11859     lnextself(*searchtri);
11860     
11861     return scoutsegment(m, b, searchtri, endpoint2, newmark);
11862   } else {
11863     lnext(*searchtri, crosstri);
11864     tspivot(crosstri, crosssubseg);
11865     
11866     if (crosssubseg.ss == m->dummysub) {
11867       return 0;
11868     } else {
11869       
11870       segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11871       otricopy(crosstri, *searchtri);
11872       insertsubseg(m, b, searchtri, newmark);
11873       
11874       return scoutsegment(m, b, searchtri, endpoint2, newmark);
11875     }
11876   }
11877 }
11878 
11879 
11880 
11881 
11882 
11883 
11884 
11885 
11886 
11887 
11888 
11889 
11890 
11891 
11892 
11893 
11894 
11895 
11896 
11897 
11898 #ifndef REDUCED
11899 #ifndef CDT_ONLY
11900 
11901 #ifdef ANSI_DECLARATORS
11902 void conformingedge(struct mesh *m, struct behavior *b,
11903                     vertex endpoint1, vertex endpoint2, int newmark)
11904 #else 
11905 void conformingedge(m, b, endpoint1, endpoint2, newmark)
11906 struct mesh *m;
11907 struct behavior *b;
11908 vertex endpoint1;
11909 vertex endpoint2;
11910 int newmark;
11911 #endif 
11912 
11913 {
11914   struct otri searchtri1, searchtri2;
11915   struct osub brokensubseg;
11916   vertex newvertex;
11917   vertex midvertex1, midvertex2;
11918   enum insertvertexresult success;
11919   int i;
11920   subseg sptr;                      
11921 
11922   if (b->verbose > 2) {
11923     printf("Forcing segment into triangulation by recursive splitting:\n");
11924     printf("  (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11925            endpoint2[0], endpoint2[1]);
11926   }
11927   
11928   newvertex = (vertex) poolalloc(&m->vertices);
11929   
11930   for (i = 0; i < 2 + m->nextras; i++) {
11931     newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11932   }
11933   setvertexmark(newvertex, newmark);
11934   setvertextype(newvertex, SEGMENTVERTEX);
11935   
11936   searchtri1.tri = m->dummytri;
11937   
11938   success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11939                          0, 0);
11940   if (success == DUPLICATEVERTEX) {
11941     if (b->verbose > 2) {
11942       printf("  Segment intersects existing vertex (%.12g, %.12g).\n",
11943              newvertex[0], newvertex[1]);
11944     }
11945     
11946     vertexdealloc(m, newvertex);
11947     org(searchtri1, newvertex);
11948   } else {
11949     if (success == VIOLATINGVERTEX) {
11950       if (b->verbose > 2) {
11951         printf("  Two segments intersect at (%.12g, %.12g).\n",
11952                newvertex[0], newvertex[1]);
11953       }
11954       
11955       tspivot(searchtri1, brokensubseg);
11956       success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11957                              0, 0);
11958       if (success != SUCCESSFULVERTEX) {
11959         printf("Internal error in conformingedge():\n");
11960         printf("  Failure to split a segment.\n");
11961         internalerror();
11962       }
11963     }
11964     
11965     if (m->steinerleft > 0) {
11966       m->steinerleft--;
11967     }
11968   }
11969   otricopy(searchtri1, searchtri2);
11970   
11971   
11972   
11973   
11974   
11975   finddirection(m, b, &searchtri2, endpoint2);
11976   if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11977     
11978     
11979     org(searchtri1, midvertex1);
11980     conformingedge(m, b, midvertex1, endpoint1, newmark);
11981   }
11982   if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11983     
11984     
11985     org(searchtri2, midvertex2);
11986     conformingedge(m, b, midvertex2, endpoint2, newmark);
11987   }
11988 }
11989 
11990 #endif 
11991 #endif 
11992 
11993 
11994 
11995 
11996 
11997 
11998 
11999 
12000 
12001 
12002 
12003 
12004 
12005 
12006 
12007 
12008 
12009 
12010 
12011 
12012 
12013 
12014 
12015 
12016 
12017 
12018 
12019 
12020 
12021 
12022 
12023 
12024 
12025 
12026 
12027 
12028 
12029 
12030 
12031 #ifdef ANSI_DECLARATORS
12032 void delaunayfixup(struct mesh *m, struct behavior *b,
12033                    struct otri *fixuptri, int leftside)
12034 #else 
12035 void delaunayfixup(m, b, fixuptri, leftside)
12036 struct mesh *m;
12037 struct behavior *b;
12038 struct otri *fixuptri;
12039 int leftside;
12040 #endif 
12041 
12042 {
12043   struct otri neartri;
12044   struct otri fartri;
12045   struct osub faredge;
12046   vertex nearvertex, leftvertex, rightvertex, farvertex;
12047   triangle ptr;                         
12048   subseg sptr;                      
12049 
12050   lnext(*fixuptri, neartri);
12051   sym(neartri, fartri);
12052   
12053   if (fartri.tri == m->dummytri) {
12054     return;
12055   }
12056   tspivot(neartri, faredge);
12057   if (faredge.ss != m->dummysub) {
12058     return;
12059   }
12060   
12061   apex(neartri, nearvertex);
12062   org(neartri, leftvertex);
12063   dest(neartri, rightvertex);
12064   apex(fartri, farvertex);
12065   
12066   if (leftside) {
12067     if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12068       
12069       
12070       return;
12071     }
12072   } else {
12073     if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12074       
12075       
12076       return;
12077     }
12078   }
12079   if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12080     
12081     
12082     
12083     
12084     if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12085         0.0) {
12086       return;
12087     }
12088     
12089   }        
12090   flip(m, b, &neartri);
12091   lprevself(*fixuptri);    
12092   
12093   delaunayfixup(m, b, fixuptri, leftside);
12094   delaunayfixup(m, b, &fartri, leftside);
12095 }
12096 
12097 
12098 
12099 
12100 
12101 
12102 
12103 
12104 
12105 
12106 
12107 
12108 
12109 
12110 
12111 
12112 
12113 
12114 
12115 
12116 
12117 
12118 
12119 
12120 
12121 
12122 
12123 
12124 
12125 
12126 
12127 
12128 
12129 
12130 
12131 
12132 
12133 
12134 
12135 
12136 
12137 
12138 
12139 
12140 
12141 
12142 
12143 
12144 
12145 
12146 
12147 
12148 
12149 
12150 
12151 #ifdef ANSI_DECLARATORS
12152 void constrainededge(struct mesh *m, struct behavior *b,
12153                      struct otri *starttri, vertex endpoint2, int newmark)
12154 #else 
12155 void constrainededge(m, b, starttri, endpoint2, newmark)
12156 struct mesh *m;
12157 struct behavior *b;
12158 struct otri *starttri;
12159 vertex endpoint2;
12160 int newmark;
12161 #endif 
12162 
12163 {
12164   struct otri fixuptri, fixuptri2;
12165   struct osub crosssubseg;
12166   vertex endpoint1;
12167   vertex farvertex;
12168   REAL area;
12169   int collision;
12170   int done;
12171   triangle ptr;             
12172   subseg sptr;                      
12173 
12174   org(*starttri, endpoint1);
12175   lnext(*starttri, fixuptri);
12176   flip(m, b, &fixuptri);
12177   
12178   
12179   collision = 0;
12180   done = 0;
12181   do {
12182     org(fixuptri, farvertex);
12183     
12184     
12185     if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12186       oprev(fixuptri, fixuptri2);
12187       
12188       delaunayfixup(m, b, &fixuptri, 0);
12189       delaunayfixup(m, b, &fixuptri2, 1);
12190       done = 1;
12191     } else {
12192       
12193       
12194       
12195       area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12196       if (area == 0.0) {
12197         
12198         collision = 1;
12199         oprev(fixuptri, fixuptri2);
12200         
12201         delaunayfixup(m, b, &fixuptri, 0);
12202         delaunayfixup(m, b, &fixuptri2, 1);
12203         done = 1;
12204       } else {
12205         if (area > 0.0) {        
12206           oprev(fixuptri, fixuptri2);
12207           
12208           
12209           delaunayfixup(m, b, &fixuptri2, 1);
12210           
12211           
12212           
12213           lprevself(fixuptri);
12214         } else {                
12215           delaunayfixup(m, b, &fixuptri, 0);
12216           
12217           
12218           
12219           oprevself(fixuptri);
12220         }
12221         
12222         tspivot(fixuptri, crosssubseg);
12223         if (crosssubseg.ss == m->dummysub) {
12224           flip(m, b, &fixuptri);    
12225         } else {
12226           
12227           collision = 1;
12228           
12229           segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12230           done = 1;
12231         }
12232       }
12233     }
12234   } while (!done);
12235   
12236   insertsubseg(m, b, &fixuptri, newmark);
12237   
12238   
12239   if (collision) {
12240     
12241     if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12242       constrainededge(m, b, &fixuptri, endpoint2, newmark);
12243     }
12244   }
12245 }
12246 
12247 
12248 
12249 
12250 
12251 
12252 
12253 #ifdef ANSI_DECLARATORS
12254 void insertsegment(struct mesh *m, struct behavior *b,
12255                    vertex endpoint1, vertex endpoint2, int newmark)
12256 #else 
12257 void insertsegment(m, b, endpoint1, endpoint2, newmark)
12258 struct mesh *m;
12259 struct behavior *b;
12260 vertex endpoint1;
12261 vertex endpoint2;
12262 int newmark;
12263 #endif 
12264 
12265 {
12266   struct otri searchtri1, searchtri2;
12267   triangle encodedtri;
12268   vertex checkvertex;
12269   triangle ptr;                         
12270 
12271   if (b->verbose > 1) {
12272     printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12273            endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12274   }
12275 
12276   
12277   checkvertex = (vertex) NULL;
12278   encodedtri = vertex2tri(endpoint1);
12279   if (encodedtri != (triangle) NULL) {
12280     decode(encodedtri, searchtri1);
12281     org(searchtri1, checkvertex);
12282   }
12283   if (checkvertex != endpoint1) {
12284     
12285     searchtri1.tri = m->dummytri;
12286     searchtri1.orient = 0;
12287     symself(searchtri1);
12288     
12289     if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12290       printf(
12291         "Internal error in insertsegment():  Unable to locate PSLG vertex\n");
12292       printf("  (%.12g, %.12g) in triangulation.\n",
12293              endpoint1[0], endpoint1[1]);
12294       internalerror();
12295     }
12296   }
12297   
12298   otricopy(searchtri1, m->recenttri);
12299   
12300   
12301   if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12302     
12303     return;
12304   }
12305   
12306   
12307   org(searchtri1, endpoint1);
12308 
12309   
12310   checkvertex = (vertex) NULL;
12311   encodedtri = vertex2tri(endpoint2);
12312   if (encodedtri != (triangle) NULL) {
12313     decode(encodedtri, searchtri2);
12314     org(searchtri2, checkvertex);
12315   }
12316   if (checkvertex != endpoint2) {
12317     
12318     searchtri2.tri = m->dummytri;
12319     searchtri2.orient = 0;
12320     symself(searchtri2);
12321     
12322     if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12323       printf(
12324         "Internal error in insertsegment():  Unable to locate PSLG vertex\n");
12325       printf("  (%.12g, %.12g) in triangulation.\n",
12326              endpoint2[0], endpoint2[1]);
12327       internalerror();
12328     }
12329   }
12330   
12331   otricopy(searchtri2, m->recenttri);
12332   
12333   
12334   if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12335     
12336     return;
12337   }
12338   
12339   
12340   org(searchtri2, endpoint2);
12341 
12342 #ifndef REDUCED
12343 #ifndef CDT_ONLY
12344   if (b->splitseg) {
12345     
12346     conformingedge(m, b, endpoint1, endpoint2, newmark);
12347   } else {
12348 #endif 
12349 #endif 
12350     
12351     constrainededge(m, b, &searchtri1, endpoint2, newmark);
12352 #ifndef REDUCED
12353 #ifndef CDT_ONLY
12354   }
12355 #endif 
12356 #endif 
12357 }
12358 
12359 
12360 
12361 
12362 
12363 
12364 
12365 #ifdef ANSI_DECLARATORS
12366 void markhull(struct mesh *m, struct behavior *b)
12367 #else 
12368 void markhull(m, b)
12369 struct mesh *m;
12370 struct behavior *b;
12371 #endif 
12372 
12373 {
12374   struct otri hulltri;
12375   struct otri nexttri;
12376   struct otri starttri;
12377   triangle ptr;             
12378 
12379   
12380   hulltri.tri = m->dummytri;
12381   hulltri.orient = 0;
12382   symself(hulltri);
12383   
12384   otricopy(hulltri, starttri);
12385   
12386   do {
12387     
12388     insertsubseg(m, b, &hulltri, 1);
12389     
12390     lnextself(hulltri);
12391     oprev(hulltri, nexttri);
12392     while (nexttri.tri != m->dummytri) {
12393       otricopy(nexttri, hulltri);
12394       oprev(hulltri, nexttri);
12395     }
12396   } while (!otriequal(hulltri, starttri));
12397 }
12398 
12399 
12400 
12401 
12402 
12403 
12404 
12405 
12406 
12407 
12408 
12409 #ifdef TRILIBRARY
12410 
12411 #ifdef ANSI_DECLARATORS
12412 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12413                   int *segmentmarkerlist, int numberofsegments)
12414 #else 
12415 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12416 struct mesh *m;
12417 struct behavior *b;
12418 int *segmentlist;
12419 int *segmentmarkerlist;
12420 int numberofsegments;
12421 #endif 
12422 
12423 #else 
12424 
12425 #ifdef ANSI_DECLARATORS
12426 void formskeleton(struct mesh *m, struct behavior *b,
12427                   FILE *polyfile, char *polyfilename)
12428 #else 
12429 void formskeleton(m, b, polyfile, polyfilename)
12430 struct mesh *m;
12431 struct behavior *b;
12432 FILE *polyfile;
12433 char *polyfilename;
12434 #endif 
12435 
12436 #endif 
12437 
12438 {
12439 #ifdef TRILIBRARY
12440   char polyfilename[6];
12441   int index;
12442 #else 
12443   char inputline[INPUTLINESIZE];
12444   char *stringptr;
12445 #endif 
12446   vertex endpoint1, endpoint2;
12447   int segmentmarkers;
12448   int end1, end2;
12449   int boundmarker;
12450   int i;
12451 
12452   if (b->poly) {
12453     if (!b->quiet) {
12454       printf("Recovering segments in Delaunay triangulation.\n");
12455     }
12456 #ifdef TRILIBRARY
12457     strcpy(polyfilename, "input");
12458     m->insegments = numberofsegments;
12459     segmentmarkers = segmentmarkerlist != (int *) NULL;
12460     index = 0;
12461 #else 
12462     
12463     
12464     stringptr = readline(inputline, polyfile, polyfilename);
12465     m->insegments = (int) strtol(stringptr, &stringptr, 0);
12466     stringptr = findfield(stringptr);
12467     if (*stringptr == '\0') {
12468       segmentmarkers = 0;
12469     } else {
12470       segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12471     }
12472 #endif 
12473     
12474     
12475     if (m->triangles.items == 0) {
12476       return;
12477     }
12478 
12479     
12480     
12481     if (m->insegments > 0) {
12482       makevertexmap(m, b);
12483       if (b->verbose) {
12484         printf("  Recovering PSLG segments.\n");
12485       }
12486     }
12487 
12488     boundmarker = 0;
12489     
12490     for (i = 0; i < m->insegments; i++) {
12491 #ifdef TRILIBRARY
12492       end1 = segmentlist[index++];
12493       end2 = segmentlist[index++];
12494       if (segmentmarkers) {
12495         boundmarker = segmentmarkerlist[i];
12496       }
12497 #else 
12498       stringptr = readline(inputline, polyfile, b->inpolyfilename);
12499       stringptr = findfield(stringptr);
12500       if (*stringptr == '\0') {
12501         printf("Error:  Segment %d has no endpoints in %s.\n",
12502                b->firstnumber + i, polyfilename);
12503         triexit(1);
12504       } else {
12505         end1 = (int) strtol(stringptr, &stringptr, 0);
12506       }
12507       stringptr = findfield(stringptr);
12508       if (*stringptr == '\0') {
12509         printf("Error:  Segment %d is missing its second endpoint in %s.\n",
12510                b->firstnumber + i, polyfilename);
12511         triexit(1);
12512       } else {
12513         end2 = (int) strtol(stringptr, &stringptr, 0);
12514       }
12515       if (segmentmarkers) {
12516         stringptr = findfield(stringptr);
12517         if (*stringptr == '\0') {
12518           boundmarker = 0;
12519         } else {
12520           boundmarker = (int) strtol(stringptr, &stringptr, 0);
12521         }
12522       }
12523 #endif 
12524       if ((end1 < b->firstnumber) ||
12525           (end1 >= b->firstnumber + m->invertices)) {
12526         if (!b->quiet) {
12527           printf("Warning:  Invalid first endpoint of segment %d in %s.\n",
12528                  b->firstnumber + i, polyfilename);
12529         }
12530       } else if ((end2 < b->firstnumber) ||
12531                  (end2 >= b->firstnumber + m->invertices)) {
12532         if (!b->quiet) {
12533           printf("Warning:  Invalid second endpoint of segment %d in %s.\n",
12534                  b->firstnumber + i, polyfilename);
12535         }
12536       } else {
12537         
12538         endpoint1 = getvertex(m, b, end1);
12539         endpoint2 = getvertex(m, b, end2);
12540         if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12541           if (!b->quiet) {
12542             printf("Warning:  Endpoints of segment %d are coincident in %s.\n",
12543                    b->firstnumber + i, polyfilename);
12544           }
12545         } else {
12546           insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12547         }
12548       }
12549     }
12550   } else {
12551     m->insegments = 0;
12552   }
12553   if (b->convex || !b->poly) {
12554     
12555     if (b->verbose) {
12556       printf("  Enclosing convex hull with segments.\n");
12557     }
12558     markhull(m, b);
12559   }
12560 }
12561 
12564 
12565 
12566 
12570 
12571 
12572 
12573 
12574 
12575 
12576 
12577 
12578 #ifdef ANSI_DECLARATORS
12579 void infecthull(struct mesh *m, struct behavior *b)
12580 #else 
12581 void infecthull(m, b)
12582 struct mesh *m;
12583 struct behavior *b;
12584 #endif 
12585 
12586 {
12587   struct otri hulltri;
12588   struct otri nexttri;
12589   struct otri starttri;
12590   struct osub hullsubseg;
12591   triangle **deadtriangle;
12592   vertex horg, hdest;
12593   triangle ptr;                         
12594   subseg sptr;                      
12595 
12596   if (b->verbose) {
12597     printf("  Marking concavities (external triangles) for elimination.\n");
12598   }
12599   
12600   hulltri.tri = m->dummytri;
12601   hulltri.orient = 0;
12602   symself(hulltri);
12603   
12604   otricopy(hulltri, starttri);
12605   
12606   do {
12607     
12608     if (!infected(hulltri)) {
12609       
12610       tspivot(hulltri, hullsubseg);
12611       if (hullsubseg.ss == m->dummysub) {
12612         
12613         if (!infected(hulltri)) {
12614           infect(hulltri);
12615           deadtriangle = (triangle **) poolalloc(&m->viri);
12616           *deadtriangle = hulltri.tri;
12617         }
12618       } else {
12619         
12620         if (mark(hullsubseg) == 0) {
12621           setmark(hullsubseg, 1);
12622           org(hulltri, horg);
12623           dest(hulltri, hdest);
12624           if (vertexmark(horg) == 0) {
12625             setvertexmark(horg, 1);
12626           }
12627           if (vertexmark(hdest) == 0) {
12628             setvertexmark(hdest, 1);
12629           }
12630         }
12631       }
12632     }
12633     
12634     lnextself(hulltri);
12635     oprev(hulltri, nexttri);
12636     while (nexttri.tri != m->dummytri) {
12637       otricopy(nexttri, hulltri);
12638       oprev(hulltri, nexttri);
12639     }
12640   } while (!otriequal(hulltri, starttri));
12641 }
12642 
12643 
12644 
12645 
12646 
12647 
12648 
12649 
12650 
12651 
12652 
12653 
12654 
12655 
12656 
12657 
12658 
12659 
12660 #ifdef ANSI_DECLARATORS
12661 void plague(struct mesh *m, struct behavior *b)
12662 #else 
12663 void plague(m, b)
12664 struct mesh *m;
12665 struct behavior *b;
12666 #endif 
12667 
12668 {
12669   struct otri testtri;
12670   struct otri neighbor;
12671   triangle **virusloop;
12672   triangle **deadtriangle;
12673   struct osub neighborsubseg;
12674   vertex testvertex;
12675   vertex norg, ndest;
12676   vertex deadorg, deaddest, deadapex;
12677   int killorg;
12678   triangle ptr;             
12679   subseg sptr;                      
12680 
12681   if (b->verbose) {
12682     printf("  Marking neighbors of marked triangles.\n");
12683   }
12684   
12685   
12686   traversalinit(&m->viri);
12687   virusloop = (triangle **) traverse(&m->viri);
12688   while (virusloop != (triangle **) NULL) {
12689     testtri.tri = *virusloop;
12690     
12691     
12692     
12693     
12694     uninfect(testtri);
12695     if (b->verbose > 2) {
12696       
12697       
12698       testtri.orient = 0;
12699       org(testtri, deadorg);
12700       dest(testtri, deaddest);
12701       apex(testtri, deadapex);
12702       printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12703              deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12704              deadapex[0], deadapex[1]);
12705     }
12706     
12707     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12708       
12709       sym(testtri, neighbor);
12710       
12711       tspivot(testtri, neighborsubseg);
12712       
12713       if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12714         if (neighborsubseg.ss != m->dummysub) {
12715           
12716           
12717           
12718           subsegdealloc(m, neighborsubseg.ss);
12719           if (neighbor.tri != m->dummytri) {
12720             
12721             
12722             uninfect(neighbor);
12723             tsdissolve(neighbor);
12724             infect(neighbor);
12725           }
12726         }
12727       } else {                   
12728         if (neighborsubseg.ss == m->dummysub) {
12729           
12730           
12731           if (b->verbose > 2) {
12732             org(neighbor, deadorg);
12733             dest(neighbor, deaddest);
12734             apex(neighbor, deadapex);
12735             printf(
12736               "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12737                    deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12738                    deadapex[0], deadapex[1]);
12739           }
12740           infect(neighbor);
12741           
12742           deadtriangle = (triangle **) poolalloc(&m->viri);
12743           *deadtriangle = neighbor.tri;
12744         } else {               
12745           
12746           stdissolve(neighborsubseg);
12747           
12748           if (mark(neighborsubseg) == 0) {
12749             setmark(neighborsubseg, 1);
12750           }
12751           org(neighbor, norg);
12752           dest(neighbor, ndest);
12753           if (vertexmark(norg) == 0) {
12754             setvertexmark(norg, 1);
12755           }
12756           if (vertexmark(ndest) == 0) {
12757             setvertexmark(ndest, 1);
12758           }
12759         }
12760       }
12761     }
12762     
12763     
12764     infect(testtri);
12765     virusloop = (triangle **) traverse(&m->viri);
12766   }
12767 
12768   if (b->verbose) {
12769     printf("  Deleting marked triangles.\n");
12770   }
12771 
12772   traversalinit(&m->viri);
12773   virusloop = (triangle **) traverse(&m->viri);
12774   while (virusloop != (triangle **) NULL) {
12775     testtri.tri = *virusloop;
12776 
12777     
12778     
12779     
12780     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12781       org(testtri, testvertex);
12782       
12783       if (testvertex != (vertex) NULL) {
12784         killorg = 1;
12785         
12786         setorg(testtri, NULL);
12787         
12788         onext(testtri, neighbor);
12789         
12790         while ((neighbor.tri != m->dummytri) &&
12791                (!otriequal(neighbor, testtri))) {
12792           if (infected(neighbor)) {
12793             
12794             setorg(neighbor, NULL);
12795           } else {
12796             
12797             killorg = 0;
12798           }
12799           
12800           onextself(neighbor);
12801         }
12802         
12803         if (neighbor.tri == m->dummytri) {
12804           
12805           oprev(testtri, neighbor);
12806           
12807           while (neighbor.tri != m->dummytri) {
12808             if (infected(neighbor)) {
12809             
12810               setorg(neighbor, NULL);
12811             } else {
12812               
12813               killorg = 0;
12814             }
12815             
12816             oprevself(neighbor);
12817           }
12818         }
12819         if (killorg) {
12820           if (b->verbose > 1) {
12821             printf("    Deleting vertex (%.12g, %.12g)\n",
12822                    testvertex[0], testvertex[1]);
12823           }
12824           setvertextype(testvertex, UNDEADVERTEX);
12825           m->undeads++;
12826         }
12827       }
12828     }
12829 
12830     
12831     
12832     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12833       sym(testtri, neighbor);
12834       if (neighbor.tri == m->dummytri) {
12835         
12836         
12837         
12838         m->hullsize--;
12839       } else {
12840         
12841         dissolve(neighbor);
12842         
12843         
12844         m->hullsize++;
12845       }
12846     }
12847     
12848     triangledealloc(m, testtri.tri);
12849     virusloop = (triangle **) traverse(&m->viri);
12850   }
12851   
12852   poolrestart(&m->viri);
12853 }
12854 
12855 
12856 
12857 
12858 
12859 
12860 
12861 
12862 
12863 
12864 
12865 
12866 
12867 
12868 
12869 
12870 #ifdef ANSI_DECLARATORS
12871 void regionplague(struct mesh *m, struct behavior *b,
12872                   REAL attribute, REAL area)
12873 #else 
12874 void regionplague(m, b, attribute, area)
12875 struct mesh *m;
12876 struct behavior *b;
12877 REAL attribute;
12878 REAL area;
12879 #endif 
12880 
12881 {
12882   struct otri testtri;
12883   struct otri neighbor;
12884   triangle **virusloop;
12885   triangle **regiontri;
12886   struct osub neighborsubseg;
12887   vertex regionorg, regiondest, regionapex;
12888   triangle ptr;             
12889   subseg sptr;                      
12890 
12891   if (b->verbose > 1) {
12892     printf("  Marking neighbors of marked triangles.\n");
12893   }
12894   
12895   
12896   
12897   traversalinit(&m->viri);
12898   virusloop = (triangle **) traverse(&m->viri);
12899   while (virusloop != (triangle **) NULL) {
12900     testtri.tri = *virusloop;
12901     
12902     
12903     
12904     
12905     uninfect(testtri);
12906     if (b->regionattrib) {
12907       
12908       setelemattribute(testtri, m->eextras, attribute);
12909     }
12910     if (b->vararea) {
12911       
12912       setareabound(testtri, area);
12913     }
12914     if (b->verbose > 2) {
12915       
12916       
12917       testtri.orient = 0;
12918       org(testtri, regionorg);
12919       dest(testtri, regiondest);
12920       apex(testtri, regionapex);
12921       printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12922              regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12923              regionapex[0], regionapex[1]);
12924     }
12925     
12926     for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12927       
12928       sym(testtri, neighbor);
12929       
12930       tspivot(testtri, neighborsubseg);
12931       
12932       
12933       if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12934           && (neighborsubseg.ss == m->dummysub)) {
12935         if (b->verbose > 2) {
12936           org(neighbor, regionorg);
12937           dest(neighbor, regiondest);
12938           apex(neighbor, regionapex);
12939           printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12940                  regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12941                  regionapex[0], regionapex[1]);
12942         }
12943         
12944         infect(neighbor);
12945         
12946         regiontri = (triangle **) poolalloc(&m->viri);
12947         *regiontri = neighbor.tri;
12948       }
12949     }
12950     
12951     
12952     infect(testtri);
12953     virusloop = (triangle **) traverse(&m->viri);
12954   }
12955 
12956   
12957   if (b->verbose > 1) {
12958     printf("  Unmarking marked triangles.\n");
12959   }
12960   traversalinit(&m->viri);
12961   virusloop = (triangle **) traverse(&m->viri);
12962   while (virusloop != (triangle **) NULL) {
12963     testtri.tri = *virusloop;
12964     uninfect(testtri);
12965     virusloop = (triangle **) traverse(&m->viri);
12966   }
12967   
12968   poolrestart(&m->viri);
12969 }
12970 
12971 
12972 
12973 
12974 
12975 
12976 
12977 
12978 
12979 
12980 
12981 
12982 
12983 #ifdef ANSI_DECLARATORS
12984 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12985                 REAL *regionlist, int regions)
12986 #else 
12987 void carveholes(m, b, holelist, holes, regionlist, regions)
12988 struct mesh *m;
12989 struct behavior *b;
12990 REAL *holelist;
12991 int holes;
12992 REAL *regionlist;
12993 int regions;
12994 #endif 
12995 
12996 {
12997   struct otri searchtri;
12998   struct otri triangleloop;
12999   struct otri *regiontris;
13000   triangle **holetri;
13001   triangle **regiontri;
13002   vertex searchorg, searchdest;
13003   enum locateresult intersect;
13004   int i;
13005   triangle ptr;                         
13006 
13007   if (!(b->quiet || (b->noholes && b->convex))) {
13008     printf("Removing unwanted triangles.\n");
13009     if (b->verbose && (holes > 0)) {
13010       printf("  Marking holes for elimination.\n");
13011     }
13012   }
13013 
13014   if (regions > 0) {
13015     
13016     regiontris = (struct otri *) trimalloc(regions *
13017                                            (int) sizeof(struct otri));
13018   } else {
13019     regiontris = (struct otri *) NULL;
13020   }
13021 
13022   if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13023     
13024     
13025     poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13026   }
13027 
13028   if (!b->convex) {
13029     
13030     
13031     infecthull(m, b);
13032   }
13033 
13034   if ((holes > 0) && !b->noholes) {
13035     
13036     for (i = 0; i < 2 * holes; i += 2) {
13037       
13038       if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13039           && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13040         
13041         searchtri.tri = m->dummytri;
13042         searchtri.orient = 0;
13043         symself(searchtri);
13044         
13045         
13046         
13047         org(searchtri, searchorg);
13048         dest(searchtri, searchdest);
13049         if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13050             0.0) {
13051           
13052           intersect = locate(m, b, &holelist[i], &searchtri);
13053           if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13054             
13055             
13056             infect(searchtri);
13057             holetri = (triangle **) poolalloc(&m->viri);
13058             *holetri = searchtri.tri;
13059           }
13060         }
13061       }
13062     }
13063   }
13064 
13065   
13066   
13067   
13068   
13069   
13070   
13071   if (regions > 0) {
13072     
13073     for (i = 0; i < regions; i++) {
13074       regiontris[i].tri = m->dummytri;
13075       
13076       if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13077           (regionlist[4 * i + 1] >= m->ymin) &&
13078           (regionlist[4 * i + 1] <= m->ymax)) {
13079         
13080         searchtri.tri = m->dummytri;
13081         searchtri.orient = 0;
13082         symself(searchtri);
13083         
13084         
13085         
13086         org(searchtri, searchorg);
13087         dest(searchtri, searchdest);
13088         if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) >
13089             0.0) {
13090           
13091           intersect = locate(m, b, ®ionlist[4 * i], &searchtri);
13092           if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13093             
13094             
13095             otricopy(searchtri, regiontris[i]);
13096           }
13097         }
13098       }
13099     }
13100   }
13101 
13102   if (m->viri.items > 0) {
13103     
13104     plague(m, b);
13105   }
13106   
13107 
13108   if (regions > 0) {
13109     if (!b->quiet) {
13110       if (b->regionattrib) {
13111         if (b->vararea) {
13112           printf("Spreading regional attributes and area constraints.\n");
13113         } else {
13114           printf("Spreading regional attributes.\n");
13115         }
13116       } else { 
13117         printf("Spreading regional area constraints.\n");
13118       }
13119     }
13120     if (b->regionattrib && !b->refine) {
13121       
13122       traversalinit(&m->triangles);
13123       triangleloop.orient = 0;
13124       triangleloop.tri = triangletraverse(m);
13125       while (triangleloop.tri != (triangle *) NULL) {
13126         setelemattribute(triangleloop, m->eextras, 0.0);
13127         triangleloop.tri = triangletraverse(m);
13128       }
13129     }
13130     for (i = 0; i < regions; i++) {
13131       if (regiontris[i].tri != m->dummytri) {
13132         
13133         
13134         if (!deadtri(regiontris[i].tri)) {
13135           
13136           infect(regiontris[i]);
13137           regiontri = (triangle **) poolalloc(&m->viri);
13138           *regiontri = regiontris[i].tri;
13139           
13140           regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13141           
13142         }
13143       }
13144     }
13145     if (b->regionattrib && !b->refine) {
13146       
13147       m->eextras++;
13148     }
13149   }
13150 
13151   
13152   if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13153     pooldeinit(&m->viri);
13154   }
13155   if (regions > 0) {
13156     trifree((VOID *) regiontris);
13157   }
13158 }
13159 
13162 
13163 
13164 
13168 
13169 
13170 
13171 
13172 
13173 
13174 
13175 #ifndef CDT_ONLY
13176 
13177 #ifdef ANSI_DECLARATORS
13178 void tallyencs(struct mesh *m, struct behavior *b)
13179 #else 
13180 void tallyencs(m, b)
13181 struct mesh *m;
13182 struct behavior *b;
13183 #endif 
13184 
13185 {
13186   struct osub subsegloop;
13187   int dummy;
13188 
13189   traversalinit(&m->subsegs);
13190   subsegloop.ssorient = 0;
13191   subsegloop.ss = subsegtraverse(m);
13192   while (subsegloop.ss != (subseg *) NULL) {
13193     
13194     dummy = checkseg4encroach(m, b, &subsegloop);
13195     subsegloop.ss = subsegtraverse(m);
13196   }
13197 }
13198 
13199 #endif 
13200 
13201 
13202 
13203 
13204 
13205 
13206 
13207 #ifndef CDT_ONLY
13208 
13209 void precisionerror()
13210 {
13211   printf("Try increasing the area criterion and/or reducing the minimum\n");
13212   printf("  allowable angle so that tiny triangles are not created.\n");
13213 #ifdef SINGLE
13214   printf("Alternatively, try recompiling me with double precision\n");
13215   printf("  arithmetic (by removing \"#define SINGLE\" from the\n");
13216   printf("  source file or \"-DSINGLE\" from the makefile).\n");
13217 #endif 
13218 }
13219 
13220 #endif 
13221 
13222 
13223 
13224 
13225 
13226 
13227 
13228 
13229 
13230 
13231 
13232 
13233 
13234 
13235 
13236 #ifndef CDT_ONLY
13237 
13238 #ifdef ANSI_DECLARATORS
13239 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13240 #else 
13241 void splitencsegs(m, b, triflaws)
13242 struct mesh *m;
13243 struct behavior *b;
13244 int triflaws;
13245 #endif 
13246 
13247 {
13248   struct otri enctri;
13249   struct otri testtri;
13250   struct osub testsh;
13251   struct osub currentenc;
13252   struct badsubseg *encloop;
13253   vertex eorg, edest, eapex;
13254   vertex newvertex;
13255   enum insertvertexresult success;
13256   REAL segmentlength, nearestpoweroftwo;
13257   REAL split;
13258   REAL multiplier, divisor;
13259   int acuteorg, acuteorg2, acutedest, acutedest2;
13260   int dummy;
13261   int i;
13262   triangle ptr;                     
13263   subseg sptr;                        
13264 
13265   
13266   
13267   while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13268     traversalinit(&m->badsubsegs);
13269     encloop = badsubsegtraverse(m);
13270     while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13271       sdecode(encloop->encsubseg, currentenc);
13272       sorg(currentenc, eorg);
13273       sdest(currentenc, edest);
13274       
13275       
13276       
13277       
13278       if (!deadsubseg(currentenc.ss) &&
13279           (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13280         
13281         
13282         
13283         
13284         
13285         
13286         
13287         
13288         
13289         
13290         
13291         
13292         
13293         
13294 
13295         
13296         stpivot(currentenc, enctri);
13297         lnext(enctri, testtri);
13298         tspivot(testtri, testsh);
13299         acuteorg = testsh.ss != m->dummysub;
13300         
13301         lnextself(testtri);
13302         tspivot(testtri, testsh);
13303         acutedest = testsh.ss != m->dummysub;
13304 
13305         
13306         
13307         
13308         if (!b->conformdel && !acuteorg && !acutedest) {
13309           apex(enctri, eapex);
13310           while ((vertextype(eapex) == FREEVERTEX) &&
13311                  ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13312                   (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13313             deletevertex(m, b, &testtri);
13314             stpivot(currentenc, enctri);
13315             apex(enctri, eapex);
13316             lprev(enctri, testtri);
13317           }
13318         }
13319 
13320         
13321         
13322         sym(enctri, testtri);
13323         if (testtri.tri != m->dummytri) {
13324           
13325           lnextself(testtri);
13326           tspivot(testtri, testsh);
13327           acutedest2 = testsh.ss != m->dummysub;
13328           acutedest = acutedest || acutedest2;
13329           
13330           lnextself(testtri);
13331           tspivot(testtri, testsh);
13332           acuteorg2 = testsh.ss != m->dummysub;
13333           acuteorg = acuteorg || acuteorg2;
13334 
13335           
13336           if (!b->conformdel && !acuteorg2 && !acutedest2) {
13337             org(testtri, eapex);
13338             while ((vertextype(eapex) == FREEVERTEX) &&
13339                    ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13340                     (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13341               deletevertex(m, b, &testtri);
13342               sym(enctri, testtri);
13343               apex(testtri, eapex);
13344               lprevself(testtri);
13345             }
13346           }
13347         }
13348 
13349         
13350         
13351         if (acuteorg || acutedest) {
13352           segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13353                                (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13354           
13355           
13356           nearestpoweroftwo = 1.0;
13357           while (segmentlength > 3.0 * nearestpoweroftwo) {
13358             nearestpoweroftwo *= 2.0;
13359           }
13360           while (segmentlength < 1.5 * nearestpoweroftwo) {
13361             nearestpoweroftwo *= 0.5;
13362           }
13363           
13364           split = nearestpoweroftwo / segmentlength;
13365           if (acutedest) {
13366             split = 1.0 - split;
13367           }
13368         } else {
13369           
13370           
13371           split = 0.5;
13372         }
13373 
13374         
13375         newvertex = (vertex) poolalloc(&m->vertices);
13376         
13377         for (i = 0; i < 2 + m->nextras; i++) {
13378           newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13379         }
13380 
13381         if (!b->noexact) {
13382           
13383           
13384           
13385           multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13386           divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13387                      (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13388           if ((multiplier != 0.0) && (divisor != 0.0)) {
13389             multiplier = multiplier / divisor;
13390             
13391             if (multiplier == multiplier) {
13392               newvertex[0] += multiplier * (edest[1] - eorg[1]);
13393               newvertex[1] += multiplier * (eorg[0] - edest[0]);
13394             }
13395           }
13396         }
13397 
13398         setvertexmark(newvertex, mark(currentenc));
13399         setvertextype(newvertex, SEGMENTVERTEX);
13400         if (b->verbose > 1) {
13401           printf(
13402   "  Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13403                  eorg[0], eorg[1], edest[0], edest[1],
13404                  newvertex[0], newvertex[1]);
13405         }
13406         
13407         if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13408             ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13409           printf("Error:  Ran out of precision at (%.12g, %.12g).\n",
13410                  newvertex[0], newvertex[1]);
13411           printf("I attempted to split a segment to a smaller size than\n");
13412           printf("  can be accommodated by the finite precision of\n");
13413           printf("  floating point arithmetic.\n");
13414           precisionerror();
13415           triexit(1);
13416         }
13417         
13418         success = insertvertex(m, b, newvertex, &enctri, ¤tenc,
13419                                1, triflaws);
13420         if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13421           printf("Internal error in splitencsegs():\n");
13422           printf("  Failure to split a segment.\n");
13423           internalerror();
13424         }
13425         if (m->steinerleft > 0) {
13426           m->steinerleft--;
13427         }
13428         
13429         dummy = checkseg4encroach(m, b, ¤tenc);
13430         snextself(currentenc);
13431         dummy = checkseg4encroach(m, b, ¤tenc);
13432       }
13433 
13434       badsubsegdealloc(m, encloop);
13435       encloop = badsubsegtraverse(m);
13436     }
13437   }
13438 }
13439 
13440 #endif 
13441 
13442 
13443 
13444 
13445 
13446 
13447 
13448 #ifndef CDT_ONLY
13449 
13450 #ifdef ANSI_DECLARATORS
13451 void tallyfaces(struct mesh *m, struct behavior *b)
13452 #else 
13453 void tallyfaces(m, b)
13454 struct mesh *m;
13455 struct behavior *b;
13456 #endif 
13457 
13458 {
13459   struct otri triangleloop;
13460 
13461   if (b->verbose) {
13462     printf("  Making a list of bad triangles.\n");
13463   }
13464   traversalinit(&m->triangles);
13465   triangleloop.orient = 0;
13466   triangleloop.tri = triangletraverse(m);
13467   while (triangleloop.tri != (triangle *) NULL) {
13468     
13469     testtriangle(m, b, &triangleloop);
13470     triangleloop.tri = triangletraverse(m);
13471   }
13472 }
13473 
13474 #endif 
13475 
13476 
13477 
13478 
13479 
13480 
13481 
13482 
13483 
13484 #ifndef CDT_ONLY
13485 
13486 #ifdef ANSI_DECLARATORS
13487 void splittriangle(struct mesh *m, struct behavior *b,
13488                    struct badtriang *badtri)
13489 #else 
13490 void splittriangle(m, b, badtri)
13491 struct mesh *m;
13492 struct behavior *b;
13493 struct badtriang *badtri;
13494 #endif 
13495 
13496 {
13497   struct otri badotri;
13498   vertex borg, bdest, bapex;
13499   vertex newvertex;
13500   REAL xi, eta;
13501   enum insertvertexresult success;
13502   int errorflag;
13503   int i;
13504 
13505   decode(badtri->poortri, badotri);
13506   org(badotri, borg);
13507   dest(badotri, bdest);
13508   apex(badotri, bapex);
13509   
13510   
13511   
13512   if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13513       (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13514     if (b->verbose > 1) {
13515       printf("  Splitting this triangle at its circumcenter:\n");
13516       printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13517              borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13518     }
13519 
13520     errorflag = 0;
13521     
13522     newvertex = (vertex) poolalloc(&m->vertices);
13523     findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13524 
13525     
13526     if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13527         ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13528         ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13529       if (!b->quiet) {
13530         printf(
13531              "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.\n",
13532                newvertex[0], newvertex[1]);
13533         errorflag = 1;
13534       }
13535       vertexdealloc(m, newvertex);
13536     } else {
13537       for (i = 2; i < 2 + m->nextras; i++) {
13538         
13539         newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13540                               + eta * (bapex[i] - borg[i]);
13541       }
13542       
13543       
13544       setvertexmark(newvertex, 0);
13545       setvertextype(newvertex, FREEVERTEX);
13546 
13547       
13548       
13549       
13550       
13551       
13552       
13553       
13554       if (eta < xi) {
13555         lprevself(badotri);
13556       }
13557 
13558       
13559       
13560       success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13561                              1, 1);
13562       if (success == SUCCESSFULVERTEX) {
13563         if (m->steinerleft > 0) {
13564           m->steinerleft--;
13565         }
13566       } else if (success == ENCROACHINGVERTEX) {
13567         
13568         
13569         undovertex(m, b);
13570         if (b->verbose > 1) {
13571           printf("  Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13572         }
13573         vertexdealloc(m, newvertex);
13574       } else if (success == VIOLATINGVERTEX) {
13575         
13576         
13577         vertexdealloc(m, newvertex);
13578       } else {                                 
13579         
13580         if (!b->quiet) {
13581           printf(
13582             "Warning:  New vertex (%.12g, %.12g) falls on existing vertex.\n",
13583                  newvertex[0], newvertex[1]);
13584           errorflag = 1;
13585         }
13586         vertexdealloc(m, newvertex);
13587       }
13588     }
13589     if (errorflag) {
13590       if (b->verbose) {
13591         printf("  The new vertex is at the circumcenter of triangle\n");
13592         printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13593                borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13594       }
13595       printf("This probably means that I am trying to refine triangles\n");
13596       printf("  to a smaller size than can be accommodated by the finite\n");
13597       printf("  precision of floating point arithmetic.  (You can be\n");
13598       printf("  sure of this if I fail to terminate.)\n");
13599       precisionerror();
13600     }
13601   }
13602 }
13603 
13604 #endif 
13605 
13606 
13607 
13608 
13609 
13610 
13611 
13612 
13613 #ifndef CDT_ONLY
13614 
13615 #ifdef ANSI_DECLARATORS
13616 void enforcequality(struct mesh *m, struct behavior *b)
13617 #else 
13618 void enforcequality(m, b)
13619 struct mesh *m;
13620 struct behavior *b;
13621 #endif 
13622 
13623 {
13624   struct badtriang *badtri;
13625   int i;
13626 
13627   if (!b->quiet) {
13628     printf("Adding Steiner points to enforce quality.\n");
13629   }
13630   
13631   poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13632            BADSUBSEGPERBLOCK, 0);
13633   if (b->verbose) {
13634     printf("  Looking for encroached subsegments.\n");
13635   }
13636   
13637   tallyencs(m, b);
13638   if (b->verbose && (m->badsubsegs.items > 0)) {
13639     printf("  Splitting encroached subsegments.\n");
13640   }
13641   
13642   splitencsegs(m, b, 0);
13643   
13644   
13645 
13646   
13647   if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13648     
13649     poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13650              BADTRIPERBLOCK, 0);
13651     
13652     for (i = 0; i < 4096; i++) {
13653       m->queuefront[i] = (struct badtriang *) NULL;
13654     }
13655     m->firstnonemptyq = -1;
13656     
13657     tallyfaces(m, b);
13658     
13659     poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13660              FLIPSTACKERPERBLOCK, 0);
13661     m->checkquality = 1;
13662     if (b->verbose) {
13663       printf("  Splitting bad triangles.\n");
13664     }
13665     while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13666       
13667       badtri = dequeuebadtriang(m);
13668       splittriangle(m, b, badtri);
13669       if (m->badsubsegs.items > 0) {
13670         
13671         enqueuebadtriang(m, b, badtri);
13672         
13673         
13674         splitencsegs(m, b, 1);
13675       } else {
13676         
13677         pooldealloc(&m->badtriangles, (VOID *) badtri);
13678       }
13679     }
13680   }
13681   
13682   
13683   
13684 
13685   
13686   if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13687       (m->steinerleft == 0)) {
13688     printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
13689     if (m->badsubsegs.items == 1) {
13690       printf("  one encroached subsegment, and therefore might not be truly\n"
13691              );
13692     } else {
13693       printf("  %ld encroached subsegments, and therefore might not be truly\n"
13694              , m->badsubsegs.items);
13695     }
13696     printf("  Delaunay.  If the Delaunay property is important to you,\n");
13697     printf("  try increasing the number of Steiner points (controlled by\n");
13698     printf("  the -S switch) slightly and try again.\n\n");
13699   }
13700 }
13701 
13702 #endif 
13703 
13706 
13707 
13708 
13709 
13710 
13711 
13712 
13713 
13714 #ifdef ANSI_DECLARATORS
13715 void highorder(struct mesh *m, struct behavior *b)
13716 #else 
13717 void highorder(m, b)
13718 struct mesh *m;
13719 struct behavior *b;
13720 #endif 
13721 
13722 {
13723   struct otri triangleloop, trisym;
13724   struct osub checkmark;
13725   vertex newvertex;
13726   vertex torg, tdest;
13727   int i;
13728   triangle ptr;                         
13729   subseg sptr;                      
13730 
13731   if (!b->quiet) {
13732     printf("Adding vertices for second-order triangles.\n");
13733   }
13734   
13735   
13736   
13737   
13738   
13739   m->vertices.deaditemstack = (VOID *) NULL;
13740 
13741   traversalinit(&m->triangles);
13742   triangleloop.tri = triangletraverse(m);
13743   
13744   
13745   
13746   
13747   
13748   
13749   while (triangleloop.tri != (triangle *) NULL) {
13750     for (triangleloop.orient = 0; triangleloop.orient < 3;
13751          triangleloop.orient++) {
13752       sym(triangleloop, trisym);
13753       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13754         org(triangleloop, torg);
13755         dest(triangleloop, tdest);
13756         
13757         
13758         newvertex = (vertex) poolalloc(&m->vertices);
13759         for (i = 0; i < 2 + m->nextras; i++) {
13760           newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13761         }
13762         
13763         
13764         setvertexmark(newvertex, trisym.tri == m->dummytri);
13765         setvertextype(newvertex,
13766                       trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13767         if (b->usesegments) {
13768           tspivot(triangleloop, checkmark);
13769           
13770           if (checkmark.ss != m->dummysub) {
13771             setvertexmark(newvertex, mark(checkmark));
13772             setvertextype(newvertex, SEGMENTVERTEX);
13773           }
13774         }
13775         if (b->verbose > 1) {
13776           printf("  Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13777         }
13778         
13779         triangleloop.tri[m->highorderindex + triangleloop.orient] =
13780                 (triangle) newvertex;
13781         if (trisym.tri != m->dummytri) {
13782           trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13783         }
13784       }
13785     }
13786     triangleloop.tri = triangletraverse(m);
13787   }
13788 }
13789 
13790 
13794 
13795 
13796 
13797 
13798 
13799 
13800 
13801 
13802 
13803 #ifndef TRILIBRARY
13804 
13805 #ifdef ANSI_DECLARATORS
13806 char *readline(char *string, FILE *infile, char *infilename)
13807 #else 
13808 char *readline(string, infile, infilename)
13809 char *string;
13810 FILE *infile;
13811 char *infilename;
13812 #endif 
13813 
13814 {
13815   char *result;
13816 
13817   
13818   do {
13819     result = fgets(string, INPUTLINESIZE, infile);
13820     if (result == (char *) NULL) {
13821       printf("  Error:  Unexpected end of file in %s.\n", infilename);
13822       triexit(1);
13823     }
13824     
13825     
13826     while ((*result != '\0') && (*result != '#')
13827            && (*result != '.') && (*result != '+') && (*result != '-')
13828            && ((*result < '0') || (*result > '9'))) {
13829       result++;
13830     }
13831   
13832   } while ((*result == '#') || (*result == '\0'));
13833   return result;
13834 }
13835 
13836 #endif 
13837 
13838 
13839 
13840 
13841 
13842 
13843 
13844 
13845 
13846 
13847 #ifndef TRILIBRARY
13848 
13849 #ifdef ANSI_DECLARATORS
13850 char *findfield(char *string)
13851 #else 
13852 char *findfield(string)
13853 char *string;
13854 #endif 
13855 
13856 {
13857   char *result;
13858 
13859   result = string;
13860   
13861   while ((*result != '\0') && (*result != '#')
13862          && (*result != ' ') && (*result != '\t')) {
13863     result++;
13864   }
13865   
13866   
13867   while ((*result != '\0') && (*result != '#')
13868          && (*result != '.') && (*result != '+') && (*result != '-')
13869          && ((*result < '0') || (*result > '9'))) {
13870     result++;
13871   }
13872   
13873   if (*result == '#') {
13874     *result = '\0';
13875   }
13876   return result;
13877 }
13878 
13879 #endif 
13880 
13881 
13882 
13883 
13884 
13885 
13886 
13887 
13888 #ifndef TRILIBRARY
13889 
13890 #ifdef ANSI_DECLARATORS
13891 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13892                char *polyfilename, FILE **polyfile)
13893 #else 
13894 void readnodes(m, b, nodefilename, polyfilename, polyfile)
13895 struct mesh *m;
13896 struct behavior *b;
13897 char *nodefilename;
13898 char *polyfilename;
13899 FILE **polyfile;
13900 #endif 
13901 
13902 {
13903   FILE *infile;
13904   vertex vertexloop;
13905   char inputline[INPUTLINESIZE];
13906   char *stringptr;
13907   char *infilename;
13908   REAL x, y;
13909   int firstnode;
13910   int nodemarkers;
13911   int currentmarker;
13912   int i, j;
13913 
13914   if (b->poly) {
13915     
13916     if (!b->quiet) {
13917       printf("Opening %s.\n", polyfilename);
13918     }
13919     *polyfile = fopen(polyfilename, "r");
13920     if (*polyfile == (FILE *) NULL) {
13921       printf("  Error:  Cannot access file %s.\n", polyfilename);
13922       triexit(1);
13923     }
13924     
13925     
13926     stringptr = readline(inputline, *polyfile, polyfilename);
13927     m->invertices = (int) strtol(stringptr, &stringptr, 0);
13928     stringptr = findfield(stringptr);
13929     if (*stringptr == '\0') {
13930       m->mesh_dim = 2;
13931     } else {
13932       m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13933     }
13934     stringptr = findfield(stringptr);
13935     if (*stringptr == '\0') {
13936       m->nextras = 0;
13937     } else {
13938       m->nextras = (int) strtol(stringptr, &stringptr, 0);
13939     }
13940     stringptr = findfield(stringptr);
13941     if (*stringptr == '\0') {
13942       nodemarkers = 0;
13943     } else {
13944       nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13945     }
13946     if (m->invertices > 0) {
13947       infile = *polyfile;
13948       infilename = polyfilename;
13949       m->readnodefile = 0;
13950     } else {
13951       
13952       
13953       m->readnodefile = 1;
13954       infilename = nodefilename;
13955     }
13956   } else {
13957     m->readnodefile = 1;
13958     infilename = nodefilename;
13959     *polyfile = (FILE *) NULL;
13960   }
13961 
13962   if (m->readnodefile) {
13963     
13964     if (!b->quiet) {
13965       printf("Opening %s.\n", nodefilename);
13966     }
13967     infile = fopen(nodefilename, "r");
13968     if (infile == (FILE *) NULL) {
13969       printf("  Error:  Cannot access file %s.\n", nodefilename);
13970       triexit(1);
13971     }
13972     
13973     
13974     stringptr = readline(inputline, infile, nodefilename);
13975     m->invertices = (int) strtol(stringptr, &stringptr, 0);
13976     stringptr = findfield(stringptr);
13977     if (*stringptr == '\0') {
13978       m->mesh_dim = 2;
13979     } else {
13980       m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13981     }
13982     stringptr = findfield(stringptr);
13983     if (*stringptr == '\0') {
13984       m->nextras = 0;
13985     } else {
13986       m->nextras = (int) strtol(stringptr, &stringptr, 0);
13987     }
13988     stringptr = findfield(stringptr);
13989     if (*stringptr == '\0') {
13990       nodemarkers = 0;
13991     } else {
13992       nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13993     }
13994   }
13995 
13996   if (m->invertices < 3) {
13997     printf("Error:  Input must have at least three input vertices.\n");
13998     triexit(1);
13999   }
14000   if (m->mesh_dim != 2) {
14001     printf("Error:  Triangle only works with two-dimensional meshes.\n");
14002     triexit(1);
14003   }
14004   if (m->nextras == 0) {
14005     b->weighted = 0;
14006   }
14007 
14008   initializevertexpool(m, b);
14009 
14010   
14011   for (i = 0; i < m->invertices; i++) {
14012     vertexloop = (vertex) poolalloc(&m->vertices);
14013     stringptr = readline(inputline, infile, infilename);
14014     if (i == 0) {
14015       firstnode = (int) strtol(stringptr, &stringptr, 0);
14016       if ((firstnode == 0) || (firstnode == 1)) {
14017         b->firstnumber = firstnode;
14018       }
14019     }
14020     stringptr = findfield(stringptr);
14021     if (*stringptr == '\0') {
14022       printf("Error:  Vertex %d has no x coordinate.\n", b->firstnumber + i);
14023       triexit(1);
14024     }
14025     x = (REAL) strtod(stringptr, &stringptr);
14026     stringptr = findfield(stringptr);
14027     if (*stringptr == '\0') {
14028       printf("Error:  Vertex %d has no y coordinate.\n", b->firstnumber + i);
14029       triexit(1);
14030     }
14031     y = (REAL) strtod(stringptr, &stringptr);
14032     vertexloop[0] = x;
14033     vertexloop[1] = y;
14034     
14035     for (j = 2; j < 2 + m->nextras; j++) {
14036       stringptr = findfield(stringptr);
14037       if (*stringptr == '\0') {
14038         vertexloop[j] = 0.0;
14039       } else {
14040         vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14041       }
14042     }
14043     if (nodemarkers) {
14044       
14045       stringptr = findfield(stringptr);
14046       if (*stringptr == '\0') {
14047         setvertexmark(vertexloop, 0);
14048       } else {
14049         currentmarker = (int) strtol(stringptr, &stringptr, 0);
14050         setvertexmark(vertexloop, currentmarker);
14051       }
14052     } else {
14053       
14054       setvertexmark(vertexloop, 0);
14055     }
14056     setvertextype(vertexloop, INPUTVERTEX);
14057     
14058     if (i == 0) {
14059       m->xmin = m->xmax = x;
14060       m->ymin = m->ymax = y;
14061     } else {
14062       m->xmin = (x < m->xmin) ? x : m->xmin;
14063       m->xmax = (x > m->xmax) ? x : m->xmax;
14064       m->ymin = (y < m->ymin) ? y : m->ymin;
14065       m->ymax = (y > m->ymax) ? y : m->ymax;
14066     }
14067   }
14068   if (m->readnodefile) {
14069     fclose(infile);
14070   }
14071 
14072   
14073   
14074   m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14075 }
14076 
14077 #endif 
14078 
14079 
14080 
14081 
14082 
14083 
14084 
14085 #ifdef TRILIBRARY
14086 
14087 #ifdef ANSI_DECLARATORS
14088 void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14089                    REAL *pointattriblist, int *pointmarkerlist,
14090                    int numberofpoints, int numberofpointattribs)
14091 #else 
14092 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14093                    numberofpoints, numberofpointattribs)
14094 struct mesh *m;
14095 struct behavior *b;
14096 REAL *pointlist;
14097 REAL *pointattriblist;
14098 int *pointmarkerlist;
14099 int numberofpoints;
14100 int numberofpointattribs;
14101 #endif 
14102 
14103 {
14104   vertex vertexloop;
14105   REAL x, y;
14106   int i, j;
14107   int coordindex;
14108   int attribindex;
14109 
14110   m->invertices = numberofpoints;
14111   m->mesh_dim = 2;
14112   m->nextras = numberofpointattribs;
14113   m->readnodefile = 0;
14114   if (m->invertices < 3) {
14115     printf("Error:  Input must have at least three input vertices.\n");
14116     triexit(1);
14117   }
14118   if (m->nextras == 0) {
14119     b->weighted = 0;
14120   }
14121 
14122   initializevertexpool(m, b);
14123 
14124   
14125   coordindex = 0;
14126   attribindex = 0;
14127   for (i = 0; i < m->invertices; i++) {
14128     vertexloop = (vertex) poolalloc(&m->vertices);
14129     
14130     x = vertexloop[0] = pointlist[coordindex++];
14131     y = vertexloop[1] = pointlist[coordindex++];
14132     
14133     for (j = 0; j < numberofpointattribs; j++) {
14134       vertexloop[2 + j] = pointattriblist[attribindex++];
14135     }
14136     if (pointmarkerlist != (int *) NULL) {
14137       
14138       setvertexmark(vertexloop, pointmarkerlist[i]);
14139     } else {
14140       
14141       setvertexmark(vertexloop, 0);
14142     }
14143     setvertextype(vertexloop, INPUTVERTEX);
14144     
14145     if (i == 0) {
14146       m->xmin = m->xmax = x;
14147       m->ymin = m->ymax = y;
14148     } else {
14149       m->xmin = (x < m->xmin) ? x : m->xmin;
14150       m->xmax = (x > m->xmax) ? x : m->xmax;
14151       m->ymin = (y < m->ymin) ? y : m->ymin;
14152       m->ymax = (y > m->ymax) ? y : m->ymax;
14153     }
14154   }
14155 
14156   
14157   
14158   m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14159 }
14160 
14161 #endif 
14162 
14163 
14164 
14165 
14166 
14167 
14168 
14169 
14170 #ifndef TRILIBRARY
14171 
14172 #ifdef ANSI_DECLARATORS
14173 void readholes(struct mesh *m, struct behavior *b,
14174                FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14175                REAL **rlist, int *regions)
14176 #else 
14177 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14178 struct mesh *m;
14179 struct behavior *b;
14180 FILE *polyfile;
14181 char *polyfilename;
14182 REAL **hlist;
14183 int *holes;
14184 REAL **rlist;
14185 int *regions;
14186 #endif 
14187 
14188 {
14189   REAL *holelist;
14190   REAL *regionlist;
14191   char inputline[INPUTLINESIZE];
14192   char *stringptr;
14193   int index;
14194   int i;
14195 
14196   
14197   stringptr = readline(inputline, polyfile, polyfilename);
14198   *holes = (int) strtol(stringptr, &stringptr, 0);
14199   if (*holes > 0) {
14200     holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14201     *hlist = holelist;
14202     for (i = 0; i < 2 * *holes; i += 2) {
14203       stringptr = readline(inputline, polyfile, polyfilename);
14204       stringptr = findfield(stringptr);
14205       if (*stringptr == '\0') {
14206         printf("Error:  Hole %d has no x coordinate.\n",
14207                b->firstnumber + (i >> 1));
14208         triexit(1);
14209       } else {
14210         holelist[i] = (REAL) strtod(stringptr, &stringptr);
14211       }
14212       stringptr = findfield(stringptr);
14213       if (*stringptr == '\0') {
14214         printf("Error:  Hole %d has no y coordinate.\n",
14215                b->firstnumber + (i >> 1));
14216         triexit(1);
14217       } else {
14218         holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14219       }
14220     }
14221   } else {
14222     *hlist = (REAL *) NULL;
14223   }
14224 
14225 #ifndef CDT_ONLY
14226   if ((b->regionattrib || b->vararea) && !b->refine) {
14227     
14228     stringptr = readline(inputline, polyfile, polyfilename);
14229     *regions = (int) strtol(stringptr, &stringptr, 0);
14230     if (*regions > 0) {
14231       regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14232       *rlist = regionlist;
14233       index = 0;
14234       for (i = 0; i < *regions; i++) {
14235         stringptr = readline(inputline, polyfile, polyfilename);
14236         stringptr = findfield(stringptr);
14237         if (*stringptr == '\0') {
14238           printf("Error:  Region %d has no x coordinate.\n",
14239                  b->firstnumber + i);
14240           triexit(1);
14241         } else {
14242           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14243         }
14244         stringptr = findfield(stringptr);
14245         if (*stringptr == '\0') {
14246           printf("Error:  Region %d has no y coordinate.\n",
14247                  b->firstnumber + i);
14248           triexit(1);
14249         } else {
14250           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14251         }
14252         stringptr = findfield(stringptr);
14253         if (*stringptr == '\0') {
14254           printf(
14255             "Error:  Region %d has no region attribute or area constraint.\n",
14256                  b->firstnumber + i);
14257           triexit(1);
14258         } else {
14259           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14260         }
14261         stringptr = findfield(stringptr);
14262         if (*stringptr == '\0') {
14263           regionlist[index] = regionlist[index - 1];
14264         } else {
14265           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14266         }
14267         index++;
14268       }
14269     }
14270   } else {
14271     
14272     *regions = 0;
14273     *rlist = (REAL *) NULL;
14274   }
14275 #endif 
14276 
14277   fclose(polyfile);
14278 }
14279 
14280 #endif 
14281 
14282 
14283 
14284 
14285 
14286 
14287 
14288 
14289 #ifndef TRILIBRARY
14290 
14291 #ifdef ANSI_DECLARATORS
14292 void finishfile(FILE *outfile, int argc, char **argv)
14293 #else 
14294 void finishfile(outfile, argc, argv)
14295 FILE *outfile;
14296 int argc;
14297 char **argv;
14298 #endif 
14299 
14300 {
14301   int i;
14302 
14303   fprintf(outfile, "# Generated by");
14304   for (i = 0; i < argc; i++) {
14305     fprintf(outfile, " ");
14306     fputs(argv[i], outfile);
14307   }
14308   fprintf(outfile, "\n");
14309   fclose(outfile);
14310 }
14311 
14312 #endif 
14313 
14314 
14315 
14316 
14317 
14318 
14319 
14320 
14321 
14322 
14323 #ifdef TRILIBRARY
14324 
14325 #ifdef ANSI_DECLARATORS
14326 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14327                 REAL **pointattriblist, int **pointmarkerlist)
14328 #else 
14329 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14330 struct mesh *m;
14331 struct behavior *b;
14332 REAL **pointlist;
14333 REAL **pointattriblist;
14334 int **pointmarkerlist;
14335 #endif 
14336 
14337 #else 
14338 
14339 #ifdef ANSI_DECLARATORS
14340 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14341                 int argc, char **argv)
14342 #else 
14343 void writenodes(m, b, nodefilename, argc, argv)
14344 struct mesh *m;
14345 struct behavior *b;
14346 char *nodefilename;
14347 int argc;
14348 char **argv;
14349 #endif 
14350 
14351 #endif 
14352 
14353 {
14354 #ifdef TRILIBRARY
14355   REAL *plist;
14356   REAL *palist;
14357   int *pmlist;
14358   int coordindex;
14359   int attribindex;
14360 #else 
14361   FILE *outfile;
14362 #endif 
14363   vertex vertexloop;
14364   long outvertices;
14365   int vertexnumber;
14366   int i;
14367 
14368   if (b->jettison) {
14369     outvertices = m->vertices.items - m->undeads;
14370   } else {
14371     outvertices = m->vertices.items;
14372   }
14373 
14374 #ifdef TRILIBRARY
14375   if (!b->quiet) {
14376     printf("Writing vertices.\n");
14377   }
14378   
14379   if (*pointlist == (REAL *) NULL) {
14380     *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14381   }
14382   
14383   if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14384     *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14385                                                  sizeof(REAL)));
14386   }
14387   
14388   if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14389     *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14390   }
14391   plist = *pointlist;
14392   palist = *pointattriblist;
14393   pmlist = *pointmarkerlist;
14394   coordindex = 0;
14395   attribindex = 0;
14396 #else 
14397   if (!b->quiet) {
14398     printf("Writing %s.\n", nodefilename);
14399   }
14400   outfile = fopen(nodefilename, "w");
14401   if (outfile == (FILE *) NULL) {
14402     printf("  Error:  Cannot create file %s.\n", nodefilename);
14403     triexit(1);
14404   }
14405   
14406   
14407   fprintf(outfile, "%ld  %d  %d  %d\n", outvertices, m->mesh_dim,
14408           m->nextras, 1 - b->nobound);
14409 #endif 
14410 
14411   traversalinit(&m->vertices);
14412   vertexnumber = b->firstnumber;
14413   vertexloop = vertextraverse(m);
14414   while (vertexloop != (vertex) NULL) {
14415     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14416 #ifdef TRILIBRARY
14417       
14418       plist[coordindex++] = vertexloop[0];
14419       plist[coordindex++] = vertexloop[1];
14420       
14421       for (i = 0; i < m->nextras; i++) {
14422         palist[attribindex++] = vertexloop[2 + i];
14423       }
14424       if (!b->nobound) {
14425         
14426         pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14427       }
14428 #else 
14429       
14430       fprintf(outfile, "%4d    %.17g  %.17g", vertexnumber, vertexloop[0],
14431               vertexloop[1]);
14432       for (i = 0; i < m->nextras; i++) {
14433         
14434         fprintf(outfile, "  %.17g", vertexloop[i + 2]);
14435       }
14436       if (b->nobound) {
14437         fprintf(outfile, "\n");
14438       } else {
14439         
14440         fprintf(outfile, "    %d\n", vertexmark(vertexloop));
14441       }
14442 #endif 
14443 
14444       setvertexmark(vertexloop, vertexnumber);
14445       vertexnumber++;
14446     }
14447     vertexloop = vertextraverse(m);
14448   }
14449 
14450 #ifndef TRILIBRARY
14451   finishfile(outfile, argc, argv);
14452 #endif 
14453 }
14454 
14455 
14456 
14457 
14458 
14459 
14460 
14461 
14462 
14463 
14464 
14465 #ifdef ANSI_DECLARATORS
14466 void numbernodes(struct mesh *m, struct behavior *b)
14467 #else 
14468 void numbernodes(m, b)
14469 struct mesh *m;
14470 struct behavior *b;
14471 #endif 
14472 
14473 {
14474   vertex vertexloop;
14475   int vertexnumber;
14476 
14477   traversalinit(&m->vertices);
14478   vertexnumber = b->firstnumber;
14479   vertexloop = vertextraverse(m);
14480   while (vertexloop != (vertex) NULL) {
14481     setvertexmark(vertexloop, vertexnumber);
14482     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14483       vertexnumber++;
14484     }
14485     vertexloop = vertextraverse(m);
14486   }
14487 }
14488 
14489 
14490 
14491 
14492 
14493 
14494 
14495 #ifdef TRILIBRARY
14496 
14497 #ifdef ANSI_DECLARATORS
14498 void writeelements(struct mesh *m, struct behavior *b,
14499                    int **trianglelist, REAL **triangleattriblist)
14500 #else 
14501 void writeelements(m, b, trianglelist, triangleattriblist)
14502 struct mesh *m;
14503 struct behavior *b;
14504 int **trianglelist;
14505 REAL **triangleattriblist;
14506 #endif 
14507 
14508 #else 
14509 
14510 #ifdef ANSI_DECLARATORS
14511 void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14512                    int argc, char **argv)
14513 #else 
14514 void writeelements(m, b, elefilename, argc, argv)
14515 struct mesh *m;
14516 struct behavior *b;
14517 char *elefilename;
14518 int argc;
14519 char **argv;
14520 #endif 
14521 
14522 #endif 
14523 
14524 {
14525 #ifdef TRILIBRARY
14526   int *tlist;
14527   REAL *talist;
14528   int vertexindex;
14529   int attribindex;
14530 #else 
14531   FILE *outfile;
14532 #endif 
14533   struct otri triangleloop;
14534   vertex p1, p2, p3;
14535   vertex mid1, mid2, mid3;
14536   long elementnumber;
14537   int i;
14538 
14539 #ifdef TRILIBRARY
14540   if (!b->quiet) {
14541     printf("Writing triangles.\n");
14542   }
14543   
14544   if (*trianglelist == (int *) NULL) {
14545     *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14546                                              ((b->order + 1) * (b->order + 2) /
14547                                               2) * sizeof(int)));
14548   }
14549   
14550   if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14551     *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14552                                                     m->eextras *
14553                                                     sizeof(REAL)));
14554   }
14555   tlist = *trianglelist;
14556   talist = *triangleattriblist;
14557   vertexindex = 0;
14558   attribindex = 0;
14559 #else 
14560   if (!b->quiet) {
14561     printf("Writing %s.\n", elefilename);
14562   }
14563   outfile = fopen(elefilename, "w");
14564   if (outfile == (FILE *) NULL) {
14565     printf("  Error:  Cannot create file %s.\n", elefilename);
14566     triexit(1);
14567   }
14568   
14569   fprintf(outfile, "%ld  %d  %d\n", m->triangles.items,
14570           (b->order + 1) * (b->order + 2) / 2, m->eextras);
14571 #endif 
14572 
14573   traversalinit(&m->triangles);
14574   triangleloop.tri = triangletraverse(m);
14575   triangleloop.orient = 0;
14576   elementnumber = b->firstnumber;
14577   while (triangleloop.tri != (triangle *) NULL) {
14578     org(triangleloop, p1);
14579     dest(triangleloop, p2);
14580     apex(triangleloop, p3);
14581     if (b->order == 1) {
14582 #ifdef TRILIBRARY
14583       tlist[vertexindex++] = vertexmark(p1);
14584       tlist[vertexindex++] = vertexmark(p2);
14585       tlist[vertexindex++] = vertexmark(p3);
14586 #else 
14587       
14588       fprintf(outfile, "%4ld    %4d  %4d  %4d", elementnumber,
14589               vertexmark(p1), vertexmark(p2), vertexmark(p3));
14590 #endif 
14591     } else {
14592       mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14593       mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14594       mid3 = (vertex) triangleloop.tri[m->highorderindex];
14595 #ifdef TRILIBRARY
14596       tlist[vertexindex++] = vertexmark(p1);
14597       tlist[vertexindex++] = vertexmark(p2);
14598       tlist[vertexindex++] = vertexmark(p3);
14599       tlist[vertexindex++] = vertexmark(mid1);
14600       tlist[vertexindex++] = vertexmark(mid2);
14601       tlist[vertexindex++] = vertexmark(mid3);
14602 #else 
14603       
14604       fprintf(outfile, "%4ld    %4d  %4d  %4d  %4d  %4d  %4d", elementnumber,
14605               vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14606               vertexmark(mid2), vertexmark(mid3));
14607 #endif 
14608     }
14609 
14610 #ifdef TRILIBRARY
14611     for (i = 0; i < m->eextras; i++) {
14612       talist[attribindex++] = elemattribute(triangleloop, i);
14613     }
14614 #else 
14615     for (i = 0; i < m->eextras; i++) {
14616       fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
14617     }
14618     fprintf(outfile, "\n");
14619 #endif 
14620 
14621     triangleloop.tri = triangletraverse(m);
14622     elementnumber++;
14623   }
14624 
14625 #ifndef TRILIBRARY
14626   finishfile(outfile, argc, argv);
14627 #endif 
14628 }
14629 
14630 
14631 
14632 
14633 
14634 
14635 
14636 #ifdef TRILIBRARY
14637 
14638 #ifdef ANSI_DECLARATORS
14639 void writepoly(struct mesh *m, struct behavior *b,
14640                int **segmentlist, int **segmentmarkerlist)
14641 #else 
14642 void writepoly(m, b, segmentlist, segmentmarkerlist)
14643 struct mesh *m;
14644 struct behavior *b;
14645 int **segmentlist;
14646 int **segmentmarkerlist;
14647 #endif 
14648 
14649 #else 
14650 
14651 #ifdef ANSI_DECLARATORS
14652 void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14653                REAL *holelist, int holes, REAL *regionlist, int regions,
14654                int argc, char **argv)
14655 #else 
14656 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14657                argc, argv)
14658 struct mesh *m;
14659 struct behavior *b;
14660 char *polyfilename;
14661 REAL *holelist;
14662 int holes;
14663 REAL *regionlist;
14664 int regions;
14665 int argc;
14666 char **argv;
14667 #endif 
14668 
14669 #endif 
14670 
14671 {
14672 #ifdef TRILIBRARY
14673   int *slist;
14674   int *smlist;
14675   int index;
14676 #else 
14677   FILE *outfile;
14678   long holenumber, regionnumber;
14679 #endif 
14680   struct osub subsegloop;
14681   vertex endpoint1, endpoint2;
14682   long subsegnumber;
14683 
14684 #ifdef TRILIBRARY
14685   if (!b->quiet) {
14686     printf("Writing segments.\n");
14687   }
14688   
14689   if (*segmentlist == (int *) NULL) {
14690     *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14691                                             sizeof(int)));
14692   }
14693   
14694   if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14695     *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14696                                                   sizeof(int)));
14697   }
14698   slist = *segmentlist;
14699   smlist = *segmentmarkerlist;
14700   index = 0;
14701 #else 
14702   if (!b->quiet) {
14703     printf("Writing %s.\n", polyfilename);
14704   }
14705   outfile = fopen(polyfilename, "w");
14706   if (outfile == (FILE *) NULL) {
14707     printf("  Error:  Cannot create file %s.\n", polyfilename);
14708     triexit(1);
14709   }
14710   
14711   
14712   
14713   fprintf(outfile, "%d  %d  %d  %d\n", 0, m->mesh_dim, m->nextras,
14714           1 - b->nobound);
14715   
14716   fprintf(outfile, "%ld  %d\n", m->subsegs.items, 1 - b->nobound);
14717 #endif 
14718 
14719   traversalinit(&m->subsegs);
14720   subsegloop.ss = subsegtraverse(m);
14721   subsegloop.ssorient = 0;
14722   subsegnumber = b->firstnumber;
14723   while (subsegloop.ss != (subseg *) NULL) {
14724     sorg(subsegloop, endpoint1);
14725     sdest(subsegloop, endpoint2);
14726 #ifdef TRILIBRARY
14727     
14728     slist[index++] = vertexmark(endpoint1);
14729     slist[index++] = vertexmark(endpoint2);
14730     if (!b->nobound) {
14731       
14732       smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14733     }
14734 #else 
14735     
14736     if (b->nobound) {
14737       fprintf(outfile, "%4ld    %4d  %4d\n", subsegnumber,
14738               vertexmark(endpoint1), vertexmark(endpoint2));
14739     } else {
14740       fprintf(outfile, "%4ld    %4d  %4d    %4d\n", subsegnumber,
14741               vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14742     }
14743 #endif 
14744 
14745     subsegloop.ss = subsegtraverse(m);
14746     subsegnumber++;
14747   }
14748 
14749 #ifndef TRILIBRARY
14750 #ifndef CDT_ONLY
14751   fprintf(outfile, "%d\n", holes);
14752   if (holes > 0) {
14753     for (holenumber = 0; holenumber < holes; holenumber++) {
14754       
14755       fprintf(outfile, "%4ld   %.17g  %.17g\n", b->firstnumber + holenumber,
14756               holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14757     }
14758   }
14759   if (regions > 0) {
14760     fprintf(outfile, "%d\n", regions);
14761     for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14762       
14763       fprintf(outfile, "%4ld   %.17g  %.17g  %.17g  %.17g\n",
14764               b->firstnumber + regionnumber,
14765               regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14766               regionlist[4 * regionnumber + 2],
14767               regionlist[4 * regionnumber + 3]);
14768     }
14769   }
14770 #endif 
14771 
14772   finishfile(outfile, argc, argv);
14773 #endif 
14774 }
14775 
14776 
14777 
14778 
14779 
14780 
14781 
14782 #ifdef TRILIBRARY
14783 
14784 #ifdef ANSI_DECLARATORS
14785 void writeedges(struct mesh *m, struct behavior *b,
14786                 int **edgelist, int **edgemarkerlist)
14787 #else 
14788 void writeedges(m, b, edgelist, edgemarkerlist)
14789 struct mesh *m;
14790 struct behavior *b;
14791 int **edgelist;
14792 int **edgemarkerlist;
14793 #endif 
14794 
14795 #else 
14796 
14797 #ifdef ANSI_DECLARATORS
14798 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14799                 int argc, char **argv)
14800 #else 
14801 void writeedges(m, b, edgefilename, argc, argv)
14802 struct mesh *m;
14803 struct behavior *b;
14804 char *edgefilename;
14805 int argc;
14806 char **argv;
14807 #endif 
14808 
14809 #endif 
14810 
14811 {
14812 #ifdef TRILIBRARY
14813   int *elist;
14814   int *emlist;
14815   int index;
14816 #else 
14817   FILE *outfile;
14818 #endif 
14819   struct otri triangleloop, trisym;
14820   struct osub checkmark;
14821   vertex p1, p2;
14822   long edgenumber;
14823   triangle ptr;                         
14824   subseg sptr;                      
14825 
14826 #ifdef TRILIBRARY
14827   if (!b->quiet) {
14828     printf("Writing edges.\n");
14829   }
14830   
14831   if (*edgelist == (int *) NULL) {
14832     *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14833   }
14834   
14835   if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14836     *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14837   }
14838   elist = *edgelist;
14839   emlist = *edgemarkerlist;
14840   index = 0;
14841 #else 
14842   if (!b->quiet) {
14843     printf("Writing %s.\n", edgefilename);
14844   }
14845   outfile = fopen(edgefilename, "w");
14846   if (outfile == (FILE *) NULL) {
14847     printf("  Error:  Cannot create file %s.\n", edgefilename);
14848     triexit(1);
14849   }
14850   
14851   fprintf(outfile, "%ld  %d\n", m->edges, 1 - b->nobound);
14852 #endif 
14853 
14854   traversalinit(&m->triangles);
14855   triangleloop.tri = triangletraverse(m);
14856   edgenumber = b->firstnumber;
14857   
14858   
14859   
14860   
14861   
14862   
14863   while (triangleloop.tri != (triangle *) NULL) {
14864     for (triangleloop.orient = 0; triangleloop.orient < 3;
14865          triangleloop.orient++) {
14866       sym(triangleloop, trisym);
14867       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14868         org(triangleloop, p1);
14869         dest(triangleloop, p2);
14870 #ifdef TRILIBRARY
14871         elist[index++] = vertexmark(p1);
14872         elist[index++] = vertexmark(p2);
14873 #endif 
14874         if (b->nobound) {
14875 #ifndef TRILIBRARY
14876           
14877           fprintf(outfile, "%4ld   %d  %d\n", edgenumber,
14878                   vertexmark(p1), vertexmark(p2));
14879 #endif 
14880         } else {
14881           
14882           
14883           if (b->usesegments) {
14884             tspivot(triangleloop, checkmark);
14885             if (checkmark.ss == m->dummysub) {
14886 #ifdef TRILIBRARY
14887               emlist[edgenumber - b->firstnumber] = 0;
14888 #else 
14889               fprintf(outfile, "%4ld   %d  %d  %d\n", edgenumber,
14890                       vertexmark(p1), vertexmark(p2), 0);
14891 #endif 
14892             } else {
14893 #ifdef TRILIBRARY
14894               emlist[edgenumber - b->firstnumber] = mark(checkmark);
14895 #else 
14896               fprintf(outfile, "%4ld   %d  %d  %d\n", edgenumber,
14897                       vertexmark(p1), vertexmark(p2), mark(checkmark));
14898 #endif 
14899             }
14900           } else {
14901 #ifdef TRILIBRARY
14902             emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14903 #else 
14904             fprintf(outfile, "%4ld   %d  %d  %d\n", edgenumber,
14905                     vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14906 #endif 
14907           }
14908         }
14909         edgenumber++;
14910       }
14911     }
14912     triangleloop.tri = triangletraverse(m);
14913   }
14914 
14915 #ifndef TRILIBRARY
14916   finishfile(outfile, argc, argv);
14917 #endif 
14918 }
14919 
14920 
14921 
14922 
14923 
14924 
14925 
14926 
14927 
14928 
14929 
14930 
14931 
14932 
14933 
14934 
14935 
14936 #ifdef TRILIBRARY
14937 
14938 #ifdef ANSI_DECLARATORS
14939 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14940                   REAL **vpointattriblist, int **vpointmarkerlist,
14941                   int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14942 #else 
14943 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14944                   vedgelist, vedgemarkerlist, vnormlist)
14945 struct mesh *m;
14946 struct behavior *b;
14947 REAL **vpointlist;
14948 REAL **vpointattriblist;
14949 int **vpointmarkerlist;
14950 int **vedgelist;
14951 int **vedgemarkerlist;
14952 REAL **vnormlist;
14953 #endif 
14954 
14955 #else 
14956 
14957 #ifdef ANSI_DECLARATORS
14958 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14959                   char *vedgefilename, int argc, char **argv)
14960 #else 
14961 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14962 struct mesh *m;
14963 struct behavior *b;
14964 char *vnodefilename;
14965 char *vedgefilename;
14966 int argc;
14967 char **argv;
14968 #endif 
14969 
14970 #endif 
14971 
14972 {
14973 #ifdef TRILIBRARY
14974   REAL *plist;
14975   REAL *palist;
14976   int *elist;
14977   REAL *normlist;
14978   int coordindex;
14979   int attribindex;
14980 #else 
14981   FILE *outfile;
14982 #endif 
14983   struct otri triangleloop, trisym;
14984   vertex torg, tdest, tapex;
14985   REAL circumcenter[2];
14986   REAL xi, eta;
14987   long vnodenumber, vedgenumber;
14988   int p1, p2;
14989   int i;
14990   triangle ptr;                         
14991 
14992 #ifdef TRILIBRARY
14993   if (!b->quiet) {
14994     printf("Writing Voronoi vertices.\n");
14995   }
14996   
14997   if (*vpointlist == (REAL *) NULL) {
14998     *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14999                                             sizeof(REAL)));
15000   }
15001   
15002   if (*vpointattriblist == (REAL *) NULL) {
15003     *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15004                                                   m->nextras * sizeof(REAL)));
15005   }
15006   *vpointmarkerlist = (int *) NULL;
15007   plist = *vpointlist;
15008   palist = *vpointattriblist;
15009   coordindex = 0;
15010   attribindex = 0;
15011 #else 
15012   if (!b->quiet) {
15013     printf("Writing %s.\n", vnodefilename);
15014   }
15015   outfile = fopen(vnodefilename, "w");
15016   if (outfile == (FILE *) NULL) {
15017     printf("  Error:  Cannot create file %s.\n", vnodefilename);
15018     triexit(1);
15019   }
15020   
15021   
15022   fprintf(outfile, "%ld  %d  %d  %d\n", m->triangles.items, 2, m->nextras, 0);
15023 #endif 
15024 
15025   traversalinit(&m->triangles);
15026   triangleloop.tri = triangletraverse(m);
15027   triangleloop.orient = 0;
15028   vnodenumber = b->firstnumber;
15029   while (triangleloop.tri != (triangle *) NULL) {
15030     org(triangleloop, torg);
15031     dest(triangleloop, tdest);
15032     apex(triangleloop, tapex);
15033     findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15034 #ifdef TRILIBRARY
15035     
15036     plist[coordindex++] = circumcenter[0];
15037     plist[coordindex++] = circumcenter[1];
15038     for (i = 2; i < 2 + m->nextras; i++) {
15039       
15040       palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15041                                      + eta * (tapex[i] - torg[i]);
15042     }
15043 #else 
15044     
15045     fprintf(outfile, "%4ld    %.17g  %.17g", vnodenumber, circumcenter[0],
15046             circumcenter[1]);
15047     for (i = 2; i < 2 + m->nextras; i++) {
15048       
15049       fprintf(outfile, "  %.17g", torg[i] + xi * (tdest[i] - torg[i])
15050                                          + eta * (tapex[i] - torg[i]));
15051     }
15052     fprintf(outfile, "\n");
15053 #endif 
15054 
15055     * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15056     triangleloop.tri = triangletraverse(m);
15057     vnodenumber++;
15058   }
15059 
15060 #ifndef TRILIBRARY
15061   finishfile(outfile, argc, argv);
15062 #endif 
15063 
15064 #ifdef TRILIBRARY
15065   if (!b->quiet) {
15066     printf("Writing Voronoi edges.\n");
15067   }
15068   
15069   if (*vedgelist == (int *) NULL) {
15070     *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15071   }
15072   *vedgemarkerlist = (int *) NULL;
15073   
15074   if (*vnormlist == (REAL *) NULL) {
15075     *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15076   }
15077   elist = *vedgelist;
15078   normlist = *vnormlist;
15079   coordindex = 0;
15080 #else 
15081   if (!b->quiet) {
15082     printf("Writing %s.\n", vedgefilename);
15083   }
15084   outfile = fopen(vedgefilename, "w");
15085   if (outfile == (FILE *) NULL) {
15086     printf("  Error:  Cannot create file %s.\n", vedgefilename);
15087     triexit(1);
15088   }
15089   
15090   fprintf(outfile, "%ld  %d\n", m->edges, 0);
15091 #endif 
15092 
15093   traversalinit(&m->triangles);
15094   triangleloop.tri = triangletraverse(m);
15095   vedgenumber = b->firstnumber;
15096   
15097   
15098   
15099   
15100   
15101   
15102   while (triangleloop.tri != (triangle *) NULL) {
15103     for (triangleloop.orient = 0; triangleloop.orient < 3;
15104          triangleloop.orient++) {
15105       sym(triangleloop, trisym);
15106       if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15107         
15108         p1 = * (int *) (triangleloop.tri + 6);
15109         if (trisym.tri == m->dummytri) {
15110           org(triangleloop, torg);
15111           dest(triangleloop, tdest);
15112 #ifdef TRILIBRARY
15113           
15114           elist[coordindex] = p1;
15115           normlist[coordindex++] = tdest[1] - torg[1];
15116           elist[coordindex] = -1;
15117           normlist[coordindex++] = torg[0] - tdest[0];
15118 #else 
15119           
15120           
15121           
15122           fprintf(outfile, "%4ld   %d  %d   %.17g  %.17g\n", vedgenumber,
15123                   p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15124 #endif 
15125         } else {
15126           
15127           p2 = * (int *) (trisym.tri + 6);
15128           
15129 #ifdef TRILIBRARY
15130           elist[coordindex] = p1;
15131           normlist[coordindex++] = 0.0;
15132           elist[coordindex] = p2;
15133           normlist[coordindex++] = 0.0;
15134 #else 
15135           fprintf(outfile, "%4ld   %d  %d\n", vedgenumber, p1, p2);
15136 #endif 
15137         }
15138         vedgenumber++;
15139       }
15140     }
15141     triangleloop.tri = triangletraverse(m);
15142   }
15143 
15144 #ifndef TRILIBRARY
15145   finishfile(outfile, argc, argv);
15146 #endif 
15147 }
15148 
15149 #ifdef TRILIBRARY
15150 
15151 #ifdef ANSI_DECLARATORS
15152 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15153 #else 
15154 void writeneighbors(m, b, neighborlist)
15155 struct mesh *m;
15156 struct behavior *b;
15157 int **neighborlist;
15158 #endif 
15159 
15160 #else 
15161 
15162 #ifdef ANSI_DECLARATORS
15163 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15164                     int argc, char **argv)
15165 #else 
15166 void writeneighbors(m, b, neighborfilename, argc, argv)
15167 struct mesh *m;
15168 struct behavior *b;
15169 char *neighborfilename;
15170 int argc;
15171 char **argv;
15172 #endif 
15173 
15174 #endif 
15175 
15176 {
15177 #ifdef TRILIBRARY
15178   int *nlist;
15179   int index;
15180 #else 
15181   FILE *outfile;
15182 #endif 
15183   struct otri triangleloop, trisym;
15184   long elementnumber;
15185   int neighbor1, neighbor2, neighbor3;
15186   triangle ptr;                         
15187 
15188 #ifdef TRILIBRARY
15189   if (!b->quiet) {
15190     printf("Writing neighbors.\n");
15191   }
15192   
15193   if (*neighborlist == (int *) NULL) {
15194     *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15195                                              sizeof(int)));
15196   }
15197   nlist = *neighborlist;
15198   index = 0;
15199 #else 
15200   if (!b->quiet) {
15201     printf("Writing %s.\n", neighborfilename);
15202   }
15203   outfile = fopen(neighborfilename, "w");
15204   if (outfile == (FILE *) NULL) {
15205     printf("  Error:  Cannot create file %s.\n", neighborfilename);
15206     triexit(1);
15207   }
15208   
15209   fprintf(outfile, "%ld  %d\n", m->triangles.items, 3);
15210 #endif 
15211 
15212   traversalinit(&m->triangles);
15213   triangleloop.tri = triangletraverse(m);
15214   triangleloop.orient = 0;
15215   elementnumber = b->firstnumber;
15216   while (triangleloop.tri != (triangle *) NULL) {
15217     * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15218     triangleloop.tri = triangletraverse(m);
15219     elementnumber++;
15220   }
15221   * (int *) (m->dummytri + 6) = -1;
15222 
15223   traversalinit(&m->triangles);
15224   triangleloop.tri = triangletraverse(m);
15225   elementnumber = b->firstnumber;
15226   while (triangleloop.tri != (triangle *) NULL) {
15227     triangleloop.orient = 1;
15228     sym(triangleloop, trisym);
15229     neighbor1 = * (int *) (trisym.tri + 6);
15230     triangleloop.orient = 2;
15231     sym(triangleloop, trisym);
15232     neighbor2 = * (int *) (trisym.tri + 6);
15233     triangleloop.orient = 0;
15234     sym(triangleloop, trisym);
15235     neighbor3 = * (int *) (trisym.tri + 6);
15236 #ifdef TRILIBRARY
15237     nlist[index++] = neighbor1;
15238     nlist[index++] = neighbor2;
15239     nlist[index++] = neighbor3;
15240 #else 
15241     
15242     fprintf(outfile, "%4ld    %d  %d  %d\n", elementnumber,
15243             neighbor1, neighbor2, neighbor3);
15244 #endif 
15245 
15246     triangleloop.tri = triangletraverse(m);
15247     elementnumber++;
15248   }
15249 
15250 #ifndef TRILIBRARY
15251   finishfile(outfile, argc, argv);
15252 #endif 
15253 }
15254 
15255 
15256 
15257 
15258 
15259 
15260 
15261 
15262 
15263 
15264 #ifndef TRILIBRARY
15265 
15266 #ifdef ANSI_DECLARATORS
15267 void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15268               int argc, char **argv)
15269 #else 
15270 void writeoff(m, b, offfilename, argc, argv)
15271 struct mesh *m;
15272 struct behavior *b;
15273 char *offfilename;
15274 int argc;
15275 char **argv;
15276 #endif 
15277 
15278 {
15279   FILE *outfile;
15280   struct otri triangleloop;
15281   vertex vertexloop;
15282   vertex p1, p2, p3;
15283   long outvertices;
15284 
15285   if (!b->quiet) {
15286     printf("Writing %s.\n", offfilename);
15287   }
15288 
15289   if (b->jettison) {
15290     outvertices = m->vertices.items - m->undeads;
15291   } else {
15292     outvertices = m->vertices.items;
15293   }
15294 
15295   outfile = fopen(offfilename, "w");
15296   if (outfile == (FILE *) NULL) {
15297     printf("  Error:  Cannot create file %s.\n", offfilename);
15298     triexit(1);
15299   }
15300   
15301   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", outvertices, m->triangles.items,
15302           m->edges);
15303 
15304   
15305   traversalinit(&m->vertices);
15306   vertexloop = vertextraverse(m);
15307   while (vertexloop != (vertex) NULL) {
15308     if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15309       
15310       fprintf(outfile, " %.17g  %.17g  %.17g\n", vertexloop[0], vertexloop[1],
15311               0.0);
15312     }
15313     vertexloop = vertextraverse(m);
15314   }
15315 
15316   
15317   traversalinit(&m->triangles);
15318   triangleloop.tri = triangletraverse(m);
15319   triangleloop.orient = 0;
15320   while (triangleloop.tri != (triangle *) NULL) {
15321     org(triangleloop, p1);
15322     dest(triangleloop, p2);
15323     apex(triangleloop, p3);
15324     
15325     fprintf(outfile, " 3   %4d  %4d  %4d\n", vertexmark(p1) - b->firstnumber,
15326             vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15327     triangleloop.tri = triangletraverse(m);
15328   }
15329   finishfile(outfile, argc, argv);
15330 }
15331 
15332 #endif 
15333 
15336 
15337 
15338 
15339 
15340 
15341 
15342 
15343 
15344 #ifdef ANSI_DECLARATORS
15345 void quality_statistics(struct mesh *m, struct behavior *b)
15346 #else 
15347 void quality_statistics(m, b)
15348 struct mesh *m;
15349 struct behavior *b;
15350 #endif 
15351 
15352 {
15353   struct otri triangleloop;
15354   vertex p[3];
15355   REAL cossquaretable[8];
15356   REAL ratiotable[16];
15357   REAL dx[3], dy[3];
15358   REAL edgelength[3];
15359   REAL dotproduct;
15360   REAL cossquare;
15361   REAL triarea;
15362   REAL shortest, longest;
15363   REAL trilongest2;
15364   REAL smallestarea, biggestarea;
15365   REAL triminaltitude2;
15366   REAL minaltitude;
15367   REAL triaspect2;
15368   REAL worstaspect;
15369   REAL smallestangle, biggestangle;
15370   REAL radconst, degconst;
15371   int angletable[18];
15372   int aspecttable[16];
15373   int aspectindex;
15374   int tendegree;
15375   int acutebiggest;
15376   int i, ii, j, k;
15377 
15378   printf("Mesh quality statistics:\n\n");
15379   radconst = PI / 18.0;
15380   degconst = 180.0 / PI;
15381   for (i = 0; i < 8; i++) {
15382     cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15383     cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15384   }
15385   for (i = 0; i < 18; i++) {
15386     angletable[i] = 0;
15387   }
15388 
15389   ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
15390   ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
15391   ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
15392   ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
15393   ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
15394   ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
15395   ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
15396   ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
15397   for (i = 0; i < 16; i++) {
15398     aspecttable[i] = 0;
15399   }
15400 
15401   worstaspect = 0.0;
15402   minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15403   minaltitude = minaltitude * minaltitude;
15404   shortest = minaltitude;
15405   longest = 0.0;
15406   smallestarea = minaltitude;
15407   biggestarea = 0.0;
15408   worstaspect = 0.0;
15409   smallestangle = 0.0;
15410   biggestangle = 2.0;
15411   acutebiggest = 1;
15412 
15413   traversalinit(&m->triangles);
15414   triangleloop.tri = triangletraverse(m);
15415   triangleloop.orient = 0;
15416   while (triangleloop.tri != (triangle *) NULL) {
15417     org(triangleloop, p[0]);
15418     dest(triangleloop, p[1]);
15419     apex(triangleloop, p[2]);
15420     trilongest2 = 0.0;
15421 
15422     for (i = 0; i < 3; i++) {
15423       j = plus1mod3[i];
15424       k = minus1mod3[i];
15425       dx[i] = p[j][0] - p[k][0];
15426       dy[i] = p[j][1] - p[k][1];
15427       edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15428       if (edgelength[i] > trilongest2) {
15429         trilongest2 = edgelength[i];
15430       }
15431       if (edgelength[i] > longest) {
15432         longest = edgelength[i];
15433       }
15434       if (edgelength[i] < shortest) {
15435         shortest = edgelength[i];
15436       }
15437     }
15438 
15439     triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15440     if (triarea < smallestarea) {
15441       smallestarea = triarea;
15442     }
15443     if (triarea > biggestarea) {
15444       biggestarea = triarea;
15445     }
15446     triminaltitude2 = triarea * triarea / trilongest2;
15447     if (triminaltitude2 < minaltitude) {
15448       minaltitude = triminaltitude2;
15449     }
15450     triaspect2 = trilongest2 / triminaltitude2;
15451     if (triaspect2 > worstaspect) {
15452       worstaspect = triaspect2;
15453     }
15454     aspectindex = 0;
15455     while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15456            && (aspectindex < 15)) {
15457       aspectindex++;
15458     }
15459     aspecttable[aspectindex]++;
15460 
15461     for (i = 0; i < 3; i++) {
15462       j = plus1mod3[i];
15463       k = minus1mod3[i];
15464       dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15465       cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15466       tendegree = 8;
15467       for (ii = 7; ii >= 0; ii--) {
15468         if (cossquare > cossquaretable[ii]) {
15469           tendegree = ii;
15470         }
15471       }
15472       if (dotproduct <= 0.0) {
15473         angletable[tendegree]++;
15474         if (cossquare > smallestangle) {
15475           smallestangle = cossquare;
15476         }
15477         if (acutebiggest && (cossquare < biggestangle)) {
15478           biggestangle = cossquare;
15479         }
15480       } else {
15481         angletable[17 - tendegree]++;
15482         if (acutebiggest || (cossquare > biggestangle)) {
15483           biggestangle = cossquare;
15484           acutebiggest = 0;
15485         }
15486       }
15487     }
15488     triangleloop.tri = triangletraverse(m);
15489   }
15490 
15491   shortest = sqrt(shortest);
15492   longest = sqrt(longest);
15493   minaltitude = sqrt(minaltitude);
15494   worstaspect = sqrt(worstaspect);
15495   smallestarea *= 0.5;
15496   biggestarea *= 0.5;
15497   if (smallestangle >= 1.0) {
15498     smallestangle = 0.0;
15499   } else {
15500     smallestangle = degconst * acos(sqrt(smallestangle));
15501   }
15502   if (biggestangle >= 1.0) {
15503     biggestangle = 180.0;
15504   } else {
15505     if (acutebiggest) {
15506       biggestangle = degconst * acos(sqrt(biggestangle));
15507     } else {
15508       biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15509     }
15510   }
15511 
15512   printf("  Smallest area: %16.5g   |  Largest area: %16.5g\n",
15513          smallestarea, biggestarea);
15514   printf("  Shortest edge: %16.5g   |  Longest edge: %16.5g\n",
15515          shortest, longest);
15516   printf("  Shortest altitude: %12.5g   |  Largest aspect ratio: %8.5g\n\n",
15517          minaltitude, worstaspect);
15518 
15519   printf("  Triangle aspect ratio histogram:\n");
15520   printf("  1.1547 - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
15521          ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15522          aspecttable[8]);
15523   for (i = 1; i < 7; i++) {
15524     printf("  %6.6g - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
15525            ratiotable[i - 1], ratiotable[i], aspecttable[i],
15526            ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15527   }
15528   printf("  %6.6g - %-6.6g    :  %8d    | %6.6g -            :  %8d\n",
15529          ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15530          aspecttable[15]);
15531   printf("  (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15532 
15533   printf("  Smallest angle: %15.5g   |  Largest angle: %15.5g\n\n",
15534          smallestangle, biggestangle);
15535 
15536   printf("  Angle histogram:\n");
15537   for (i = 0; i < 9; i++) {
15538     printf("    %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8d\n",
15539            i * 10, i * 10 + 10, angletable[i],
15540            i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15541   }
15542   printf("\n");
15543 }
15544 
15545 
15546 
15547 
15548 
15549 
15550 
15551 #ifdef ANSI_DECLARATORS
15552 void statistics(struct mesh *m, struct behavior *b)
15553 #else 
15554 void statistics(m, b)
15555 struct mesh *m;
15556 struct behavior *b;
15557 #endif 
15558 
15559 {
15560   printf("\nStatistics:\n\n");
15561   printf("  Input vertices: %d\n", m->invertices);
15562   if (b->refine) {
15563     printf("  Input triangles: %d\n", m->inelements);
15564   }
15565   if (b->poly) {
15566     printf("  Input segments: %d\n", m->insegments);
15567     if (!b->refine) {
15568       printf("  Input holes: %d\n", m->holes);
15569     }
15570   }
15571 
15572   printf("\n  Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15573   printf("  Mesh triangles: %ld\n", m->triangles.items);
15574   printf("  Mesh edges: %ld\n", m->edges);
15575   printf("  Mesh exterior boundary edges: %ld\n", m->hullsize);
15576   if (b->poly || b->refine) {
15577     printf("  Mesh interior boundary edges: %ld\n",
15578            m->subsegs.items - m->hullsize);
15579     printf("  Mesh subsegments (constrained edges): %ld\n",
15580            m->subsegs.items);
15581   }
15582   printf("\n");
15583 
15584   if (b->verbose) {
15585     quality_statistics(m, b);
15586     printf("Memory allocation statistics:\n\n");
15587     printf("  Maximum number of vertices: %ld\n", m->vertices.maxitems);
15588     printf("  Maximum number of triangles: %ld\n", m->triangles.maxitems);
15589     if (m->subsegs.maxitems > 0) {
15590       printf("  Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15591     }
15592     if (m->viri.maxitems > 0) {
15593       printf("  Maximum number of viri: %ld\n", m->viri.maxitems);
15594     }
15595     if (m->badsubsegs.maxitems > 0) {
15596       printf("  Maximum number of encroached subsegments: %ld\n",
15597              m->badsubsegs.maxitems);
15598     }
15599     if (m->badtriangles.maxitems > 0) {
15600       printf("  Maximum number of bad triangles: %ld\n",
15601              m->badtriangles.maxitems);
15602     }
15603     if (m->flipstackers.maxitems > 0) {
15604       printf("  Maximum number of stacked triangle flips: %ld\n",
15605              m->flipstackers.maxitems);
15606     }
15607     if (m->splaynodes.maxitems > 0) {
15608       printf("  Maximum number of splay tree nodes: %ld\n",
15609              m->splaynodes.maxitems);
15610     }
15611     printf("  Approximate heap memory use (bytes): %ld\n\n",
15612            m->vertices.maxitems * m->vertices.itembytes +
15613            m->triangles.maxitems * m->triangles.itembytes +
15614            m->subsegs.maxitems * m->subsegs.itembytes +
15615            m->viri.maxitems * m->viri.itembytes +
15616            m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15617            m->badtriangles.maxitems * m->badtriangles.itembytes +
15618            m->flipstackers.maxitems * m->flipstackers.itembytes +
15619            m->splaynodes.maxitems * m->splaynodes.itembytes);
15620 
15621     printf("Algorithmic statistics:\n\n");
15622     if (!b->weighted) {
15623       printf("  Number of incircle tests: %ld\n", m->incirclecount);
15624     } else {
15625       printf("  Number of 3D orientation tests: %ld\n", m->orient3dcount);
15626     }
15627     printf("  Number of 2D orientation tests: %ld\n", m->counterclockcount);
15628     if (m->hyperbolacount > 0) {
15629       printf("  Number of right-of-hyperbola tests: %ld\n",
15630              m->hyperbolacount);
15631     }
15632     if (m->circletopcount > 0) {
15633       printf("  Number of circle top computations: %ld\n",
15634              m->circletopcount);
15635     }
15636     if (m->circumcentercount > 0) {
15637       printf("  Number of triangle circumcenter computations: %ld\n",
15638              m->circumcentercount);
15639     }
15640     printf("\n");
15641   }
15642 }
15643 
15644 
15645 
15646 
15647 
15648 
15649 
15650 
15651 
15652 
15653 
15654 
15655 
15656 
15657 
15658 
15659 
15660 
15661 
15662 
15663 
15664 
15665 
15666 
15667 
15668 
15669 
15670 #ifdef TRILIBRARY
15671 
15672 #ifdef ANSI_DECLARATORS
15673 void triangulate(char *triswitches, struct triangulateio *in,
15674                  struct triangulateio *out, struct triangulateio *vorout)
15675 #else 
15676 void triangulate(triswitches, in, out, vorout)
15677 char *triswitches;
15678 struct triangulateio *in;
15679 struct triangulateio *out;
15680 struct triangulateio *vorout;
15681 #endif 
15682 
15683 #else 
15684 
15685 #ifdef ANSI_DECLARATORS
15686 #include "triangle.h"
15687 int ShewchukTRIANGLE(int argc, char **argv)
15688 #else 
15689 #include "triangle.h"
15690 int ShewchukTRIANGLE(argc, argv)
15691 int argc;
15692 char **argv;
15693 #endif 
15694 
15695 #endif 
15696 
15697 {
15698   struct mesh m;
15699   struct behavior b;
15700   REAL *holearray;                                        
15701   REAL *regionarray;   
15702 #ifndef TRILIBRARY
15703   FILE *polyfile;
15704 #endif 
15705 
15706 #ifndef NO_TIMER
15707 #define NO_TIMER
15708 #endif
15709 
15710 #ifndef NO_TIMER
15711   
15712   
15713   struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15714   struct timezone tz;
15715 #endif 
15716 
15717 #ifndef NO_TIMER
15718   gettimeofday(&tv0, &tz);
15719 #endif 
15720 
15721   triangleinit(&m);
15722 #ifdef TRILIBRARY
15723   parsecommandline(1, &triswitches, &b);
15724 #else 
15725   parsecommandline(argc, argv, &b);
15726 #endif 
15727   m.steinerleft = b.steiner;
15728 
15729 #ifdef TRILIBRARY
15730   transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15731                 in->pointmarkerlist, in->numberofpoints,
15732                 in->numberofpointattributes);
15733 #else 
15734   readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15735 #endif 
15736 
15737 #ifndef NO_TIMER
15738   if (!b.quiet) {
15739     gettimeofday(&tv1, &tz);
15740   }
15741 #endif 
15742 
15743 #ifdef CDT_ONLY
15744   m.hullsize = delaunay(&m, &b);                
15745 #else 
15746   if (b.refine) {
15747     
15748 #ifdef TRILIBRARY
15749     m.hullsize = reconstruct(&m, &b, in->trianglelist,
15750                              in->triangleattributelist, in->trianglearealist,
15751                              in->numberoftriangles, in->numberofcorners,
15752                              in->numberoftriangleattributes,
15753                              in->segmentlist, in->segmentmarkerlist,
15754                              in->numberofsegments);
15755 #else 
15756     m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15757                              b.inpolyfilename, polyfile);
15758 #endif 
15759   } else {
15760     m.hullsize = delaunay(&m, &b);              
15761   }
15762 #endif 
15763 
15764 #ifndef NO_TIMER
15765   if (!b.quiet) {
15766     gettimeofday(&tv2, &tz);
15767     if (b.refine) {
15768       printf("Mesh reconstruction");
15769     } else {
15770       printf("Delaunay");
15771     }
15772     printf(" milliseconds:  %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15773            (tv2.tv_usec - tv1.tv_usec) / 1000l);
15774   }
15775 #endif 
15776 
15777   
15778   
15779   m.infvertex1 = (vertex) NULL;
15780   m.infvertex2 = (vertex) NULL;
15781   m.infvertex3 = (vertex) NULL;
15782 
15783   if (b.usesegments) {
15784     m.checksegments = 1;                
15785     if (!b.refine) {
15786       
15787 #ifdef TRILIBRARY
15788       formskeleton(&m, &b, in->segmentlist,
15789                    in->segmentmarkerlist, in->numberofsegments);
15790 #else 
15791       formskeleton(&m, &b, polyfile, b.inpolyfilename);
15792 #endif 
15793     }
15794   }
15795 
15796 #ifndef NO_TIMER
15797   if (!b.quiet) {
15798     gettimeofday(&tv3, &tz);
15799     if (b.usesegments && !b.refine) {
15800       printf("Segment milliseconds:  %ld\n",
15801              1000l * (tv3.tv_sec - tv2.tv_sec) +
15802              (tv3.tv_usec - tv2.tv_usec) / 1000l);
15803     }
15804   }
15805 #endif 
15806 
15807   if (b.poly && (m.triangles.items > 0)) {
15808 #ifdef TRILIBRARY
15809     holearray = in->holelist;
15810     m.holes = in->numberofholes;
15811     regionarray = in->regionlist;
15812     m.regions = in->numberofregions;
15813 #else 
15814     readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15815               ®ionarray, &m.regions);
15816 #endif 
15817     if (!b.refine) {
15818       
15819       carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15820     }
15821   } else {
15822     
15823     
15824     
15825     m.holes = 0;
15826     m.regions = 0;
15827   }
15828 
15829 #ifndef NO_TIMER
15830   if (!b.quiet) {
15831     gettimeofday(&tv4, &tz);
15832     if (b.poly && !b.refine) {
15833       printf("Hole milliseconds:  %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15834              (tv4.tv_usec - tv3.tv_usec) / 1000l);
15835     }
15836   }
15837 #endif 
15838 
15839 #ifndef CDT_ONLY
15840   if (b.quality && (m.triangles.items > 0)) {
15841     enforcequality(&m, &b);           
15842   }
15843 #endif 
15844 
15845 #ifndef NO_TIMER
15846   if (!b.quiet) {
15847     gettimeofday(&tv5, &tz);
15848 #ifndef CDT_ONLY
15849     if (b.quality) {
15850       printf("Quality milliseconds:  %ld\n",
15851              1000l * (tv5.tv_sec - tv4.tv_sec) +
15852              (tv5.tv_usec - tv4.tv_usec) / 1000l);
15853     }
15854 #endif 
15855   }
15856 #endif 
15857 
15858   
15859   m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15860 
15861   if (b.order > 1) {
15862     highorder(&m, &b);       
15863   }
15864   if (!b.quiet) {
15865     printf("\n");
15866   }
15867 
15868 #ifdef TRILIBRARY
15869   if (b.jettison) {
15870     out->numberofpoints = m.vertices.items - m.undeads;
15871   } else {
15872     out->numberofpoints = m.vertices.items;
15873   }
15874   out->numberofpointattributes = m.nextras;
15875   out->numberoftriangles = m.triangles.items;
15876   out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15877   out->numberoftriangleattributes = m.eextras;
15878   out->numberofedges = m.edges;
15879   if (b.usesegments) {
15880     out->numberofsegments = m.subsegs.items;
15881   } else {
15882     out->numberofsegments = m.hullsize;
15883   }
15884   if (vorout != (struct triangulateio *) NULL) {
15885     vorout->numberofpoints = m.triangles.items;
15886     vorout->numberofpointattributes = m.nextras;
15887     vorout->numberofedges = m.edges;
15888   }
15889 #endif 
15890   
15891   
15892   if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15893     if (!b.quiet) {
15894 #ifdef TRILIBRARY
15895       printf("NOT writing vertices.\n");
15896 #else 
15897       printf("NOT writing a .node file.\n");
15898 #endif 
15899     }
15900     numbernodes(&m, &b);         
15901   } else {
15902     
15903 #ifdef TRILIBRARY
15904     writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15905                &out->pointmarkerlist);
15906 #else 
15907     writenodes(&m, &b, b.outnodefilename, argc, argv);
15908 #endif 
15909   }
15910   if (b.noelewritten) {
15911     if (!b.quiet) {
15912 #ifdef TRILIBRARY
15913       printf("NOT writing triangles.\n");
15914 #else 
15915       printf("NOT writing an .ele file.\n");
15916 #endif 
15917     }
15918   } else {
15919 #ifdef TRILIBRARY
15920     writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15921 #else 
15922     writeelements(&m, &b, b.outelefilename, argc, argv);
15923 #endif 
15924   }
15925   
15926   
15927   if (b.poly || b.convex) {
15928     
15929     if (b.nopolywritten || b.noiterationnum) {
15930       if (!b.quiet) {
15931 #ifdef TRILIBRARY
15932         printf("NOT writing segments.\n");
15933 #else 
15934         printf("NOT writing a .poly file.\n");
15935 #endif 
15936       }
15937     } else {
15938 #ifdef TRILIBRARY
15939       writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15940       out->numberofholes = m.holes;
15941       out->numberofregions = m.regions;
15942       if (b.poly) {
15943         out->holelist = in->holelist;
15944         out->regionlist = in->regionlist;
15945       } else {
15946         out->holelist = (REAL *) NULL;
15947         out->regionlist = (REAL *) NULL;
15948       }
15949 #else 
15950       writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15951                 m.regions, argc, argv);
15952 #endif 
15953     }
15954   }
15955 #ifndef TRILIBRARY
15956 #ifndef CDT_ONLY
15957   if (m.regions > 0) {
15958     trifree((VOID *) regionarray);
15959   }
15960 #endif 
15961   if (m.holes > 0) {
15962     trifree((VOID *) holearray);
15963   }
15964   if (b.geomview) {
15965     writeoff(&m, &b, b.offfilename, argc, argv);
15966   }
15967 #endif 
15968   if (b.edgesout) {
15969 #ifdef TRILIBRARY
15970     writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15971 #else 
15972     writeedges(&m, &b, b.edgefilename, argc, argv);
15973 #endif 
15974   }
15975   if (b.voronoi) {
15976 #ifdef TRILIBRARY
15977     writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15978                  &vorout->pointmarkerlist, &vorout->edgelist,
15979                  &vorout->edgemarkerlist, &vorout->normlist);
15980 #else 
15981     writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15982 #endif 
15983   }
15984   if (b.neighbors) {
15985 #ifdef TRILIBRARY
15986     writeneighbors(&m, &b, &out->neighborlist);
15987 #else 
15988     writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15989 #endif 
15990   }
15991 
15992   if (!b.quiet) {
15993 #ifndef NO_TIMER
15994     gettimeofday(&tv6, &tz);
15995     printf("\nOutput milliseconds:  %ld\n",
15996            1000l * (tv6.tv_sec - tv5.tv_sec) +
15997            (tv6.tv_usec - tv5.tv_usec) / 1000l);
15998     printf("Total running milliseconds:  %ld\n",
15999            1000l * (tv6.tv_sec - tv0.tv_sec) +
16000            (tv6.tv_usec - tv0.tv_usec) / 1000l);
16001 #endif 
16002 
16003     statistics(&m, &b);
16004   }
16005 
16006 #ifndef REDUCED
16007   if (b.docheck) {
16008     checkmesh(&m, &b);
16009     checkdelaunay(&m, &b);
16010   }
16011 #endif 
16012 
16013   triangledeinit(&m, &b);
16014 #ifndef TRILIBRARY
16015   return 0;
16016 #endif 
16017 }