00001
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
00217
00218
00219
00220 #ifdef SINGLE
00221 #define REAL float
00222 #else
00223 #define REAL double
00224 #endif
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
00276
00277
00278
00279 #define INEXACT
00280
00281
00282
00283
00284 #define FILENAMESIZE 2048
00285
00286
00287
00288
00289 #define INPUTLINESIZE 1024
00290
00291
00292
00293
00294
00295 #define TRIPERBLOCK 4092
00296 #define SUBSEGPERBLOCK 508
00297 #define VERTEXPERBLOCK 4092
00298 #define VIRUSPERBLOCK 1020
00299
00300 #define BADSUBSEGPERBLOCK 252
00301
00302 #define BADTRIPERBLOCK 4092
00303
00304 #define FLIPSTACKERPERBLOCK 252
00305
00306 #define SPLAYNODEPERBLOCK 508
00307
00308
00309
00310
00311
00312 #define INPUTVERTEX 0
00313 #define SEGMENTVERTEX 1
00314 #define FREEVERTEX 2
00315 #define DEADVERTEX -32768
00316 #define UNDEADVERTEX -32767
00317
00318
00319
00320
00321
00322 #define VOID int
00323
00324
00325
00326
00327
00328
00329
00330 #define SAMPLEFACTOR 11
00331
00332
00333
00334
00335
00336 #define SAMPLERATE 10
00337
00338
00339
00340 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
00341
00342
00343
00344 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
00345
00346
00347
00348 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
00349
00350 #include <stdio.h>
00351 #include <stdlib.h>
00352 #include <string.h>
00353 #include <math.h>
00354 #ifndef NO_TIMER
00355 #include <sys/time.h>
00356 #endif
00357 #ifdef CPU86
00358 #include <float.h>
00359 #endif
00360 #ifdef LINUX
00361 #include <fpu_control.h>
00362 #endif
00363 #ifdef TRILIBRARY
00364 #include "triangle.h"
00365 #endif
00366
00367
00368
00369 #ifndef TRILIBRARY
00370 char *readline();
00371 char *findfield();
00372 #endif
00373
00374
00375
00376
00377
00378 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
00379
00380
00381
00382
00383
00384
00385
00386 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
00387 DUPLICATEVERTEX};
00388
00389
00390
00391
00392
00393
00394 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
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
00510
00511
00512
00513 typedef REAL **triangle;
00514
00515
00516
00517
00518
00519
00520 struct otri {
00521 triangle *tri;
00522 int orient;
00523 };
00524
00525
00526
00527
00528
00529
00530 typedef REAL **subseg;
00531
00532
00533
00534
00535
00536
00537 struct osub {
00538 subseg *ss;
00539 int ssorient;
00540 };
00541
00542
00543
00544
00545
00546
00547 typedef REAL *vertex;
00548
00549
00550
00551
00552 struct badsubseg {
00553 subseg encsubseg;
00554 vertex subsegorg, subsegdest;
00555 };
00556
00557
00558
00559
00560
00561 struct badtriang {
00562 triangle poortri;
00563 REAL key;
00564 vertex triangorg, triangdest, triangapex;
00565 struct badtriang *nexttriang;
00566 };
00567
00568
00569
00570
00571
00572 struct flipstacker {
00573 triangle flippedtri;
00574 struct flipstacker *prevflip;
00575 };
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 struct event {
00588 REAL xkey, ykey;
00589 VOID *eventptr;
00590 int heapposition;
00591 };
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 struct splaynode {
00605 struct otri keyedge;
00606 vertex keydest;
00607 struct splaynode *lchild, *rchild;
00608 };
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 struct memorypool {
00634 VOID **firstblock, **nowblock;
00635 VOID *nextitem;
00636 VOID *deaditemstack;
00637 VOID **pathblock;
00638 VOID *pathitem;
00639 int alignbytes;
00640 int itembytes;
00641 int itemsperblock;
00642 int itemsfirstblock;
00643 long items, maxitems;
00644 int unallocateditems;
00645 int pathitemsleft;
00646 };
00647
00648
00649
00650
00651 REAL splitter;
00652 REAL epsilon;
00653 REAL resulterrbound;
00654 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00655 REAL iccerrboundA, iccerrboundB, iccerrboundC;
00656 REAL o3derrboundA, o3derrboundB, o3derrboundC;
00657
00658
00659
00660 unsigned long randomseed;
00661
00662
00663
00664
00665
00666 struct mesh {
00667
00668
00669
00670
00671
00672 struct memorypool triangles;
00673 struct memorypool subsegs;
00674 struct memorypool vertices;
00675 struct memorypool viri;
00676 struct memorypool badsubsegs;
00677 struct memorypool badtriangles;
00678 struct memorypool flipstackers;
00679 struct memorypool splaynodes;
00680
00681
00682
00683
00684 struct badtriang *queuefront[4096];
00685 struct badtriang *queuetail[4096];
00686 int nextnonemptyq[4096];
00687 int firstnonemptyq;
00688
00689
00690
00691 struct flipstacker *lastflip;
00692
00693
00694
00695 REAL xmin, xmax, ymin, ymax;
00696 REAL xminextreme;
00697 int invertices;
00698 int inelements;
00699 int insegments;
00700 int holes;
00701 int regions;
00702 int undeads;
00703 long edges;
00704 int mesh_dim;
00705 int nextras;
00706 int eextras;
00707 long hullsize;
00708 int steinerleft;
00709 int vertexmarkindex;
00710 int vertex2triindex;
00711 int highorderindex;
00712 int elemattribindex;
00713 int areaboundindex;
00714 int checksegments;
00715 int checkquality;
00716 int readnodefile;
00717 long samples;
00718
00719 long incirclecount;
00720 long counterclockcount;
00721 long orient3dcount;
00722 long hyperbolacount;
00723 long circumcentercount;
00724 long circletopcount;
00725
00726
00727
00728 vertex infvertex1, infvertex2, infvertex3;
00729
00730
00731
00732 triangle *dummytri;
00733 triangle *dummytribase;
00734
00735
00736
00737
00738
00739 subseg *dummysub;
00740 subseg *dummysubbase;
00741
00742
00743
00744
00745 struct otri recenttri;
00746
00747 };
00748
00749
00750
00751
00752
00753 struct behavior {
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
00785
00786
00787
00788 int poly, refine, quality, vararea, fixedarea, usertest;
00789 int regionattrib, convex, weighted, jettison;
00790 int firstnumber;
00791 int edgesout, voronoi, neighbors, geomview;
00792 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
00793 int noholes, noexact, conformdel;
00794 int incremental, sweepline, dwyer;
00795 int splitseg;
00796 int docheck;
00797 int quiet, verbose;
00798 int usesegments;
00799 int order;
00800 int nobisect;
00801 int steiner;
00802 REAL minangle, goodangle, offconstant;
00803 REAL maxarea;
00804
00805
00806
00807 #ifndef TRILIBRARY
00808 char innodefilename[FILENAMESIZE];
00809 char inelefilename[FILENAMESIZE];
00810 char inpolyfilename[FILENAMESIZE];
00811 char areafilename[FILENAMESIZE];
00812 char outnodefilename[FILENAMESIZE];
00813 char outelefilename[FILENAMESIZE];
00814 char outpolyfilename[FILENAMESIZE];
00815 char edgefilename[FILENAMESIZE];
00816 char vnodefilename[FILENAMESIZE];
00817 char vedgefilename[FILENAMESIZE];
00818 char neighborfilename[FILENAMESIZE];
00819 char offfilename[FILENAMESIZE];
00820 #endif
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
00928
00929
00930
00931
00935
00936
00937 int plus1mod3[3] = {1, 2, 0};
00938 int minus1mod3[3] = {2, 0, 1};
00939
00940
00941
00942
00943
00944
00945
00946
00947 #define decode(ptr, otri) \
00948 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
00949 (otri).tri = (triangle *) \
00950 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
00951
00952
00953
00954
00955
00956 #define encode(otri) \
00957 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967 #define sym(otri1, otri2) \
00968 ptr = (otri1).tri[(otri1).orient]; \
00969 decode(ptr, otri2);
00970
00971 #define symself(otri) \
00972 ptr = (otri).tri[(otri).orient]; \
00973 decode(ptr, otri);
00974
00975
00976
00977 #define lnext(otri1, otri2) \
00978 (otri2).tri = (otri1).tri; \
00979 (otri2).orient = plus1mod3[(otri1).orient]
00980
00981 #define lnextself(otri) \
00982 (otri).orient = plus1mod3[(otri).orient]
00983
00984
00985
00986 #define lprev(otri1, otri2) \
00987 (otri2).tri = (otri1).tri; \
00988 (otri2).orient = minus1mod3[(otri1).orient]
00989
00990 #define lprevself(otri) \
00991 (otri).orient = minus1mod3[(otri).orient]
00992
00993
00994
00995
00996
00997 #define onext(otri1, otri2) \
00998 lprev(otri1, otri2); \
00999 symself(otri2);
01000
01001 #define onextself(otri) \
01002 lprevself(otri); \
01003 symself(otri);
01004
01005
01006
01007
01008
01009 #define oprev(otri1, otri2) \
01010 sym(otri1, otri2); \
01011 lnextself(otri2);
01012
01013 #define oprevself(otri) \
01014 symself(otri); \
01015 lnextself(otri);
01016
01017
01018
01019
01020
01021 #define dnext(otri1, otri2) \
01022 sym(otri1, otri2); \
01023 lprevself(otri2);
01024
01025 #define dnextself(otri) \
01026 symself(otri); \
01027 lprevself(otri);
01028
01029
01030
01031
01032
01033 #define dprev(otri1, otri2) \
01034 lnext(otri1, otri2); \
01035 symself(otri2);
01036
01037 #define dprevself(otri) \
01038 lnextself(otri); \
01039 symself(otri);
01040
01041
01042
01043
01044
01045 #define rnext(otri1, otri2) \
01046 sym(otri1, otri2); \
01047 lnextself(otri2); \
01048 symself(otri2);
01049
01050 #define rnextself(otri) \
01051 symself(otri); \
01052 lnextself(otri); \
01053 symself(otri);
01054
01055
01056
01057
01058
01059 #define rprev(otri1, otri2) \
01060 sym(otri1, otri2); \
01061 lprevself(otri2); \
01062 symself(otri2);
01063
01064 #define rprevself(otri) \
01065 symself(otri); \
01066 lprevself(otri); \
01067 symself(otri);
01068
01069
01070
01071
01072 #define org(otri, vertexptr) \
01073 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
01074
01075 #define dest(otri, vertexptr) \
01076 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
01077
01078 #define apex(otri, vertexptr) \
01079 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
01080
01081 #define setorg(otri, vertexptr) \
01082 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01083
01084 #define setdest(otri, vertexptr) \
01085 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01086
01087 #define setapex(otri, vertexptr) \
01088 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
01089
01090
01091
01092 #define bond(otri1, otri2) \
01093 (otri1).tri[(otri1).orient] = encode(otri2); \
01094 (otri2).tri[(otri2).orient] = encode(otri1)
01095
01096
01097
01098
01099
01100
01101 #define dissolve(otri) \
01102 (otri).tri[(otri).orient] = (triangle) m->dummytri
01103
01104
01105
01106 #define otricopy(otri1, otri2) \
01107 (otri2).tri = (otri1).tri; \
01108 (otri2).orient = (otri1).orient
01109
01110
01111
01112 #define otriequal(otri1, otri2) \
01113 (((otri1).tri == (otri2).tri) && \
01114 ((otri1).orient == (otri2).orient))
01115
01116
01117
01118
01119 #define infect(otri) \
01120 (otri).tri[6] = (triangle) \
01121 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
01122
01123 #define uninfect(otri) \
01124 (otri).tri[6] = (triangle) \
01125 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
01126
01127
01128
01129 #define infected(otri) \
01130 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
01131
01132
01133
01134 #define elemattribute(otri, attnum) \
01135 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
01136
01137 #define setelemattribute(otri, attnum, value) \
01138 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
01139
01140
01141
01142 #define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
01143
01144 #define setareabound(otri, value) \
01145 ((REAL *) (otri).tri)[m->areaboundindex] = value
01146
01147
01148
01149
01150
01151
01152 #define deadtri(tria) ((tria)[1] == (triangle) NULL)
01153
01154 #define killtri(tria) \
01155 (tria)[1] = (triangle) NULL; \
01156 (tria)[3] = (triangle) NULL
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 #define sdecode(sptr, osub) \
01168 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
01169 (osub).ss = (subseg *) \
01170 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
01171
01172
01173
01174
01175
01176 #define sencode(osub) \
01177 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
01178
01179
01180
01181 #define ssym(osub1, osub2) \
01182 (osub2).ss = (osub1).ss; \
01183 (osub2).ssorient = 1 - (osub1).ssorient
01184
01185 #define ssymself(osub) \
01186 (osub).ssorient = 1 - (osub).ssorient
01187
01188
01189
01190
01191 #define spivot(osub1, osub2) \
01192 sptr = (osub1).ss[(osub1).ssorient]; \
01193 sdecode(sptr, osub2)
01194
01195 #define spivotself(osub) \
01196 sptr = (osub).ss[(osub).ssorient]; \
01197 sdecode(sptr, osub)
01198
01199
01200
01201
01202 #define snext(osub1, osub2) \
01203 sptr = (osub1).ss[1 - (osub1).ssorient]; \
01204 sdecode(sptr, osub2)
01205
01206 #define snextself(osub) \
01207 sptr = (osub).ss[1 - (osub).ssorient]; \
01208 sdecode(sptr, osub)
01209
01210
01211
01212
01213 #define sorg(osub, vertexptr) \
01214 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
01215
01216 #define sdest(osub, vertexptr) \
01217 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
01218
01219 #define setsorg(osub, vertexptr) \
01220 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
01221
01222 #define setsdest(osub, vertexptr) \
01223 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
01224
01225 #define segorg(osub, vertexptr) \
01226 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
01227
01228 #define segdest(osub, vertexptr) \
01229 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
01230
01231 #define setsegorg(osub, vertexptr) \
01232 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
01233
01234 #define setsegdest(osub, vertexptr) \
01235 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
01236
01237
01238
01239
01240
01241 #define mark(osub) (* (int *) ((osub).ss + 8))
01242
01243 #define setmark(osub, value) \
01244 * (int *) ((osub).ss + 8) = value
01245
01246
01247
01248 #define sbond(osub1, osub2) \
01249 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
01250 (osub2).ss[(osub2).ssorient] = sencode(osub1)
01251
01252
01253
01254
01255 #define sdissolve(osub) \
01256 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
01257
01258
01259
01260 #define subsegcopy(osub1, osub2) \
01261 (osub2).ss = (osub1).ss; \
01262 (osub2).ssorient = (osub1).ssorient
01263
01264
01265
01266 #define subsegequal(osub1, osub2) \
01267 (((osub1).ss == (osub2).ss) && \
01268 ((osub1).ssorient == (osub2).ssorient))
01269
01270
01271
01272
01273
01274
01275 #define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
01276
01277 #define killsubseg(sub) \
01278 (sub)[1] = (subseg) NULL; \
01279 (sub)[2] = (subseg) NULL
01280
01281
01282
01283
01284
01285
01286
01287 #define tspivot(otri, osub) \
01288 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
01289 sdecode(sptr, osub)
01290
01291
01292
01293
01294 #define stpivot(osub, otri) \
01295 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
01296 decode(ptr, otri)
01297
01298
01299
01300 #define tsbond(otri, osub) \
01301 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
01302 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
01303
01304
01305
01306 #define tsdissolve(otri) \
01307 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
01308
01309
01310
01311 #define stdissolve(osub) \
01312 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
01313
01314
01315
01316
01317
01318 #define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
01319
01320 #define setvertexmark(vx, value) \
01321 ((int *) (vx))[m->vertexmarkindex] = value
01322
01323 #define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
01324
01325 #define setvertextype(vx, value) \
01326 ((int *) (vx))[m->vertexmarkindex + 1] = value
01327
01328 #define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
01329
01330 #define setvertex2tri(vx, value) \
01331 ((triangle *) (vx))[m->vertex2triindex] = value
01332
01335
01336
01337
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364 #ifdef EXTERNAL_TEST
01365
01366 int triunsuitable();
01367
01368 #else
01369
01370 #ifdef ANSI_DECLARATORS
01371 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
01372 #else
01373 int triunsuitable(triorg, tridest, triapex, area)
01374 vertex triorg;
01375 vertex tridest;
01376 vertex triapex;
01377 REAL area;
01378 #endif
01379
01380 {
01381 REAL dxoa, dxda, dxod;
01382 REAL dyoa, dyda, dyod;
01383 REAL oalen, dalen, odlen;
01384 REAL maxlen;
01385
01386 dxoa = triorg[0] - triapex[0];
01387 dyoa = triorg[1] - triapex[1];
01388 dxda = tridest[0] - triapex[0];
01389 dyda = tridest[1] - triapex[1];
01390 dxod = triorg[0] - tridest[0];
01391 dyod = triorg[1] - tridest[1];
01392
01393 oalen = dxoa * dxoa + dyoa * dyoa;
01394 dalen = dxda * dxda + dyda * dyda;
01395 odlen = dxod * dxod + dyod * dyod;
01396
01397 maxlen = (dalen > oalen) ? dalen : oalen;
01398 maxlen = (odlen > maxlen) ? odlen : maxlen;
01399
01400 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
01401 return 1;
01402 } else {
01403 return 0;
01404 }
01405 }
01406
01407 #endif
01408
01411
01412
01413
01417 #ifdef ANSI_DECLARATORS
01418 void triexit(int status)
01419 #else
01420 void triexit(status)
01421 int status;
01422 #endif
01423
01424 {
01425 exit(status);
01426 }
01427
01428 #ifdef ANSI_DECLARATORS
01429 VOID *trimalloc(int size)
01430 #else
01431 VOID *trimalloc(size)
01432 int size;
01433 #endif
01434
01435 {
01436 VOID *memptr;
01437
01438 memptr = (VOID *) malloc((unsigned int) size);
01439 if (memptr == (VOID *) NULL) {
01440 printf("Error: Out of memory.\n");
01441 triexit(1);
01442 }
01443 return(memptr);
01444 }
01445
01446 #ifdef ANSI_DECLARATORS
01447 void trifree(VOID *memptr)
01448 #else
01449 void trifree(memptr)
01450 VOID *memptr;
01451 #endif
01452
01453 {
01454 free(memptr);
01455 }
01456
01459
01460
01461
01465
01466
01467
01468
01469
01470
01471 #ifndef TRILIBRARY
01472
01473 void syntax()
01474 {
01475 #ifdef CDT_ONLY
01476 #ifdef REDUCED
01477 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
01478 #else
01479 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
01480 #endif
01481 #else
01482 #ifdef REDUCED
01483 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
01484 #else
01485 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
01486 #endif
01487 #endif
01488
01489 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
01490 #ifndef CDT_ONLY
01491 printf(" -r Refines a previously generated mesh.\n");
01492 printf(
01493 " -q Quality mesh generation. A minimum angle may be specified.\n");
01494 printf(" -a Applies a maximum triangle area constraint.\n");
01495 printf(" -u Applies a user-defined triangle constraint.\n");
01496 #endif
01497 printf(
01498 " -A Applies attributes to identify triangles in certain regions.\n");
01499 printf(" -c Encloses the convex hull with segments.\n");
01500 #ifndef CDT_ONLY
01501 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
01502 #endif
01503
01504
01505
01506
01507 printf(" -j Jettison unused vertices from output .node file.\n");
01508 printf(" -e Generates an edge list.\n");
01509 printf(" -v Generates a Voronoi diagram.\n");
01510 printf(" -n Generates a list of triangle neighbors.\n");
01511 printf(" -g Generates an .off file for Geomview.\n");
01512 printf(" -B Suppresses output of boundary information.\n");
01513 printf(" -P Suppresses output of .poly file.\n");
01514 printf(" -N Suppresses output of .node file.\n");
01515 printf(" -E Suppresses output of .ele file.\n");
01516 printf(" -I Suppresses mesh iteration numbers.\n");
01517 printf(" -O Ignores holes in .poly file.\n");
01518 printf(" -X Suppresses use of exact arithmetic.\n");
01519 printf(" -z Numbers all items starting from zero (rather than one).\n");
01520 printf(" -o2 Generates second-order subparametric elements.\n");
01521 #ifndef CDT_ONLY
01522 printf(" -Y Suppresses boundary segment splitting.\n");
01523 printf(" -S Specifies maximum number of added Steiner points.\n");
01524 #endif
01525 #ifndef REDUCED
01526 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
01527 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
01528 #endif
01529 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
01530 #ifndef REDUCED
01531 #ifndef CDT_ONLY
01532 printf(
01533 " -s Force segments into mesh by splitting (instead of using CDT).\n");
01534 #endif
01535 printf(" -C Check consistency of final mesh.\n");
01536 #endif
01537 printf(" -Q Quiet: No terminal output except errors.\n");
01538 printf(" -V Verbose: Detailed information on what I'm doing.\n");
01539 printf(" -h Help: Detailed instructions for Triangle.\n");
01540 triexit(0);
01541 }
01542
01543 #endif
01544
01545
01546
01547
01548
01549
01550
01551 #ifndef TRILIBRARY
01552
01553 void info()
01554 {
01555 printf("Triangle\n");
01556 printf(
01557 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
01558 printf("Version 1.6\n\n");
01559 printf(
01560 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
01561 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
01562 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
01563 printf(
01564 "Created as part of the Quake project (tools for earthquake simulation).\n");
01565 printf(
01566 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
01567 printf("There is no warranty whatsoever. Use at your own risk.\n");
01568 #ifdef SINGLE
01569 printf("This executable is compiled for single precision arithmetic.\n\n\n");
01570 #else
01571 printf("This executable is compiled for double precision arithmetic.\n\n\n");
01572 #endif
01573 printf(
01574 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
01575 printf(
01576 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
01577 printf(
01578 "high-quality triangular meshes. The latter can be generated with no small\n"
01579 );
01580 printf(
01581 "or large angles, and are thus suitable for finite element analysis. If no\n"
01582 );
01583 printf(
01584 "command line switch is specified, your .node input file is read, and the\n");
01585 printf(
01586 "Delaunay triangulation is returned in .node and .ele output files. The\n");
01587 printf("command syntax is:\n\n");
01588 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
01589 printf(
01590 "Underscores indicate that numbers may optionally follow certain switches.\n");
01591 printf(
01592 "Do not leave any space between a switch and its numeric parameter.\n");
01593 printf(
01594 "input_file must be a file with extension .node, or extension .poly if the\n");
01595 printf(
01596 "-p switch is used. If -r is used, you must supply .node and .ele files,\n");
01597 printf(
01598 "and possibly a .poly file and an .area file as well. The formats of these\n"
01599 );
01600 printf("files are described below.\n\n");
01601 printf("Command Line Switches:\n\n");
01602 printf(
01603 " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
01604 );
01605 printf(
01606 " vertices, segments, holes, regional attributes, and regional area\n");
01607 printf(
01608 " constraints. Generates a constrained Delaunay triangulation (CDT)\n"
01609 );
01610 printf(
01611 " fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
01612 printf(
01613 " constrained Delaunay triangulation (CCDT). If you want a truly\n");
01614 printf(
01615 " Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
01616 printf(
01617 " well. When -p is not used, Triangle reads a .node file by default.\n"
01618 );
01619 printf(
01620 " -r Refines a previously generated mesh. The mesh is read from a .node\n"
01621 );
01622 printf(
01623 " file and an .ele file. If -p is also used, a .poly file is read\n");
01624 printf(
01625 " and used to constrain segments in the mesh. If -a is also used\n");
01626 printf(
01627 " (with no number following), an .area file is read and used to\n");
01628 printf(
01629 " impose area constraints on the mesh. Further details on refinement\n"
01630 );
01631 printf(" appear below.\n");
01632 printf(
01633 " -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
01634 printf(
01635 " Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
01636 );
01637 printf(
01638 " ensure that all angles are between 20 and 140 degrees. An\n");
01639 printf(
01640 " alternative bound on the minimum angle, replacing 20 degrees, may\n");
01641 printf(
01642 " be specified after the `q'. The specified angle may include a\n");
01643 printf(
01644 " decimal point, but not exponential notation. Note that a bound of\n"
01645 );
01646 printf(
01647 " theta degrees on the smallest angle also implies a bound of\n");
01648 printf(
01649 " (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
01650 );
01651 printf(
01652 " degrees or smaller, Triangle is mathematically guaranteed to\n");
01653 printf(
01654 " terminate (assuming infinite precision arithmetic--Triangle may\n");
01655 printf(
01656 " fail to terminate if you run out of precision). In practice,\n");
01657 printf(
01658 " Triangle often succeeds for minimum angles up to 34 degrees. For\n");
01659 printf(
01660 " some meshes, however, you might need to reduce the minimum angle to\n"
01661 );
01662 printf(
01663 " avoid problems associated with insufficient floating-point\n");
01664 printf(" precision.\n");
01665 printf(
01666 " -a Imposes a maximum triangle area. If a number follows the `a', no\n");
01667 printf(
01668 " triangle is generated whose area is larger than that number. If no\n"
01669 );
01670 printf(
01671 " number is specified, an .area file (if -r is used) or .poly file\n");
01672 printf(
01673 " (if -r is not used) specifies a set of maximum area constraints.\n");
01674 printf(
01675 " An .area file contains a separate area constraint for each\n");
01676 printf(
01677 " triangle, and is useful for refining a finite element mesh based on\n"
01678 );
01679 printf(
01680 " a posteriori error estimates. A .poly file can optionally contain\n"
01681 );
01682 printf(
01683 " an area constraint for each segment-bounded region, thereby\n");
01684 printf(
01685 " controlling triangle densities in a first triangulation of a PSLG.\n"
01686 );
01687 printf(
01688 " You can impose both a fixed area constraint and a varying area\n");
01689 printf(
01690 " constraint by invoking the -a switch twice, once with and once\n");
01691 printf(
01692 " without a number following. Each area specified may include a\n");
01693 printf(" decimal point.\n");
01694 printf(
01695 " -u Imposes a user-defined constraint on triangle size. There are two\n"
01696 );
01697 printf(
01698 " ways to use this feature. One is to edit the triunsuitable()\n");
01699 printf(
01700 " procedure in triangle.c to encode any constraint you like, then\n");
01701 printf(
01702 " recompile Triangle. The other is to compile triangle.c with the\n");
01703 printf(
01704 " EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
01705 printf(
01706 " link Triangle with a separate object file that implements\n");
01707 printf(
01708 " triunsuitable(). In either case, the -u switch causes the user-\n");
01709 printf(" defined test to be applied to every triangle.\n");
01710 printf(
01711 " -A Assigns an additional floating-point attribute to each triangle\n");
01712 printf(
01713 " that identifies what segment-bounded region each triangle belongs\n");
01714 printf(
01715 " to. Attributes are assigned to regions by the .poly file. If a\n");
01716 printf(
01717 " region is not explicitly marked by the .poly file, triangles in\n");
01718 printf(
01719 " that region are assigned an attribute of zero. The -A switch has\n");
01720 printf(
01721 " an effect only when the -p switch is used and the -r switch is not.\n"
01722 );
01723 printf(
01724 " -c Creates segments on the convex hull of the triangulation. If you\n");
01725 printf(
01726 " are triangulating a vertex set, this switch causes a .poly file to\n"
01727 );
01728 printf(
01729 " be written, containing all edges of the convex hull. If you are\n");
01730 printf(
01731 " triangulating a PSLG, this switch specifies that the whole convex\n");
01732 printf(
01733 " hull of the PSLG should be triangulated, regardless of what\n");
01734 printf(
01735 " segments the PSLG has. If you do not use this switch when\n");
01736 printf(
01737 " triangulating a PSLG, Triangle assumes that you have identified the\n"
01738 );
01739 printf(
01740 " region to be triangulated by surrounding it with segments of the\n");
01741 printf(
01742 " input PSLG. Beware: if you are not careful, this switch can cause\n"
01743 );
01744 printf(
01745 " the introduction of an extremely thin angle between a PSLG segment\n"
01746 );
01747 printf(
01748 " and a convex hull segment, which can cause overrefinement (and\n");
01749 printf(
01750 " possibly failure if Triangle runs out of precision). If you are\n");
01751 printf(
01752 " refining a mesh, the -c switch works differently: it causes a\n");
01753 printf(
01754 " .poly file to be written containing the boundary edges of the mesh\n"
01755 );
01756 printf(" (useful if no .poly file was read).\n");
01757 printf(
01758 " -D Conforming Delaunay triangulation: use this switch if you want to\n"
01759 );
01760 printf(
01761 " ensure that all the triangles in the mesh are Delaunay, and not\n");
01762 printf(
01763 " merely constrained Delaunay; or if you want to ensure that all the\n"
01764 );
01765 printf(
01766 " Voronoi vertices lie within the triangulation. (Some finite volume\n"
01767 );
01768 printf(
01769 " methods have this requirement.) This switch invokes Ruppert's\n");
01770 printf(
01771 " original algorithm, which splits every subsegment whose diametral\n");
01772 printf(
01773 " circle is encroached. It usually increases the number of vertices\n"
01774 );
01775 printf(" and triangles.\n");
01776 printf(
01777 " -j Jettisons vertices that are not part of the final triangulation\n");
01778 printf(
01779 " from the output .node file. By default, Triangle copies all\n");
01780 printf(
01781 " vertices in the input .node file to the output .node file, in the\n");
01782 printf(
01783 " same order, so their indices do not change. The -j switch prevents\n"
01784 );
01785 printf(
01786 " duplicated input vertices, or vertices `eaten' by holes, from\n");
01787 printf(
01788 " appearing in the output .node file. Thus, if two input vertices\n");
01789 printf(
01790 " have exactly the same coordinates, only the first appears in the\n");
01791 printf(
01792 " output. If any vertices are jettisoned, the vertex numbering in\n");
01793 printf(
01794 " the output .node file differs from that of the input .node file.\n");
01795 printf(
01796 " -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
01797 printf(
01798 " -v Outputs the Voronoi diagram associated with the triangulation.\n");
01799 printf(
01800 " Does not attempt to detect degeneracies, so some Voronoi vertices\n");
01801 printf(
01802 " may be duplicated. See the discussion of Voronoi diagrams below.\n");
01803 printf(
01804 " -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
01805 printf(" triangle.\n");
01806 printf(
01807 " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
01808 );
01809 printf(" viewing with the Geometry Center's Geomview package.\n");
01810 printf(
01811 " -B No boundary markers in the output .node, .poly, and .edge output\n");
01812 printf(
01813 " files. See the detailed discussion of boundary markers below.\n");
01814 printf(
01815 " -P No output .poly file. Saves disk space, but you lose the ability\n");
01816 printf(
01817 " to maintain constraining segments on later refinements of the mesh.\n"
01818 );
01819 printf(" -N No output .node file.\n");
01820 printf(" -E No output .ele file.\n");
01821 printf(
01822 " -I No iteration numbers. Suppresses the output of .node and .poly\n");
01823 printf(
01824 " files, so your input files won't be overwritten. (If your input is\n"
01825 );
01826 printf(
01827 " a .poly file only, a .node file is written.) Cannot be used with\n");
01828 printf(
01829 " the -r switch, because that would overwrite your input .ele file.\n");
01830 printf(
01831 " Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
01832 printf(
01833 " using a .node file for input, because no .node file is written, so\n"
01834 );
01835 printf(" there is no record of any added Steiner points.\n");
01836 printf(" -O No holes. Ignores the holes in the .poly file.\n");
01837 printf(
01838 " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
01839 );
01840 printf(
01841 " arithmetic for certain tests if it thinks the inexact tests are not\n"
01842 );
01843 printf(
01844 " accurate enough. Exact arithmetic ensures the robustness of the\n");
01845 printf(
01846 " triangulation algorithms, despite floating-point roundoff error.\n");
01847 printf(
01848 " Disabling exact arithmetic with the -X switch causes a small\n");
01849 printf(
01850 " improvement in speed and creates the possibility that Triangle will\n"
01851 );
01852 printf(" fail to produce a valid mesh. Not recommended.\n");
01853 printf(
01854 " -z Numbers all items starting from zero (rather than one). Note that\n"
01855 );
01856 printf(
01857 " this switch is normally overridden by the value used to number the\n"
01858 );
01859 printf(
01860 " first vertex of the input .node or .poly file. However, this\n");
01861 printf(
01862 " switch is useful when calling Triangle from another program.\n");
01863 printf(
01864 " -o2 Generates second-order subparametric elements with six nodes each.\n"
01865 );
01866 printf(
01867 " -Y No new vertices on the boundary. This switch is useful when the\n");
01868 printf(
01869 " mesh boundary must be preserved so that it conforms to some\n");
01870 printf(
01871 " adjacent mesh. Be forewarned that you will probably sacrifice much\n"
01872 );
01873 printf(
01874 " of the quality of the mesh; Triangle will try, but the resulting\n");
01875 printf(
01876 " mesh may contain poorly shaped triangles. Works well if all the\n");
01877 printf(
01878 " boundary vertices are closely spaced. Specify this switch twice\n");
01879 printf(
01880 " (`-YY') to prevent all segment splitting, including internal\n");
01881 printf(" boundaries.\n");
01882 printf(
01883 " -S Specifies the maximum number of Steiner points (vertices that are\n");
01884 printf(
01885 " not in the input, but are added to meet the constraints on minimum\n"
01886 );
01887 printf(
01888 " angle and maximum area). The default is to allow an unlimited\n");
01889 printf(
01890 " number. If you specify this switch with no number after it,\n");
01891 printf(
01892 " the limit is set to zero. Triangle always adds vertices at segment\n"
01893 );
01894 printf(
01895 " intersections, even if it needs to use more vertices than the limit\n"
01896 );
01897 printf(
01898 " you set. When Triangle inserts segments by splitting (-s), it\n");
01899 printf(
01900 " always adds enough vertices to ensure that all the segments of the\n"
01901 );
01902 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
01903 printf(
01904 " -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
01905 printf(
01906 " construct a Delaunay triangulation. Try it if the divide-and-\n");
01907 printf(" conquer algorithm fails.\n");
01908 printf(
01909 " -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
01910 printf(
01911 " triangulation. Warning: does not use exact arithmetic for all\n");
01912 printf(" calculations. An exact result is not guaranteed.\n");
01913 printf(
01914 " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
01915 printf(
01916 " default, Triangle alternates between vertical and horizontal cuts,\n"
01917 );
01918 printf(
01919 " which usually improve the speed except with vertex sets that are\n");
01920 printf(
01921 " small or short and wide. This switch is primarily of theoretical\n");
01922 printf(" interest.\n");
01923 printf(
01924 " -s Specifies that segments should be forced into the triangulation by\n"
01925 );
01926 printf(
01927 " recursively splitting them at their midpoints, rather than by\n");
01928 printf(
01929 " generating a constrained Delaunay triangulation. Segment splitting\n"
01930 );
01931 printf(
01932 " is true to Ruppert's original algorithm, but can create needlessly\n"
01933 );
01934 printf(
01935 " small triangles. This switch is primarily of theoretical interest.\n"
01936 );
01937 printf(
01938 " -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
01939 );
01940 printf(
01941 " checking, even if the -X switch is used. Useful if you suspect\n");
01942 printf(" Triangle is buggy.\n");
01943 printf(
01944 " -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
01945 printf(" unless an error occurs.\n");
01946 printf(
01947 " -V Verbose: Gives detailed information about what Triangle is doing.\n"
01948 );
01949 printf(
01950 " Add more `V's for increasing amount of detail. `-V' is most\n");
01951 printf(
01952 " useful; itgives information on algorithmic progress and much more\n");
01953 printf(
01954 " detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
01955 printf(
01956 " prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
01957 );
01958 printf(" information only a debugger could love.\n");
01959 printf(" -h Help: Displays these instructions.\n");
01960 printf("\n");
01961 printf("Definitions:\n");
01962 printf("\n");
01963 printf(
01964 " A Delaunay triangulation of a vertex set is a triangulation whose\n");
01965 printf(
01966 " vertices are the vertex set, that covers the convex hull of the vertex\n");
01967 printf(
01968 " set. A Delaunay triangulation has the property that no vertex lies\n");
01969 printf(
01970 " inside the circumscribing circle (circle that passes through all three\n");
01971 printf(" vertices) of any triangle in the triangulation.\n\n");
01972 printf(
01973 " A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
01974 printf(
01975 " polygonal cells (some of which may be unbounded, meaning infinitely\n");
01976 printf(
01977 " large), where each cell is the set of points in the plane that are closer\n"
01978 );
01979 printf(
01980 " to some input vertex than to any other input vertex. The Voronoi diagram\n"
01981 );
01982 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
01983 printf(
01984 " A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
01985 printf(
01986 " Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
01987 );
01988 printf(
01989 " Segments may intersect each other only at their endpoints. The file\n");
01990 printf(" format for PSLGs (.poly files) is described below.\n\n");
01991 printf(
01992 " A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
01993 printf(
01994 " Delaunay triangulation, but each PSLG segment is present as a single edge\n"
01995 );
01996 printf(
01997 " of the CDT. (A constrained Delaunay triangulation is not truly a\n");
01998 printf(
01999 " Delaunay triangulation, because some of its triangles might not be\n");
02000 printf(
02001 " Delaunay.) By definition, a CDT does not have any vertices other than\n");
02002 printf(
02003 " those specified in the input PSLG. Depending on context, a CDT might\n");
02004 printf(
02005 " cover the convex hull of the PSLG, or it might cover only a segment-\n");
02006 printf(" bounded region (e.g. a polygon).\n\n");
02007 printf(
02008 " A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
02009 );
02010 printf(
02011 " each triangle is truly Delaunay, and each PSLG segment is represented by\n"
02012 );
02013 printf(
02014 " a linear contiguous sequence of edges of the triangulation. New vertices\n"
02015 );
02016 printf(
02017 " (not part of the PSLG) may appear, and each input segment may have been\n");
02018 printf(
02019 " subdivided into shorter edges (subsegments) by these additional vertices.\n"
02020 );
02021 printf(
02022 " The new vertices are frequently necessary to maintain the Delaunay\n");
02023 printf(" property while ensuring that every segment is represented.\n\n");
02024 printf(
02025 " A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
02026 printf(
02027 " triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
02028 printf(" vertices may appear, and input segments may be subdivided into\n");
02029 printf(
02030 " subsegments, but not to guarantee that segments are respected; rather, to\n"
02031 );
02032 printf(
02033 " improve the quality of the triangles. The high-quality meshes produced\n");
02034 printf(
02035 " by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
02036 printf(" with the -D switch.\n\n");
02037 printf("File Formats:\n\n");
02038 printf(
02039 " All files may contain comments prefixed by the character '#'. Vertices,\n"
02040 );
02041 printf(
02042 " triangles, edges, holes, and maximum area constraints must be numbered\n");
02043 printf(
02044 " consecutively, starting from either 1 or 0. Whichever you choose, all\n");
02045 printf(
02046 " input files must be consistent; if the vertices are numbered from 1, so\n");
02047 printf(
02048 " must be all other objects. Triangle automatically detects your choice\n");
02049 printf(
02050 " while reading the .node (or .poly) file. (When calling Triangle from\n");
02051 printf(
02052 " another program, use the -z switch if you wish to number objects from\n");
02053 printf(" zero.) Examples of these file formats are given below.\n\n");
02054 printf(" .node files:\n");
02055 printf(
02056 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02057 );
02058 printf(
02059 " <# of boundary markers (0 or 1)>\n"
02060 );
02061 printf(
02062 " Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02063 printf("\n");
02064 printf(
02065 " The attributes, which are typically floating-point values of physical\n");
02066 printf(
02067 " quantities (such as mass or conductivity) associated with the nodes of\n"
02068 );
02069 printf(
02070 " a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
02071 );
02072 printf(
02073 " -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
02074 );
02075 printf(" has attributes assigned to it by linear interpolation.\n\n");
02076 printf(
02077 " If the fourth entry of the first line is `1', the last column of the\n");
02078 printf(
02079 " remainder of the file is assumed to contain boundary markers. Boundary\n"
02080 );
02081 printf(
02082 " markers are used to identify boundary vertices and vertices resting on\n"
02083 );
02084 printf(
02085 " PSLG segments; a complete description appears in a section below. The\n"
02086 );
02087 printf(
02088 " .node file produced by Triangle contains boundary markers in the last\n");
02089 printf(" column unless they are suppressed by the -B switch.\n\n");
02090 printf(" .ele files:\n");
02091 printf(
02092 " First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
02093 printf(
02094 " Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
02095 printf("\n");
02096 printf(
02097 " Nodes are indices into the corresponding .node file. The first three\n");
02098 printf(
02099 " nodes are the corner vertices, and are listed in counterclockwise order\n"
02100 );
02101 printf(
02102 " around each triangle. (The remaining nodes, if any, depend on the type\n"
02103 );
02104 printf(" of finite element used.)\n\n");
02105 printf(
02106 " The attributes are just like those of .node files. Because there is no\n"
02107 );
02108 printf(
02109 " simple mapping from input to output triangles, Triangle attempts to\n");
02110 printf(
02111 " interpolate attributes, and may cause a lot of diffusion of attributes\n"
02112 );
02113 printf(
02114 " among nearby triangles as the triangulation is refined. Attributes do\n"
02115 );
02116 printf(" not diffuse across segments, so attributes used to identify\n");
02117 printf(" segment-bounded regions remain intact.\n\n");
02118 printf(
02119 " In .ele files produced by Triangle, each triangular element has three\n");
02120 printf(
02121 " nodes (vertices) unless the -o2 switch is used, in which case\n");
02122 printf(
02123 " subparametric quadratic elements with six nodes each are generated.\n");
02124 printf(
02125 " The first three nodes are the corners in counterclockwise order, and\n");
02126 printf(
02127 " the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
02128 printf(
02129 " opposite the first, second, and third vertices, respectively.\n");
02130 printf("\n");
02131 printf(" .poly files:\n");
02132 printf(
02133 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02134 );
02135 printf(
02136 " <# of boundary markers (0 or 1)>\n"
02137 );
02138 printf(
02139 " Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02140 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
02141 printf(
02142 " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
02143 printf(" One line: <# of holes>\n");
02144 printf(" Following lines: <hole #> <x> <y>\n");
02145 printf(
02146 " Optional line: <# of regional attributes and/or area constraints>\n");
02147 printf(
02148 " Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
02149 printf("\n");
02150 printf(
02151 " A .poly file represents a PSLG, as well as some additional information.\n"
02152 );
02153 printf(
02154 " The first section lists all the vertices, and is identical to the\n");
02155 printf(
02156 " format of .node files. <# of vertices> may be set to zero to indicate\n"
02157 );
02158 printf(
02159 " that the vertices are listed in a separate .node file; .poly files\n");
02160 printf(
02161 " produced by Triangle always have this format. A vertex set represented\n"
02162 );
02163 printf(
02164 " this way has the advantage that it may easily be triangulated with or\n");
02165 printf(
02166 " without segments (depending on whether the -p switch is invoked).\n");
02167 printf("\n");
02168 printf(
02169 " The second section lists the segments. Segments are edges whose\n");
02170 printf(
02171 " presence in the triangulation is enforced. (Depending on the choice of\n"
02172 );
02173 printf(
02174 " switches, segment might be subdivided into smaller edges). Each\n");
02175 printf(
02176 " segment is specified by listing the indices of its two endpoints. This\n"
02177 );
02178 printf(
02179 " means that you must include its endpoints in the vertex list. Each\n");
02180 printf(" segment, like each point, may have a boundary marker.\n\n");
02181 printf(
02182 " If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
02183 );
02184 printf(
02185 " Delaunay triangulation (CDT), in which each segment appears as a single\n"
02186 );
02187 printf(
02188 " edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
02189 );
02190 printf(
02191 " produces a conforming constrained Delaunay triangulation (CCDT), in\n");
02192 printf(
02193 " which segments may be subdivided into smaller edges. If -D is\n");
02194 printf(
02195 " selected, Triangle produces a conforming Delaunay triangulation, so\n");
02196 printf(
02197 " that every triangle is Delaunay, and not just constrained Delaunay.\n");
02198 printf("\n");
02199 printf(
02200 " The third section lists holes (and concavities, if -c is selected) in\n");
02201 printf(
02202 " the triangulation. Holes are specified by identifying a point inside\n");
02203 printf(
02204 " each hole. After the triangulation is formed, Triangle creates holes\n");
02205 printf(
02206 " by eating triangles, spreading out from each hole point until its\n");
02207 printf(
02208 " progress is blocked by segments in the PSLG. You must be careful to\n");
02209 printf(
02210 " enclose each hole in segments, or your whole triangulation might be\n");
02211 printf(
02212 " eaten away. If the two triangles abutting a segment are eaten, the\n");
02213 printf(
02214 " segment itself is also eaten. Do not place a hole directly on a\n");
02215 printf(" segment; if you do, Triangle chooses one side of the segment\n");
02216 printf(" arbitrarily.\n\n");
02217 printf(
02218 " The optional fourth section lists regional attributes (to be assigned\n");
02219 printf(
02220 " to all triangles in a region) and regional constraints on the maximum\n");
02221 printf(
02222 " triangle area. Triangle reads this section only if the -A switch is\n");
02223 printf(
02224 " used or the -a switch is used without a number following it, and the -r\n"
02225 );
02226 printf(
02227 " switch is not used. Regional attributes and area constraints are\n");
02228 printf(
02229 " propagated in the same manner as holes: you specify a point for each\n");
02230 printf(
02231 " attribute and/or constraint, and the attribute and/or constraint\n");
02232 printf(
02233 " affects the whole region (bounded by segments) containing the point.\n");
02234 printf(
02235 " If two values are written on a line after the x and y coordinate, the\n");
02236 printf(
02237 " first such value is assumed to be a regional attribute (but is only\n");
02238 printf(
02239 " applied if the -A switch is selected), and the second value is assumed\n"
02240 );
02241 printf(
02242 " to be a regional area constraint (but is only applied if the -a switch\n"
02243 );
02244 printf(
02245 " is selected). You may specify just one value after the coordinates,\n");
02246 printf(
02247 " which can serve as both an attribute and an area constraint, depending\n"
02248 );
02249 printf(
02250 " on the choice of switches. If you are using the -A and -a switches\n");
02251 printf(
02252 " simultaneously and wish to assign an attribute to some region without\n");
02253 printf(" imposing an area constraint, use a negative maximum area.\n\n");
02254 printf(
02255 " When a triangulation is created from a .poly file, you must either\n");
02256 printf(
02257 " enclose the entire region to be triangulated in PSLG segments, or\n");
02258 printf(
02259 " use the -c switch, which automatically creates extra segments that\n");
02260 printf(
02261 " enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
02262 );
02263 printf(
02264 " Triangle eats all triangles that are not enclosed by segments; if you\n");
02265 printf(
02266 " are not careful, your whole triangulation may be eaten away. If you do\n"
02267 );
02268 printf(
02269 " use the -c switch, you can still produce concavities by the appropriate\n"
02270 );
02271 printf(
02272 " placement of holes just inside the boundary of the convex hull.\n");
02273 printf("\n");
02274 printf(
02275 " An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
02276 printf(
02277 " upon segments (except, of course, the endpoints of each segment). You\n"
02278 );
02279 printf(
02280 " aren't required to make your .poly files ideal, but you should be aware\n"
02281 );
02282 printf(
02283 " of what can go wrong. Segment intersections are relatively safe--\n");
02284 printf(
02285 " Triangle calculates the intersection points for you and adds them to\n");
02286 printf(
02287 " the triangulation--as long as your machine's floating-point precision\n");
02288 printf(
02289 " doesn't become a problem. You are tempting the fates if you have three\n"
02290 );
02291 printf(
02292 " segments that cross at the same location, and expect Triangle to figure\n"
02293 );
02294 printf(
02295 " out where the intersection point is. Thanks to floating-point roundoff\n"
02296 );
02297 printf(
02298 " error, Triangle will probably decide that the three segments intersect\n"
02299 );
02300 printf(
02301 " at three different points, and you will find a minuscule triangle in\n");
02302 printf(
02303 " your output--unless Triangle tries to refine the tiny triangle, uses\n");
02304 printf(
02305 " up the last bit of machine precision, and fails to terminate at all.\n");
02306 printf(
02307 " You're better off putting the intersection point in the input files,\n");
02308 printf(
02309 " and manually breaking up each segment into two. Similarly, if you\n");
02310 printf(
02311 " place a vertex at the middle of a segment, and hope that Triangle will\n"
02312 );
02313 printf(
02314 " break up the segment at that vertex, you might get lucky. On the other\n"
02315 );
02316 printf(
02317 " hand, Triangle might decide that the vertex doesn't lie precisely on\n");
02318 printf(
02319 " the segment, and you'll have a needle-sharp triangle in your output--or\n"
02320 );
02321 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
02322 printf("\n");
02323 printf(
02324 " When Triangle reads a .poly file, it also writes a .poly file, which\n");
02325 printf(
02326 " includes all the subsegments--the edges that are parts of input\n");
02327 printf(
02328 " segments. If the -c switch is used, the output .poly file also\n");
02329 printf(
02330 " includes all of the edges on the convex hull. Hence, the output .poly\n"
02331 );
02332 printf(
02333 " file is useful for finding edges associated with input segments and for\n"
02334 );
02335 printf(
02336 " setting boundary conditions in finite element simulations. Moreover,\n");
02337 printf(
02338 " you will need the output .poly file if you plan to refine the output\n");
02339 printf(
02340 " mesh, and don't want segments to be missing in later triangulations.\n");
02341 printf("\n");
02342 printf(" .area files:\n");
02343 printf(" First line: <# of triangles>\n");
02344 printf(" Following lines: <triangle #> <maximum area>\n");
02345 printf("\n");
02346 printf(
02347 " An .area file associates with each triangle a maximum area that is used\n"
02348 );
02349 printf(
02350 " for mesh refinement. As with other file formats, every triangle must\n");
02351 printf(
02352 " be represented, and the triangles must be numbered consecutively. A\n");
02353 printf(
02354 " triangle may be left unconstrained by assigning it a negative maximum\n");
02355 printf(" area.\n\n");
02356 printf(" .edge files:\n");
02357 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
02358 printf(
02359 " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
02360 printf("\n");
02361 printf(
02362 " Endpoints are indices into the corresponding .node file. Triangle can\n"
02363 );
02364 printf(
02365 " produce .edge files (use the -e switch), but cannot read them. The\n");
02366 printf(
02367 " optional column of boundary markers is suppressed by the -B switch.\n");
02368 printf("\n");
02369 printf(
02370 " In Voronoi diagrams, one also finds a special kind of edge that is an\n");
02371 printf(
02372 " infinite ray with only one endpoint. For these edges, a different\n");
02373 printf(" format is used:\n\n");
02374 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
02375 printf(
02376 " The `direction' is a floating-point vector that indicates the direction\n"
02377 );
02378 printf(" of the infinite ray.\n\n");
02379 printf(" .neigh files:\n");
02380 printf(
02381 " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
02382 );
02383 printf(
02384 " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
02385 printf("\n");
02386 printf(
02387 " Neighbors are indices into the corresponding .ele file. An index of -1\n"
02388 );
02389 printf(
02390 " indicates no neighbor (because the triangle is on an exterior\n");
02391 printf(
02392 " boundary). The first neighbor of triangle i is opposite the first\n");
02393 printf(" corner of triangle i, and so on.\n\n");
02394 printf(
02395 " Triangle can produce .neigh files (use the -n switch), but cannot read\n"
02396 );
02397 printf(" them.\n\n");
02398 printf("Boundary Markers:\n\n");
02399 printf(
02400 " Boundary markers are tags used mainly to identify which output vertices\n");
02401 printf(
02402 " and edges are associated with which PSLG segment, and to identify which\n");
02403 printf(
02404 " vertices and edges occur on a boundary of the triangulation. A common\n");
02405 printf(
02406 " use is to determine where boundary conditions should be applied to a\n");
02407 printf(
02408 " finite element mesh. You can prevent boundary markers from being written\n"
02409 );
02410 printf(" into files produced by Triangle by using the -B switch.\n\n");
02411 printf(
02412 " The boundary marker associated with each segment in an output .poly file\n"
02413 );
02414 printf(" and each edge in an output .edge file is chosen as follows:\n");
02415 printf(
02416 " - If an output edge is part or all of a PSLG segment with a nonzero\n");
02417 printf(
02418 " boundary marker, then the edge is assigned the same marker.\n");
02419 printf(
02420 " - Otherwise, if the edge lies on a boundary of the triangulation\n");
02421 printf(
02422 " (even the boundary of a hole), then the edge is assigned the marker\n");
02423 printf(" one (1).\n");
02424 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
02425 printf(
02426 " The boundary marker associated with each vertex in an output .node file\n");
02427 printf(" is chosen as follows:\n");
02428 printf(
02429 " - If a vertex is assigned a nonzero boundary marker in the input file,\n"
02430 );
02431 printf(
02432 " then it is assigned the same marker in the output .node file.\n");
02433 printf(
02434 " - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
02435 printf(
02436 " endpoint of the segment) with a nonzero boundary marker, then the\n");
02437 printf(
02438 " vertex is assigned the same marker. If the vertex lies on several\n");
02439 printf(" such segments, one of the markers is chosen arbitrarily.\n");
02440 printf(
02441 " - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
02442 printf(" then the vertex is assigned the marker one (1).\n");
02443 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
02444 printf("\n");
02445 printf(
02446 " If you want Triangle to determine for you which vertices and edges are on\n"
02447 );
02448 printf(
02449 " the boundary, assign them the boundary marker zero (or use no markers at\n"
02450 );
02451 printf(
02452 " all) in your input files. In the output files, all boundary vertices,\n");
02453 printf(" edges, and segments will be assigned the value one.\n\n");
02454 printf("Triangulation Iteration Numbers:\n\n");
02455 printf(
02456 " Because Triangle can read and refine its own triangulations, input\n");
02457 printf(
02458 " and output files have iteration numbers. For instance, Triangle might\n");
02459 printf(
02460 " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
02461 printf(
02462 " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
02463 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
02464 printf(
02465 " their iteration number is zero; hence, Triangle might read the file\n");
02466 printf(
02467 " points.node, triangulate it, and produce the files points.1.node and\n");
02468 printf(" points.1.ele.\n\n");
02469 printf(
02470 " Iteration numbers allow you to create a sequence of successively finer\n");
02471 printf(
02472 " meshes suitable for multigrid methods. They also allow you to produce a\n"
02473 );
02474 printf(
02475 " sequence of meshes using error estimate-driven mesh refinement.\n");
02476 printf("\n");
02477 printf(
02478 " If you're not using refinement or quality meshing, and you don't like\n");
02479 printf(
02480 " iteration numbers, use the -I switch to disable them. This switch also\n");
02481 printf(
02482 " disables output of .node and .poly files to prevent your input files from\n"
02483 );
02484 printf(
02485 " being overwritten. (If the input is a .poly file that contains its own\n");
02486 printf(
02487 " points, a .node file is written. This can be quite convenient for\n");
02488 printf(" computing CDTs or quality meshes.)\n\n");
02489 printf("Examples of How to Use Triangle:\n\n");
02490 printf(
02491 " `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
02492 );
02493 printf(
02494 " triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
02495 printf(
02496 " to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
02497 printf(
02498 " instead. (No additional .node file is needed, so none is written.)\n");
02499 printf("\n");
02500 printf(
02501 " `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
02502 printf(
02503 " object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
02504 );
02505 printf(
02506 " its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
02507 );
02508 printf(
02509 " The segments are copied to object.2.poly, and all edges are written to\n");
02510 printf(" object.2.edge.\n\n");
02511 printf(
02512 " `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
02513 );
02514 printf(
02515 " object.node), generates a mesh whose angles are all between 31.5 and 117\n"
02516 );
02517 printf(
02518 " degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
02519 );
02520 printf(
02521 " mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
02522 printf(" into multiple subsegments; these are written to object.1.poly.\n");
02523 printf("\n");
02524 printf(
02525 " Here is a sample file `box.poly' describing a square with a square hole:\n"
02526 );
02527 printf("\n");
02528 printf(
02529 " # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
02530 );
02531 printf(" 8 2 0 1\n");
02532 printf(" # Outer box has these vertices:\n");
02533 printf(" 1 0 0 0\n");
02534 printf(" 2 0 3 0\n");
02535 printf(" 3 3 0 0\n");
02536 printf(" 4 3 3 33 # A special marker for this vertex.\n");
02537 printf(" # Inner square has these vertices:\n");
02538 printf(" 5 1 1 0\n");
02539 printf(" 6 1 2 0\n");
02540 printf(" 7 2 1 0\n");
02541 printf(" 8 2 2 0\n");
02542 printf(" # Five segments with boundary markers.\n");
02543 printf(" 5 1\n");
02544 printf(" 1 1 2 5 # Left side of outer box.\n");
02545 printf(" # Square hole has these segments:\n");
02546 printf(" 2 5 7 0\n");
02547 printf(" 3 7 8 0\n");
02548 printf(" 4 8 6 10\n");
02549 printf(" 5 6 5 0\n");
02550 printf(" # One hole in the middle of the inner square.\n");
02551 printf(" 1\n");
02552 printf(" 1 1.5 1.5\n");
02553 printf("\n");
02554 printf(
02555 " Note that some segments are missing from the outer square, so you must\n");
02556 printf(
02557 " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
02558 );
02559 printf(
02560 " file `box.1.node', with twelve vertices. The last four vertices were\n");
02561 printf(
02562 " added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
02563 printf(
02564 " from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
02565 printf(
02566 " other vertices but 4 have been marked to indicate that they lie on a\n");
02567 printf(" boundary.\n\n");
02568 printf(" 12 2 0 1\n");
02569 printf(" 1 0 0 5\n");
02570 printf(" 2 0 3 5\n");
02571 printf(" 3 3 0 1\n");
02572 printf(" 4 3 3 33\n");
02573 printf(" 5 1 1 1\n");
02574 printf(" 6 1 2 10\n");
02575 printf(" 7 2 1 1\n");
02576 printf(" 8 2 2 10\n");
02577 printf(" 9 0 1.5 5\n");
02578 printf(" 10 1.5 0 1\n");
02579 printf(" 11 3 1.5 1\n");
02580 printf(" 12 1.5 3 1\n");
02581 printf(" # Generated by triangle -pqc box.poly\n");
02582 printf("\n");
02583 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
02584 printf("\n");
02585 printf(" 12 3 0\n");
02586 printf(" 1 5 6 9\n");
02587 printf(" 2 10 3 7\n");
02588 printf(" 3 6 8 12\n");
02589 printf(" 4 9 1 5\n");
02590 printf(" 5 6 2 9\n");
02591 printf(" 6 7 3 11\n");
02592 printf(" 7 11 4 8\n");
02593 printf(" 8 7 5 10\n");
02594 printf(" 9 12 2 6\n");
02595 printf(" 10 8 7 11\n");
02596 printf(" 11 5 1 10\n");
02597 printf(" 12 8 4 12\n");
02598 printf(" # Generated by triangle -pqc box.poly\n\n");
02599 printf(
02600 " Here is the output file `box.1.poly'. Note that segments have been added\n"
02601 );
02602 printf(
02603 " to represent the convex hull, and some segments have been subdivided by\n");
02604 printf(
02605 " newly added vertices. Note also that <# of vertices> is set to zero to\n");
02606 printf(" indicate that the vertices should be read from the .node file.\n");
02607 printf("\n");
02608 printf(" 0 2 0 1\n");
02609 printf(" 12 1\n");
02610 printf(" 1 1 9 5\n");
02611 printf(" 2 5 7 1\n");
02612 printf(" 3 8 7 1\n");
02613 printf(" 4 6 8 10\n");
02614 printf(" 5 5 6 1\n");
02615 printf(" 6 3 10 1\n");
02616 printf(" 7 4 11 1\n");
02617 printf(" 8 2 12 1\n");
02618 printf(" 9 9 2 5\n");
02619 printf(" 10 10 1 1\n");
02620 printf(" 11 11 3 1\n");
02621 printf(" 12 12 4 1\n");
02622 printf(" 1\n");
02623 printf(" 1 1.5 1.5\n");
02624 printf(" # Generated by triangle -pqc box.poly\n");
02625 printf("\n");
02626 printf("Refinement and Area Constraints:\n");
02627 printf("\n");
02628 printf(
02629 " The -r switch causes a mesh (.node and .ele files) to be read and\n");
02630 printf(
02631 " refined. If the -p switch is also used, a .poly file is read and used to\n"
02632 );
02633 printf(
02634 " specify edges that are constrained and cannot be eliminated (although\n");
02635 printf(
02636 " they can be subdivided into smaller edges) by the refinement process.\n");
02637 printf("\n");
02638 printf(
02639 " When you refine a mesh, you generally want to impose tighter constraints.\n"
02640 );
02641 printf(
02642 " One way to accomplish this is to use -q with a larger angle, or -a\n");
02643 printf(
02644 " followed by a smaller area than you used to generate the mesh you are\n");
02645 printf(
02646 " refining. Another way to do this is to create an .area file, which\n");
02647 printf(
02648 " specifies a maximum area for each triangle, and use the -a switch\n");
02649 printf(
02650 " (without a number following). Each triangle's area constraint is applied\n"
02651 );
02652 printf(
02653 " to that triangle. Area constraints tend to diffuse as the mesh is\n");
02654 printf(
02655 " refined, so if there are large variations in area constraint between\n");
02656 printf(
02657 " adjacent triangles, you may not get the results you want. In that case,\n"
02658 );
02659 printf(
02660 " consider instead using the -u switch and writing a C procedure that\n");
02661 printf(" determines which triangles are too large.\n\n");
02662 printf(
02663 " If you are refining a mesh composed of linear (three-node) elements, the\n"
02664 );
02665 printf(
02666 " output mesh contains all the nodes present in the input mesh, in the same\n"
02667 );
02668 printf(
02669 " order, with new nodes added at the end of the .node file. However, the\n");
02670 printf(
02671 " refinement is not hierarchical: there is no guarantee that each output\n");
02672 printf(
02673 " element is contained in a single input element. Often, an output element\n"
02674 );
02675 printf(
02676 " can overlap two or three input elements, and some input edges are not\n");
02677 printf(
02678 " present in the output mesh. Hence, a sequence of refined meshes forms a\n"
02679 );
02680 printf(
02681 " hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
02682 printf(
02683 " mesh of higher-order elements, the hierarchical property applies only to\n"
02684 );
02685 printf(
02686 " the nodes at the corners of an element; the midpoint nodes on each edge\n");
02687 printf(" are discarded before the mesh is refined.\n\n");
02688 printf(
02689 " Maximum area constraints in .poly files operate differently from those in\n"
02690 );
02691 printf(
02692 " .area files. A maximum area in a .poly file applies to the whole\n");
02693 printf(
02694 " (segment-bounded) region in which a point falls, whereas a maximum area\n");
02695 printf(
02696 " in an .area file applies to only one triangle. Area constraints in .poly\n"
02697 );
02698 printf(
02699 " files are used only when a mesh is first generated, whereas area\n");
02700 printf(
02701 " constraints in .area files are used only to refine an existing mesh, and\n"
02702 );
02703 printf(
02704 " are typically based on a posteriori error estimates resulting from a\n");
02705 printf(" finite element simulation on that mesh.\n\n");
02706 printf(
02707 " `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
02708 printf(
02709 " refines the triangulation to enforce a 25 degree minimum angle, and then\n"
02710 );
02711 printf(
02712 " writes the refined triangulation to object.2.node and object.2.ele.\n");
02713 printf("\n");
02714 printf(
02715 " `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
02716 );
02717 printf(
02718 " After reconstructing the mesh and its subsegments, Triangle refines the\n");
02719 printf(
02720 " mesh so that no triangle has area greater than 6.2, and furthermore the\n");
02721 printf(
02722 " triangles satisfy the maximum area constraints in z.3.area. No angle\n");
02723 printf(
02724 " bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
02725 );
02726 printf(" z.4.poly.\n\n");
02727 printf(
02728 " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
02729 printf(
02730 " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
02731 printf(" suitable for multigrid.\n\n");
02732 printf("Convex Hulls and Mesh Boundaries:\n\n");
02733 printf(
02734 " If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
02735 printf(
02736 " hull as a by-product in the output .poly file if you use the -c switch.\n");
02737 printf(
02738 " There are faster algorithms for finding a two-dimensional convex hull\n");
02739 printf(" than triangulation, of course, but this one comes for free.\n\n");
02740 printf(
02741 " If the input is an unconstrained mesh (you are using the -r switch but\n");
02742 printf(
02743 " not the -p switch), Triangle produces a list of its boundary edges\n");
02744 printf(
02745 " (including hole boundaries) as a by-product when you use the -c switch.\n");
02746 printf(
02747 " If you also use the -p switch, the output .poly file contains all the\n");
02748 printf(" segments from the input .poly file as well.\n\n");
02749 printf("Voronoi Diagrams:\n\n");
02750 printf(
02751 " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
02752 printf(
02753 " .v.edge. For example, `triangle -v points' reads points.node, produces\n");
02754 printf(
02755 " its Delaunay triangulation in points.1.node and points.1.ele, and\n");
02756 printf(
02757 " produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
02758 );
02759 printf(
02760 " .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
02761 printf(
02762 " file contains a list of all Voronoi edges, some of which may be infinite\n"
02763 );
02764 printf(
02765 " rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
02766 printf(" vertices through Triangle, if so desired.)\n\n");
02767 printf(
02768 " This implementation does not use exact arithmetic to compute the Voronoi\n"
02769 );
02770 printf(
02771 " vertices, and does not check whether neighboring vertices are identical.\n"
02772 );
02773 printf(
02774 " Be forewarned that if the Delaunay triangulation is degenerate or\n");
02775 printf(
02776 " near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
02777 printf(" crossing edges.\n\n");
02778 printf(
02779 " The result is a valid Voronoi diagram only if Triangle's output is a true\n"
02780 );
02781 printf(
02782 " Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
02783 printf(
02784 " may contain crossing edges and other pathology) if the output is a CDT or\n"
02785 );
02786 printf(
02787 " CCDT, or if it has holes or concavities. If the triangulated domain is\n");
02788 printf(
02789 " convex and has no holes, you can use -D switch to force Triangle to\n");
02790 printf(
02791 " construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
02792 printf(" Voronoi diagram will be valid.\n\n");
02793 printf("Mesh Topology:\n\n");
02794 printf(
02795 " You may wish to know which triangles are adjacent to a certain Delaunay\n");
02796 printf(
02797 " edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
02798 printf(
02799 " Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
02800 printf(
02801 " each other. All of this information can be found by cross-referencing\n");
02802 printf(
02803 " output files with the recollection that the Delaunay triangulation and\n");
02804 printf(" the Voronoi diagram are planar duals.\n\n");
02805 printf(
02806 " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
02807 printf(
02808 " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
02809 printf(
02810 " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
02811 printf(
02812 " vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
02813 printf(" of vertex k of the corresponding .node file.\n\n");
02814 printf(
02815 " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
02816 printf(
02817 " vertices of the corresponding Voronoi edge. If the endpoints of a\n");
02818 printf(
02819 " Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
02820 );
02821 printf(
02822 " and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
02823 );
02824 printf(
02825 " respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
02826 );
02827 printf(
02828 " at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
02829 );
02830 printf(
02831 " a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
02832 );
02833 printf(
02834 " adjoin the right and left sides of the corresponding Voronoi edge,\n");
02835 printf(
02836 " respectively. To find which Voronoi cells are adjacent to each other,\n");
02837 printf(" just read the list of Delaunay edges.\n\n");
02838 printf(
02839 " Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
02840 );
02841 printf(
02842 " but you can reconstructed it straightforwardly. For instance, to find\n");
02843 printf(
02844 " all the edges of Voronoi cell 1, search the output .edge file for every\n");
02845 printf(
02846 " edge that has input vertex 1 as an endpoint. The corresponding dual\n");
02847 printf(
02848 " edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
02849 printf("\n");
02850 printf(
02851 " For each Voronoi vertex, the .neigh file gives a list of the three\n");
02852 printf(
02853 " Voronoi vertices attached to it. You might find this more convenient\n");
02854 printf(" than the .v.edge file.\n\n");
02855 printf("Quadratic Elements:\n\n");
02856 printf(
02857 " Triangle generates meshes with subparametric quadratic elements if the\n");
02858 printf(
02859 " -o2 switch is specified. Quadratic elements have six nodes per element,\n"
02860 );
02861 printf(
02862 " rather than three. `Subparametric' means that the edges of the triangles\n"
02863 );
02864 printf(
02865 " are always straight, so that subparametric quadratic elements are\n");
02866 printf(
02867 " geometrically identical to linear elements, even though they can be used\n"
02868 );
02869 printf(
02870 " with quadratic interpolating functions. The three extra nodes of an\n");
02871 printf(
02872 " element fall at the midpoints of the three edges, with the fourth, fifth,\n"
02873 );
02874 printf(
02875 " and sixth nodes appearing opposite the first, second, and third corners\n");
02876 printf(" respectively.\n\n");
02877 printf("Domains with Small Angles:\n\n");
02878 printf(
02879 " If two input segments adjoin each other at a small angle, clearly the -q\n"
02880 );
02881 printf(
02882 " switch cannot remove the small angle. Moreover, Triangle may have no\n");
02883 printf(
02884 " choice but to generate additional triangles whose smallest angles are\n");
02885 printf(
02886 " smaller than the specified bound. However, these triangles only appear\n");
02887 printf(
02888 " between input segments separated by small angles. Moreover, if you\n");
02889 printf(
02890 " request a minimum angle of theta degrees, Triangle will generally produce\n"
02891 );
02892 printf(
02893 " no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
02894 );
02895 printf(" the minimum angle.\n\n");
02896 printf("Statistics:\n\n");
02897 printf(
02898 " After generating a mesh, Triangle prints a count of entities in the\n");
02899 printf(
02900 " output mesh, including the number of vertices, triangles, edges, exterior\n"
02901 );
02902 printf(
02903 " boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
02904 printf(
02905 " including hole boundaries), interior boundary edges (i.e. subsegments of\n"
02906 );
02907 printf(
02908 " input segments not on the boundary), and total subsegments. If you've\n");
02909 printf(
02910 " forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
02911 );
02912 printf(
02913 " with the -rNEP switches to read the mesh and print the statistics without\n"
02914 );
02915 printf(
02916 " writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
02917 printf("\n");
02918 printf(
02919 " The -V switch produces extended statistics, including a rough estimate\n");
02920 printf(
02921 " of memory use, the number of calls to geometric predicates, and\n");
02922 printf(
02923 " histograms of the angles and the aspect ratios of the triangles in the\n");
02924 printf(" mesh.\n\n");
02925 printf("Exact Arithmetic:\n\n");
02926 printf(
02927 " Triangle uses adaptive exact arithmetic to perform what computational\n");
02928 printf(
02929 " geometers call the `orientation' and `incircle' tests. If the floating-\n"
02930 );
02931 printf(
02932 " point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
02933 printf(
02934 " most workstations do), and does not use extended precision internal\n");
02935 printf(
02936 " floating-point registers, then your output is guaranteed to be an\n");
02937 printf(
02938 " absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
02939 );
02940 printf(
02941 " error notwithstanding. The word `adaptive' implies that these arithmetic\n"
02942 );
02943 printf(
02944 " routines compute the result only to the precision necessary to guarantee\n"
02945 );
02946 printf(
02947 " correctness, so they are usually nearly as fast as their approximate\n");
02948 printf(" counterparts.\n\n");
02949 printf(
02950 " May CPUs, including Intel x86 processors, have extended precision\n");
02951 printf(
02952 " floating-point registers. These must be reconfigured so their precision\n"
02953 );
02954 printf(
02955 " is reduced to memory precision. Triangle does this if it is compiled\n");
02956 printf(" correctly. See the makefile for details.\n\n");
02957 printf(
02958 " The exact tests can be disabled with the -X switch. On most inputs, this\n"
02959 );
02960 printf(
02961 " switch reduces the computation time by about eight percent--it's not\n");
02962 printf(
02963 " worth the risk. There are rare difficult inputs (having many collinear\n");
02964 printf(
02965 " and cocircular vertices), however, for which the difference in speed\n");
02966 printf(
02967 " could be a factor of two. Be forewarned that these are precisely the\n");
02968 printf(
02969 " inputs most likely to cause errors if you use the -X switch. Hence, the\n"
02970 );
02971 printf(" -X switch is not recommended.\n\n");
02972 printf(
02973 " Unfortunately, the exact tests don't solve every numerical problem.\n");
02974 printf(
02975 " Exact arithmetic is not used to compute the positions of new vertices,\n");
02976 printf(
02977 " because the bit complexity of vertex coordinates would grow without\n");
02978 printf(
02979 " bound. Hence, segment intersections aren't computed exactly; in very\n");
02980 printf(
02981 " unusual cases, roundoff error in computing an intersection point might\n");
02982 printf(
02983 " actually lead to an inverted triangle and an invalid triangulation.\n");
02984 printf(
02985 " (This is one reason to specify your own intersection points in your .poly\n"
02986 );
02987 printf(
02988 " files.) Similarly, exact arithmetic is not used to compute the vertices\n"
02989 );
02990 printf(" of the Voronoi diagram.\n\n");
02991 printf(
02992 " Another pair of problems not solved by the exact arithmetic routines is\n");
02993 printf(
02994 " underflow and overflow. If Triangle is compiled for double precision\n");
02995 printf(
02996 " arithmetic, I believe that Triangle's geometric predicates work correctly\n"
02997 );
02998 printf(
02999 " if the exponent of every input coordinate falls in the range [-148, 201].\n"
03000 );
03001 printf(
03002 " Underflow can silently prevent the orientation and incircle tests from\n");
03003 printf(
03004 " being performed exactly, while overflow typically causes a floating\n");
03005 printf(" exception.\n\n");
03006 printf("Calling Triangle from Another Program:\n\n");
03007 printf(" Read the file triangle.h for details.\n\n");
03008 printf("Troubleshooting:\n\n");
03009 printf(" Please read this section before mailing me bugs.\n\n");
03010 printf(" `My output mesh has no triangles!'\n\n");
03011 printf(
03012 " If you're using a PSLG, you've probably failed to specify a proper set\n"
03013 );
03014 printf(
03015 " of bounding segments, or forgotten to use the -c switch. Or you may\n");
03016 printf(
03017 " have placed a hole badly, thereby eating all your triangles. To test\n");
03018 printf(" these possibilities, try again with the -c and -O switches.\n");
03019 printf(
03020 " Alternatively, all your input vertices may be collinear, in which case\n"
03021 );
03022 printf(" you can hardly expect to triangulate them.\n\n");
03023 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
03024 printf(
03025 " Bad things can happen when triangles get so small that the distance\n");
03026 printf(
03027 " between their vertices isn't much larger than the precision of your\n");
03028 printf(
03029 " machine's arithmetic. If you've compiled Triangle for single-precision\n"
03030 );
03031 printf(
03032 " arithmetic, you might do better by recompiling it for double-precision.\n"
03033 );
03034 printf(
03035 " Then again, you might just have to settle for more lenient constraints\n"
03036 );
03037 printf(
03038 " on the minimum angle and the maximum area than you had planned.\n");
03039 printf("\n");
03040 printf(
03041 " You can minimize precision problems by ensuring that the origin lies\n");
03042 printf(
03043 " inside your vertex set, or even inside the densest part of your\n");
03044 printf(
03045 " mesh. If you're triangulating an object whose x-coordinates all fall\n");
03046 printf(
03047 " between 6247133 and 6247134, you're not leaving much floating-point\n");
03048 printf(" precision for Triangle to work with.\n\n");
03049 printf(
03050 " Precision problems can occur covertly if the input PSLG contains two\n");
03051 printf(
03052 " segments that meet (or intersect) at an extremely small angle, or if\n");
03053 printf(
03054 " such an angle is introduced by the -c switch. If you don't realize\n");
03055 printf(
03056 " that a tiny angle is being formed, you might never discover why\n");
03057 printf(
03058 " Triangle is crashing. To check for this possibility, use the -S switch\n"
03059 );
03060 printf(
03061 " (with an appropriate limit on the number of Steiner points, found by\n");
03062 printf(
03063 " trial-and-error) to stop Triangle early, and view the output .poly file\n"
03064 );
03065 printf(
03066 " with Show Me (described below). Look carefully for regions where dense\n"
03067 );
03068 printf(
03069 " clusters of vertices are forming and for small angles between segments.\n"
03070 );
03071 printf(
03072 " Zoom in closely, as such segments might look like a single segment from\n"
03073 );
03074 printf(" a distance.\n\n");
03075 printf(
03076 " If some of the input values are too large, Triangle may suffer a\n");
03077 printf(
03078 " floating exception due to overflow when attempting to perform an\n");
03079 printf(
03080 " orientation or incircle test. (Read the section on exact arithmetic\n");
03081 printf(
03082 " above.) Again, I recommend compiling Triangle for double (rather\n");
03083 printf(" than single) precision arithmetic.\n\n");
03084 printf(
03085 " Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
03086 printf(
03087 " -u) with an input that is not segment-bounded--that is, if your input\n");
03088 printf(
03089 " is a vertex set, or you're using the -c switch. If the convex hull of\n"
03090 );
03091 printf(
03092 " your input vertices has collinear vertices on its boundary, an input\n");
03093 printf(
03094 " vertex that you think lies on the convex hull might actually lie just\n");
03095 printf(
03096 " inside the convex hull. If so, the vertex and the nearby convex hull\n");
03097 printf(
03098 " edge form an extremely thin triangle. When Triangle tries to refine\n");
03099 printf(
03100 " the mesh to enforce angle and area constraints, Triangle might generate\n"
03101 );
03102 printf(
03103 " extremely tiny triangles, or it might fail because of insufficient\n");
03104 printf(" floating-point precision.\n\n");
03105 printf(
03106 " `The numbering of the output vertices doesn't match the input vertices.'\n"
03107 );
03108 printf("\n");
03109 printf(
03110 " You may have had duplicate input vertices, or you may have eaten some\n");
03111 printf(
03112 " of your input vertices with a hole, or by placing them outside the area\n"
03113 );
03114 printf(
03115 " enclosed by segments. In any case, you can solve the problem by not\n");
03116 printf(" using the -j switch.\n\n");
03117 printf(
03118 " `Triangle executes without incident, but when I look at the resulting\n");
03119 printf(
03120 " mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
03121 printf("\n");
03122 printf(
03123 " If you select the -X switch, Triangle occasionally makes mistakes due\n");
03124 printf(
03125 " to floating-point roundoff error. Although these errors are rare,\n");
03126 printf(
03127 " don't use the -X switch. If you still have problems, please report the\n"
03128 );
03129 printf(" bug.\n\n");
03130 printf(
03131 " `Triangle executes without incident, but when I look at the resulting\n");
03132 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
03133 printf(" inconsistencies.'\n");
03134 printf("\n");
03135 printf(
03136 " If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
03137 );
03138 printf(
03139 " diagram if the domain you are triangulating is convex and free of\n");
03140 printf(
03141 " holes, and you use the -D switch to construct a conforming Delaunay\n");
03142 printf(" triangulation (instead of a CDT or CCDT).\n\n");
03143 printf(
03144 " Strange things can happen if you've taken liberties with your PSLG. Do\n");
03145 printf(
03146 " you have a vertex lying in the middle of a segment? Triangle sometimes\n");
03147 printf(
03148 " copes poorly with that sort of thing. Do you want to lay out a collinear\n"
03149 );
03150 printf(
03151 " row of evenly spaced, segment-connected vertices? Have you simply\n");
03152 printf(
03153 " defined one long segment connecting the leftmost vertex to the rightmost\n"
03154 );
03155 printf(
03156 " vertex, and a bunch of vertices lying along it? This method occasionally\n"
03157 );
03158 printf(
03159 " works, especially with horizontal and vertical lines, but often it\n");
03160 printf(
03161 " doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
03162 );
03163 printf(" separate segment. If you don't like it, tough.\n\n");
03164 printf(
03165 " Furthermore, if you have segments that intersect other than at their\n");
03166 printf(
03167 " endpoints, try not to let the intersections fall extremely close to PSLG\n"
03168 );
03169 printf(" vertices or each other.\n\n");
03170 printf(
03171 " If you have problems refining a triangulation not produced by Triangle:\n");
03172 printf(
03173 " Are you sure the triangulation is geometrically valid? Is it formatted\n");
03174 printf(
03175 " correctly for Triangle? Are the triangles all listed so the first three\n"
03176 );
03177 printf(
03178 " vertices are their corners in counterclockwise order? Are all of the\n");
03179 printf(
03180 " triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
03181 );
03182 printf(" assumes that it starts with a CDT.\n\n");
03183 printf("Show Me:\n\n");
03184 printf(
03185 " Triangle comes with a separate program named `Show Me', whose primary\n");
03186 printf(
03187 " purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
03188 );
03189 printf(
03190 " purpose is to check the validity of your input files, and do so more\n");
03191 printf(
03192 " thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
03193 printf(
03194 " you have the X Windows system. Sorry, Microsoft Windows users.\n");
03195 printf("\n");
03196 printf("Triangle on the Web:\n");
03197 printf("\n");
03198 printf(" To see an illustrated version of these instructions, check out\n");
03199 printf("\n");
03200 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
03201 printf("\n");
03202 printf("A Brief Plea:\n");
03203 printf("\n");
03204 printf(
03205 " If you use Triangle, and especially if you use it to accomplish real\n");
03206 printf(
03207 " work, I would like very much to hear from you. A short letter or email\n");
03208 printf(
03209 " (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
03210 );
03211 printf(
03212 " to me. The more people I know are using this program, the more easily I\n"
03213 );
03214 printf(
03215 " can justify spending time on improvements, which in turn will benefit\n");
03216 printf(
03217 " you. Also, I can put you on a list to receive email whenever a new\n");
03218 printf(" version of Triangle is available.\n\n");
03219 printf(
03220 " If you use a mesh generated by Triangle in a publication, please include\n"
03221 );
03222 printf(
03223 " an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
03224 );
03225 printf(
03226 " If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
03227 printf(
03228 " ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
03229 printf(
03230 " Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
03231 printf(
03232 " Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
03233 printf(
03234 " Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
03235 printf(
03236 " Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
03237 );
03238 printf(" Geometry.)'\n\n");
03239 printf("Research credit:\n\n");
03240 printf(
03241 " Of course, I can take credit for only a fraction of the ideas that made\n");
03242 printf(
03243 " this mesh generator possible. Triangle owes its existence to the efforts\n"
03244 );
03245 printf(
03246 " of many fine computational geometers and other researchers, including\n");
03247 printf(
03248 " Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
03249 );
03250 printf(
03251 " Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
03252 printf(
03253 " Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
03254 printf(
03255 " Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
03256 printf(
03257 " Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
03258 );
03259 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
03260 printf(
03261 " Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
03262 printf(" source code for references.\n\n");
03263 triexit(0);
03264 }
03265
03266 #endif
03267
03268
03269
03270
03271
03272
03273
03274 void internalerror()
03275 {
03276 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
03277 printf(" Include the message above, your input data set, and the exact\n");
03278 printf(" command line you used to run Triangle.\n");
03279 triexit(1);
03280 }
03281
03282
03283
03284
03285
03286
03287
03288
03289 #ifdef ANSI_DECLARATORS
03290 void parsecommandline(int argc, char **argv, struct behavior *b)
03291 #else
03292 void parsecommandline(argc, argv, b)
03293 int argc;
03294 char **argv;
03295 struct behavior *b;
03296 #endif
03297
03298 {
03299 #ifdef TRILIBRARY
03300 #define STARTINDEX 0
03301 #else
03302 #define STARTINDEX 1
03303 int increment;
03304 int meshnumber;
03305 #endif
03306 int i, j, k;
03307 char workstring[FILENAMESIZE];
03308
03309 b->poly = b->refine = b->quality = 0;
03310 b->vararea = b->fixedarea = b->usertest = 0;
03311 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
03312 b->firstnumber = 1;
03313 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
03314 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
03315 b->noiterationnum = 0;
03316 b->noholes = b->noexact = 0;
03317 b->incremental = b->sweepline = 0;
03318 b->dwyer = 1;
03319 b->splitseg = 0;
03320 b->docheck = 0;
03321 b->nobisect = 0;
03322 b->conformdel = 0;
03323 b->steiner = -1;
03324 b->order = 1;
03325 b->minangle = 0.0;
03326 b->maxarea = -1.0;
03327 b->quiet = b->verbose = 0;
03328 #ifndef TRILIBRARY
03329 b->innodefilename[0] = '\0';
03330 #endif
03331
03332 for (i = STARTINDEX; i < argc; i++) {
03333 #ifndef TRILIBRARY
03334 if (argv[i][0] == '-') {
03335 #endif
03336 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
03337 if (argv[i][j] == 'p') {
03338 b->poly = 1;
03339 }
03340 #ifndef CDT_ONLY
03341 if (argv[i][j] == 'r') {
03342 b->refine = 1;
03343 }
03344 if (argv[i][j] == 'q') {
03345 b->quality = 1;
03346 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03347 (argv[i][j + 1] == '.')) {
03348 k = 0;
03349 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03350 (argv[i][j + 1] == '.')) {
03351 j++;
03352 workstring[k] = argv[i][j];
03353 k++;
03354 }
03355 workstring[k] = '\0';
03356 b->minangle = (REAL) strtod(workstring, (char **) NULL);
03357 } else {
03358 b->minangle = 20.0;
03359 }
03360 }
03361 if (argv[i][j] == 'a') {
03362 b->quality = 1;
03363 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03364 (argv[i][j + 1] == '.')) {
03365 b->fixedarea = 1;
03366 k = 0;
03367 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03368 (argv[i][j + 1] == '.')) {
03369 j++;
03370 workstring[k] = argv[i][j];
03371 k++;
03372 }
03373 workstring[k] = '\0';
03374 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
03375 if (b->maxarea <= 0.0) {
03376 printf("Error: Maximum area must be greater than zero.\n");
03377 triexit(1);
03378 }
03379 } else {
03380 b->vararea = 1;
03381 }
03382 }
03383 if (argv[i][j] == 'u') {
03384 b->quality = 1;
03385 b->usertest = 1;
03386 }
03387 #endif
03388 if (argv[i][j] == 'A') {
03389 b->regionattrib = 1;
03390 }
03391 if (argv[i][j] == 'c') {
03392 b->convex = 1;
03393 }
03394 if (argv[i][j] == 'w') {
03395 b->weighted = 1;
03396 }
03397 if (argv[i][j] == 'W') {
03398 b->weighted = 2;
03399 }
03400 if (argv[i][j] == 'j') {
03401 b->jettison = 1;
03402 }
03403 if (argv[i][j] == 'z') {
03404 b->firstnumber = 0;
03405 }
03406 if (argv[i][j] == 'e') {
03407 b->edgesout = 1;
03408 }
03409 if (argv[i][j] == 'v') {
03410 b->voronoi = 1;
03411 }
03412 if (argv[i][j] == 'n') {
03413 b->neighbors = 1;
03414 }
03415 if (argv[i][j] == 'g') {
03416 b->geomview = 1;
03417 }
03418 if (argv[i][j] == 'B') {
03419 b->nobound = 1;
03420 }
03421 if (argv[i][j] == 'P') {
03422 b->nopolywritten = 1;
03423 }
03424 if (argv[i][j] == 'N') {
03425 b->nonodewritten = 1;
03426 }
03427 if (argv[i][j] == 'E') {
03428 b->noelewritten = 1;
03429 }
03430 #ifndef TRILIBRARY
03431 if (argv[i][j] == 'I') {
03432 b->noiterationnum = 1;
03433 }
03434 #endif
03435 if (argv[i][j] == 'O') {
03436 b->noholes = 1;
03437 }
03438 if (argv[i][j] == 'X') {
03439 b->noexact = 1;
03440 }
03441 if (argv[i][j] == 'o') {
03442 if (argv[i][j + 1] == '2') {
03443 j++;
03444 b->order = 2;
03445 }
03446 }
03447 #ifndef CDT_ONLY
03448 if (argv[i][j] == 'Y') {
03449 b->nobisect++;
03450 }
03451 if (argv[i][j] == 'S') {
03452 b->steiner = 0;
03453 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
03454 j++;
03455 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
03456 }
03457 }
03458 #endif
03459 #ifndef REDUCED
03460 if (argv[i][j] == 'i') {
03461 b->incremental = 1;
03462 }
03463 if (argv[i][j] == 'F') {
03464 b->sweepline = 1;
03465 }
03466 #endif
03467 if (argv[i][j] == 'l') {
03468 b->dwyer = 0;
03469 }
03470 #ifndef REDUCED
03471 #ifndef CDT_ONLY
03472 if (argv[i][j] == 's') {
03473 b->splitseg = 1;
03474 }
03475 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
03476 b->quality = 1;
03477 b->conformdel = 1;
03478 }
03479 #endif
03480 if (argv[i][j] == 'C') {
03481 b->docheck = 1;
03482 }
03483 #endif
03484 if (argv[i][j] == 'Q') {
03485 b->quiet = 1;
03486 }
03487 if (argv[i][j] == 'V') {
03488 b->verbose++;
03489 }
03490 #ifndef TRILIBRARY
03491 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03492 (argv[i][j] == '?')) {
03493 info();
03494 }
03495 #endif
03496 }
03497 #ifndef TRILIBRARY
03498 } else {
03499 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
03500 b->innodefilename[FILENAMESIZE - 1] = '\0';
03501 }
03502 #endif
03503 }
03504 #ifndef TRILIBRARY
03505 if (b->innodefilename[0] == '\0') {
03506 syntax();
03507 }
03508 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
03509 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03510 }
03511 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
03512 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03513 b->poly = 1;
03514 }
03515 #ifndef CDT_ONLY
03516 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
03517 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
03518 b->refine = 1;
03519 }
03520 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
03521 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03522 b->refine = 1;
03523 b->quality = 1;
03524 b->vararea = 1;
03525 }
03526 #endif
03527 #endif
03528 b->usesegments = b->poly || b->refine || b->quality || b->convex;
03529 b->goodangle = cos(b->minangle * PI / 180.0);
03530 if (b->goodangle == 1.0) {
03531 b->offconstant = 0.0;
03532 } else {
03533 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
03534 }
03535 b->goodangle *= b->goodangle;
03536 if (b->refine && b->noiterationnum) {
03537 printf(
03538 "Error: You cannot use the -I switch when refining a triangulation.\n");
03539 triexit(1);
03540 }
03541
03542
03543 if (!b->refine && !b->poly) {
03544 b->vararea = 0;
03545 }
03546
03547
03548 if (b->refine || !b->poly) {
03549 b->regionattrib = 0;
03550 }
03551
03552
03553 if (b->weighted && (b->poly || b->quality)) {
03554 b->weighted = 0;
03555 if (!b->quiet) {
03556 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
03557 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
03558 );
03559 }
03560 }
03561 if (b->jettison && b->nonodewritten && !b->quiet) {
03562 printf("Warning: -j and -N switches are somewhat incompatible.\n");
03563 printf(" If any vertices are jettisoned, you will need the output\n");
03564 printf(" .node file to reconstruct the new node indices.");
03565 }
03566
03567 #ifndef TRILIBRARY
03568 strcpy(b->inpolyfilename, b->innodefilename);
03569 strcpy(b->inelefilename, b->innodefilename);
03570 strcpy(b->areafilename, b->innodefilename);
03571 increment = 0;
03572 strcpy(workstring, b->innodefilename);
03573 j = 1;
03574 while (workstring[j] != '\0') {
03575 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03576 increment = j + 1;
03577 }
03578 j++;
03579 }
03580 meshnumber = 0;
03581 if (increment > 0) {
03582 j = increment;
03583 do {
03584 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03585 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03586 } else {
03587 increment = 0;
03588 }
03589 j++;
03590 } while (workstring[j] != '\0');
03591 }
03592 if (b->noiterationnum) {
03593 strcpy(b->outnodefilename, b->innodefilename);
03594 strcpy(b->outelefilename, b->innodefilename);
03595 strcpy(b->edgefilename, b->innodefilename);
03596 strcpy(b->vnodefilename, b->innodefilename);
03597 strcpy(b->vedgefilename, b->innodefilename);
03598 strcpy(b->neighborfilename, b->innodefilename);
03599 strcpy(b->offfilename, b->innodefilename);
03600 strcat(b->outnodefilename, ".node");
03601 strcat(b->outelefilename, ".ele");
03602 strcat(b->edgefilename, ".edge");
03603 strcat(b->vnodefilename, ".v.node");
03604 strcat(b->vedgefilename, ".v.edge");
03605 strcat(b->neighborfilename, ".neigh");
03606 strcat(b->offfilename, ".off");
03607 } else if (increment == 0) {
03608 strcpy(b->outnodefilename, b->innodefilename);
03609 strcpy(b->outpolyfilename, b->innodefilename);
03610 strcpy(b->outelefilename, b->innodefilename);
03611 strcpy(b->edgefilename, b->innodefilename);
03612 strcpy(b->vnodefilename, b->innodefilename);
03613 strcpy(b->vedgefilename, b->innodefilename);
03614 strcpy(b->neighborfilename, b->innodefilename);
03615 strcpy(b->offfilename, b->innodefilename);
03616 strcat(b->outnodefilename, ".1.node");
03617 strcat(b->outpolyfilename, ".1.poly");
03618 strcat(b->outelefilename, ".1.ele");
03619 strcat(b->edgefilename, ".1.edge");
03620 strcat(b->vnodefilename, ".1.v.node");
03621 strcat(b->vedgefilename, ".1.v.edge");
03622 strcat(b->neighborfilename, ".1.neigh");
03623 strcat(b->offfilename, ".1.off");
03624 } else {
03625 workstring[increment] = '%';
03626 workstring[increment + 1] = 'd';
03627 workstring[increment + 2] = '\0';
03628 sprintf(b->outnodefilename, workstring, meshnumber + 1);
03629 strcpy(b->outpolyfilename, b->outnodefilename);
03630 strcpy(b->outelefilename, b->outnodefilename);
03631 strcpy(b->edgefilename, b->outnodefilename);
03632 strcpy(b->vnodefilename, b->outnodefilename);
03633 strcpy(b->vedgefilename, b->outnodefilename);
03634 strcpy(b->neighborfilename, b->outnodefilename);
03635 strcpy(b->offfilename, b->outnodefilename);
03636 strcat(b->outnodefilename, ".node");
03637 strcat(b->outpolyfilename, ".poly");
03638 strcat(b->outelefilename, ".ele");
03639 strcat(b->edgefilename, ".edge");
03640 strcat(b->vnodefilename, ".v.node");
03641 strcat(b->vedgefilename, ".v.edge");
03642 strcat(b->neighborfilename, ".neigh");
03643 strcat(b->offfilename, ".off");
03644 }
03645 strcat(b->innodefilename, ".node");
03646 strcat(b->inpolyfilename, ".poly");
03647 strcat(b->inelefilename, ".ele");
03648 strcat(b->areafilename, ".area");
03649 #endif
03650 }
03651
03654
03655
03656
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671 #ifdef ANSI_DECLARATORS
03672 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
03673 #else
03674 void printtriangle(m, b, t)
03675 struct mesh *m;
03676 struct behavior *b;
03677 struct otri *t;
03678 #endif
03679
03680 {
03681 struct otri printtri;
03682 struct osub printsh;
03683 vertex printvertex;
03684
03685 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
03686 t->orient);
03687 decode(t->tri[0], printtri);
03688 if (printtri.tri == m->dummytri) {
03689 printf(" [0] = Outer space\n");
03690 } else {
03691 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
03692 printtri.orient);
03693 }
03694 decode(t->tri[1], printtri);
03695 if (printtri.tri == m->dummytri) {
03696 printf(" [1] = Outer space\n");
03697 } else {
03698 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
03699 printtri.orient);
03700 }
03701 decode(t->tri[2], printtri);
03702 if (printtri.tri == m->dummytri) {
03703 printf(" [2] = Outer space\n");
03704 } else {
03705 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
03706 printtri.orient);
03707 }
03708
03709 org(*t, printvertex);
03710 if (printvertex == (vertex) NULL)
03711 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
03712 else
03713 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03714 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
03715 printvertex[0], printvertex[1]);
03716 dest(*t, printvertex);
03717 if (printvertex == (vertex) NULL)
03718 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
03719 else
03720 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03721 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
03722 printvertex[0], printvertex[1]);
03723 apex(*t, printvertex);
03724 if (printvertex == (vertex) NULL)
03725 printf(" Apex [%d] = NULL\n", t->orient + 3);
03726 else
03727 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
03728 t->orient + 3, (unsigned long) printvertex,
03729 printvertex[0], printvertex[1]);
03730
03731 if (b->usesegments) {
03732 sdecode(t->tri[6], printsh);
03733 if (printsh.ss != m->dummysub) {
03734 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
03735 printsh.ssorient);
03736 }
03737 sdecode(t->tri[7], printsh);
03738 if (printsh.ss != m->dummysub) {
03739 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
03740 printsh.ssorient);
03741 }
03742 sdecode(t->tri[8], printsh);
03743 if (printsh.ss != m->dummysub) {
03744 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
03745 printsh.ssorient);
03746 }
03747 }
03748
03749 if (b->vararea) {
03750 printf(" Area constraint: %.4g\n", areabound(*t));
03751 }
03752 }
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765 #ifdef ANSI_DECLARATORS
03766 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
03767 #else
03768 void printsubseg(m, b, s)
03769 struct mesh *m;
03770 struct behavior *b;
03771 struct osub *s;
03772 #endif
03773
03774 {
03775 struct osub printsh;
03776 struct otri printtri;
03777 vertex printvertex;
03778
03779 printf("subsegment x%lx with orientation %d and mark %d:\n",
03780 (unsigned long) s->ss, s->ssorient, mark(*s));
03781 sdecode(s->ss[0], printsh);
03782 if (printsh.ss == m->dummysub) {
03783 printf(" [0] = No subsegment\n");
03784 } else {
03785 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
03786 printsh.ssorient);
03787 }
03788 sdecode(s->ss[1], printsh);
03789 if (printsh.ss == m->dummysub) {
03790 printf(" [1] = No subsegment\n");
03791 } else {
03792 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
03793 printsh.ssorient);
03794 }
03795
03796 sorg(*s, printvertex);
03797 if (printvertex == (vertex) NULL)
03798 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
03799 else
03800 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03801 2 + s->ssorient, (unsigned long) printvertex,
03802 printvertex[0], printvertex[1]);
03803 sdest(*s, printvertex);
03804 if (printvertex == (vertex) NULL)
03805 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
03806 else
03807 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03808 3 - s->ssorient, (unsigned long) printvertex,
03809 printvertex[0], printvertex[1]);
03810
03811 decode(s->ss[6], printtri);
03812 if (printtri.tri == m->dummytri) {
03813 printf(" [6] = Outer space\n");
03814 } else {
03815 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
03816 printtri.orient);
03817 }
03818 decode(s->ss[7], printtri);
03819 if (printtri.tri == m->dummytri) {
03820 printf(" [7] = Outer space\n");
03821 } else {
03822 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
03823 printtri.orient);
03824 }
03825
03826 segorg(*s, printvertex);
03827 if (printvertex == (vertex) NULL)
03828 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
03829 else
03830 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
03831 4 + s->ssorient, (unsigned long) printvertex,
03832 printvertex[0], printvertex[1]);
03833 segdest(*s, printvertex);
03834 if (printvertex == (vertex) NULL)
03835 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
03836 else
03837 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
03838 5 - s->ssorient, (unsigned long) printvertex,
03839 printvertex[0], printvertex[1]);
03840 }
03841
03844
03845
03846
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859 #ifdef ANSI_DECLARATORS
03860 void poolzero(struct memorypool *pool)
03861 #else
03862 void poolzero(pool)
03863 struct memorypool *pool;
03864 #endif
03865
03866 {
03867 pool->firstblock = (VOID **) NULL;
03868 pool->nowblock = (VOID **) NULL;
03869 pool->nextitem = (VOID *) NULL;
03870 pool->deaditemstack = (VOID *) NULL;
03871 pool->pathblock = (VOID **) NULL;
03872 pool->pathitem = (VOID *) NULL;
03873 pool->alignbytes = 0;
03874 pool->itembytes = 0;
03875 pool->itemsperblock = 0;
03876 pool->itemsfirstblock = 0;
03877 pool->items = 0;
03878 pool->maxitems = 0;
03879 pool->unallocateditems = 0;
03880 pool->pathitemsleft = 0;
03881 }
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893 #ifdef ANSI_DECLARATORS
03894 void poolrestart(struct memorypool *pool)
03895 #else
03896 void poolrestart(pool)
03897 struct memorypool *pool;
03898 #endif
03899
03900 {
03901 unsigned long alignptr;
03902
03903 pool->items = 0;
03904 pool->maxitems = 0;
03905
03906
03907 pool->nowblock = pool->firstblock;
03908
03909 alignptr = (unsigned long) (pool->nowblock + 1);
03910
03911 pool->nextitem = (VOID *)
03912 (alignptr + (unsigned long) pool->alignbytes -
03913 (alignptr % (unsigned long) pool->alignbytes));
03914
03915 pool->unallocateditems = pool->itemsfirstblock;
03916
03917 pool->deaditemstack = (VOID *) NULL;
03918 }
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935
03936
03937
03938
03939 #ifdef ANSI_DECLARATORS
03940 void poolinit(struct memorypool *pool, int bytecount, int itemcount,
03941 int firstitemcount, int alignment)
03942 #else
03943 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
03944 struct memorypool *pool;
03945 int bytecount;
03946 int itemcount;
03947 int firstitemcount;
03948 int alignment;
03949 #endif
03950
03951 {
03952
03953
03954
03955
03956 if (alignment > sizeof(VOID *)) {
03957 pool->alignbytes = alignment;
03958 } else {
03959 pool->alignbytes = sizeof(VOID *);
03960 }
03961 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
03962 pool->alignbytes;
03963 pool->itemsperblock = itemcount;
03964 if (firstitemcount == 0) {
03965 pool->itemsfirstblock = itemcount;
03966 } else {
03967 pool->itemsfirstblock = firstitemcount;
03968 }
03969
03970
03971
03972
03973 pool->firstblock = (VOID **)
03974 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
03975 pool->alignbytes);
03976
03977 *(pool->firstblock) = (VOID *) NULL;
03978 poolrestart(pool);
03979 }
03980
03981
03982
03983
03984
03985
03986
03987 #ifdef ANSI_DECLARATORS
03988 void pooldeinit(struct memorypool *pool)
03989 #else
03990 void pooldeinit(pool)
03991 struct memorypool *pool;
03992 #endif
03993
03994 {
03995 while (pool->firstblock != (VOID **) NULL) {
03996 pool->nowblock = (VOID **) *(pool->firstblock);
03997 trifree((VOID *) pool->firstblock);
03998 pool->firstblock = pool->nowblock;
03999 }
04000 }
04001
04002
04003
04004
04005
04006
04007
04008 #ifdef ANSI_DECLARATORS
04009 VOID *poolalloc(struct memorypool *pool)
04010 #else
04011 VOID *poolalloc(pool)
04012 struct memorypool *pool;
04013 #endif
04014
04015 {
04016 VOID *newitem;
04017 VOID **newblock;
04018 unsigned long alignptr;
04019
04020
04021
04022 if (pool->deaditemstack != (VOID *) NULL) {
04023 newitem = pool->deaditemstack;
04024 pool->deaditemstack = * (VOID **) pool->deaditemstack;
04025 } else {
04026
04027 if (pool->unallocateditems == 0) {
04028
04029 if (*(pool->nowblock) == (VOID *) NULL) {
04030
04031 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
04032 (int) sizeof(VOID *) +
04033 pool->alignbytes);
04034 *(pool->nowblock) = (VOID *) newblock;
04035
04036 *newblock = (VOID *) NULL;
04037 }
04038
04039
04040 pool->nowblock = (VOID **) *(pool->nowblock);
04041
04042
04043 alignptr = (unsigned long) (pool->nowblock + 1);
04044
04045 pool->nextitem = (VOID *)
04046 (alignptr + (unsigned long) pool->alignbytes -
04047 (alignptr % (unsigned long) pool->alignbytes));
04048
04049 pool->unallocateditems = pool->itemsperblock;
04050 }
04051
04052
04053 newitem = pool->nextitem;
04054
04055 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
04056 pool->unallocateditems--;
04057 pool->maxitems++;
04058 }
04059 pool->items++;
04060 return newitem;
04061 }
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071 #ifdef ANSI_DECLARATORS
04072 void pooldealloc(struct memorypool *pool, VOID *dyingitem)
04073 #else
04074 void pooldealloc(pool, dyingitem)
04075 struct memorypool *pool;
04076 VOID *dyingitem;
04077 #endif
04078
04079 {
04080
04081 *((VOID **) dyingitem) = pool->deaditemstack;
04082 pool->deaditemstack = dyingitem;
04083 pool->items--;
04084 }
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094 #ifdef ANSI_DECLARATORS
04095 void traversalinit(struct memorypool *pool)
04096 #else
04097 void traversalinit(pool)
04098 struct memorypool *pool;
04099 #endif
04100
04101 {
04102 unsigned long alignptr;
04103
04104
04105 pool->pathblock = pool->firstblock;
04106
04107 alignptr = (unsigned long) (pool->pathblock + 1);
04108
04109 pool->pathitem = (VOID *)
04110 (alignptr + (unsigned long) pool->alignbytes -
04111 (alignptr % (unsigned long) pool->alignbytes));
04112
04113 pool->pathitemsleft = pool->itemsfirstblock;
04114 }
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126
04127
04128
04129
04130 #ifdef ANSI_DECLARATORS
04131 VOID *traverse(struct memorypool *pool)
04132 #else
04133 VOID *traverse(pool)
04134 struct memorypool *pool;
04135 #endif
04136
04137 {
04138 VOID *newitem;
04139 unsigned long alignptr;
04140
04141
04142 if (pool->pathitem == pool->nextitem) {
04143 return (VOID *) NULL;
04144 }
04145
04146
04147 if (pool->pathitemsleft == 0) {
04148
04149 pool->pathblock = (VOID **) *(pool->pathblock);
04150
04151 alignptr = (unsigned long) (pool->pathblock + 1);
04152
04153 pool->pathitem = (VOID *)
04154 (alignptr + (unsigned long) pool->alignbytes -
04155 (alignptr % (unsigned long) pool->alignbytes));
04156
04157 pool->pathitemsleft = pool->itemsperblock;
04158 }
04159
04160 newitem = pool->pathitem;
04161
04162 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
04163 pool->pathitemsleft--;
04164 return newitem;
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
04192
04193
04194
04195 #ifdef ANSI_DECLARATORS
04196 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
04197 int subsegbytes)
04198 #else
04199 void dummyinit(m, b, trianglebytes, subsegbytes)
04200 struct mesh *m;
04201 struct behavior *b;
04202 int trianglebytes;
04203 int subsegbytes;
04204 #endif
04205
04206 {
04207 unsigned long alignptr;
04208
04209
04210 m->dummytribase = (triangle *) trimalloc(trianglebytes +
04211 m->triangles.alignbytes);
04212
04213 alignptr = (unsigned long) m->dummytribase;
04214 m->dummytri = (triangle *)
04215 (alignptr + (unsigned long) m->triangles.alignbytes -
04216 (alignptr % (unsigned long) m->triangles.alignbytes));
04217
04218
04219
04220
04221 m->dummytri[0] = (triangle) m->dummytri;
04222 m->dummytri[1] = (triangle) m->dummytri;
04223 m->dummytri[2] = (triangle) m->dummytri;
04224
04225 m->dummytri[3] = (triangle) NULL;
04226 m->dummytri[4] = (triangle) NULL;
04227 m->dummytri[5] = (triangle) NULL;
04228
04229 if (b->usesegments) {
04230
04231
04232
04233 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
04234 m->subsegs.alignbytes);
04235
04236 alignptr = (unsigned long) m->dummysubbase;
04237 m->dummysub = (subseg *)
04238 (alignptr + (unsigned long) m->subsegs.alignbytes -
04239 (alignptr % (unsigned long) m->subsegs.alignbytes));
04240
04241
04242
04243
04244 m->dummysub[0] = (subseg) m->dummysub;
04245 m->dummysub[1] = (subseg) m->dummysub;
04246
04247 m->dummysub[2] = (subseg) NULL;
04248 m->dummysub[3] = (subseg) NULL;
04249 m->dummysub[4] = (subseg) NULL;
04250 m->dummysub[5] = (subseg) NULL;
04251
04252 m->dummysub[6] = (subseg) m->dummytri;
04253 m->dummysub[7] = (subseg) m->dummytri;
04254
04255 * (int *) (m->dummysub + 8) = 0;
04256
04257
04258
04259 m->dummytri[6] = (triangle) m->dummysub;
04260 m->dummytri[7] = (triangle) m->dummysub;
04261 m->dummytri[8] = (triangle) m->dummysub;
04262 }
04263 }
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275 #ifdef ANSI_DECLARATORS
04276 void initializevertexpool(struct mesh *m, struct behavior *b)
04277 #else
04278 void initializevertexpool(m, b)
04279 struct mesh *m;
04280 struct behavior *b;
04281 #endif
04282
04283 {
04284 int vertexsize;
04285
04286
04287
04288
04289 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
04290 sizeof(int) - 1) /
04291 sizeof(int);
04292 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
04293 if (b->poly) {
04294
04295
04296 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
04297 sizeof(triangle);
04298 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
04299 }
04300
04301
04302 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
04303 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
04304 sizeof(REAL));
04305 }
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318 #ifdef ANSI_DECLARATORS
04319 void initializetrisubpools(struct mesh *m, struct behavior *b)
04320 #else
04321 void initializetrisubpools(m, b)
04322 struct mesh *m;
04323 struct behavior *b;
04324 #endif
04325
04326 {
04327 int trisize;
04328
04329
04330
04331
04332
04333 m->highorderindex = 6 + (b->usesegments * 3);
04334
04335 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
04336 sizeof(triangle);
04337
04338
04339 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
04340
04341
04342
04343 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
04344
04345
04346 if (b->vararea) {
04347 trisize = (m->areaboundindex + 1) * sizeof(REAL);
04348 } else if (m->eextras + b->regionattrib > 0) {
04349 trisize = m->areaboundindex * sizeof(REAL);
04350 }
04351
04352
04353
04354
04355 if ((b->voronoi || b->neighbors) &&
04356 (trisize < 6 * sizeof(triangle) + sizeof(int))) {
04357 trisize = 6 * sizeof(triangle) + sizeof(int);
04358 }
04359
04360
04361 poolinit(&m->triangles, trisize, TRIPERBLOCK,
04362 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
04363 TRIPERBLOCK, 4);
04364
04365 if (b->usesegments) {
04366
04367
04368 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
04369 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
04370
04371
04372 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
04373 } else {
04374
04375 dummyinit(m, b, m->triangles.itembytes, 0);
04376 }
04377 }
04378
04379
04380
04381
04382
04383
04384
04385 #ifdef ANSI_DECLARATORS
04386 void triangledealloc(struct mesh *m, triangle *dyingtriangle)
04387 #else
04388 void triangledealloc(m, dyingtriangle)
04389 struct mesh *m;
04390 triangle *dyingtriangle;
04391 #endif
04392
04393 {
04394
04395
04396 killtri(dyingtriangle);
04397 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
04398 }
04399
04400
04401
04402
04403
04404
04405
04406 #ifdef ANSI_DECLARATORS
04407 triangle *triangletraverse(struct mesh *m)
04408 #else
04409 triangle *triangletraverse(m)
04410 struct mesh *m;
04411 #endif
04412
04413 {
04414 triangle *newtriangle;
04415
04416 do {
04417 newtriangle = (triangle *) traverse(&m->triangles);
04418 if (newtriangle == (triangle *) NULL) {
04419 return (triangle *) NULL;
04420 }
04421 } while (deadtri(newtriangle));
04422 return newtriangle;
04423 }
04424
04425
04426
04427
04428
04429
04430
04431 #ifdef ANSI_DECLARATORS
04432 void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
04433 #else
04434 void subsegdealloc(m, dyingsubseg)
04435 struct mesh *m;
04436 subseg *dyingsubseg;
04437 #endif
04438
04439 {
04440
04441
04442 killsubseg(dyingsubseg);
04443 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
04444 }
04445
04446
04447
04448
04449
04450
04451
04452 #ifdef ANSI_DECLARATORS
04453 subseg *subsegtraverse(struct mesh *m)
04454 #else
04455 subseg *subsegtraverse(m)
04456 struct mesh *m;
04457 #endif
04458
04459 {
04460 subseg *newsubseg;
04461
04462 do {
04463 newsubseg = (subseg *) traverse(&m->subsegs);
04464 if (newsubseg == (subseg *) NULL) {
04465 return (subseg *) NULL;
04466 }
04467 } while (deadsubseg(newsubseg));
04468 return newsubseg;
04469 }
04470
04471
04472
04473
04474
04475
04476
04477 #ifdef ANSI_DECLARATORS
04478 void vertexdealloc(struct mesh *m, vertex dyingvertex)
04479 #else
04480 void vertexdealloc(m, dyingvertex)
04481 struct mesh *m;
04482 vertex dyingvertex;
04483 #endif
04484
04485 {
04486
04487
04488 setvertextype(dyingvertex, DEADVERTEX);
04489 pooldealloc(&m->vertices, (VOID *) dyingvertex);
04490 }
04491
04492
04493
04494
04495
04496
04497
04498 #ifdef ANSI_DECLARATORS
04499 vertex vertextraverse(struct mesh *m)
04500 #else
04501 vertex vertextraverse(m)
04502 struct mesh *m;
04503 #endif
04504
04505 {
04506 vertex newvertex;
04507
04508 do {
04509 newvertex = (vertex) traverse(&m->vertices);
04510 if (newvertex == (vertex) NULL) {
04511 return (vertex) NULL;
04512 }
04513 } while (vertextype(newvertex) == DEADVERTEX);
04514 return newvertex;
04515 }
04516
04517
04518
04519
04520
04521
04522
04523
04524 #ifndef CDT_ONLY
04525
04526 #ifdef ANSI_DECLARATORS
04527 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
04528 #else
04529 void badsubsegdealloc(m, dyingseg)
04530 struct mesh *m;
04531 struct badsubseg *dyingseg;
04532 #endif
04533
04534 {
04535
04536
04537 dyingseg->subsegorg = (vertex) NULL;
04538 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
04539 }
04540
04541 #endif
04542
04543
04544
04545
04546
04547
04548
04549 #ifndef CDT_ONLY
04550
04551 #ifdef ANSI_DECLARATORS
04552 struct badsubseg *badsubsegtraverse(struct mesh *m)
04553 #else
04554 struct badsubseg *badsubsegtraverse(m)
04555 struct mesh *m;
04556 #endif
04557
04558 {
04559 struct badsubseg *newseg;
04560
04561 do {
04562 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
04563 if (newseg == (struct badsubseg *) NULL) {
04564 return (struct badsubseg *) NULL;
04565 }
04566 } while (newseg->subsegorg == (vertex) NULL);
04567 return newseg;
04568 }
04569
04570 #endif
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580
04581
04582
04583
04584 #ifdef ANSI_DECLARATORS
04585 vertex getvertex(struct mesh *m, struct behavior *b, int number)
04586 #else
04587 vertex getvertex(m, b, number)
04588 struct mesh *m;
04589 struct behavior *b;
04590 int number;
04591 #endif
04592
04593 {
04594 VOID **getblock;
04595 char *foundvertex;
04596 unsigned long alignptr;
04597 int current;
04598
04599 getblock = m->vertices.firstblock;
04600 current = b->firstnumber;
04601
04602
04603 if (current + m->vertices.itemsfirstblock <= number) {
04604 getblock = (VOID **) *getblock;
04605 current += m->vertices.itemsfirstblock;
04606 while (current + m->vertices.itemsperblock <= number) {
04607 getblock = (VOID **) *getblock;
04608 current += m->vertices.itemsperblock;
04609 }
04610 }
04611
04612
04613 alignptr = (unsigned long) (getblock + 1);
04614 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
04615 (alignptr % (unsigned long) m->vertices.alignbytes));
04616 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
04617 }
04618
04619
04620
04621
04622
04623
04624
04625 #ifdef ANSI_DECLARATORS
04626 void triangledeinit(struct mesh *m, struct behavior *b)
04627 #else
04628 void triangledeinit(m, b)
04629 struct mesh *m;
04630 struct behavior *b;
04631 #endif
04632
04633 {
04634 pooldeinit(&m->triangles);
04635 trifree((VOID *) m->dummytribase);
04636 if (b->usesegments) {
04637 pooldeinit(&m->subsegs);
04638 trifree((VOID *) m->dummysubbase);
04639 }
04640 pooldeinit(&m->vertices);
04641 #ifndef CDT_ONLY
04642 if (b->quality) {
04643 pooldeinit(&m->badsubsegs);
04644 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
04645 pooldeinit(&m->badtriangles);
04646 pooldeinit(&m->flipstackers);
04647 }
04648 }
04649 #endif
04650 }
04651
04654
04655
04656
04660
04661
04662
04663
04664
04665
04666 #ifdef ANSI_DECLARATORS
04667 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
04668 #else
04669 void maketriangle(m, b, newotri)
04670 struct mesh *m;
04671 struct behavior *b;
04672 struct otri *newotri;
04673 #endif
04674
04675 {
04676 int i;
04677
04678 newotri->tri = (triangle *) poolalloc(&m->triangles);
04679
04680 newotri->tri[0] = (triangle) m->dummytri;
04681 newotri->tri[1] = (triangle) m->dummytri;
04682 newotri->tri[2] = (triangle) m->dummytri;
04683
04684 newotri->tri[3] = (triangle) NULL;
04685 newotri->tri[4] = (triangle) NULL;
04686 newotri->tri[5] = (triangle) NULL;
04687 if (b->usesegments) {
04688
04689
04690 newotri->tri[6] = (triangle) m->dummysub;
04691 newotri->tri[7] = (triangle) m->dummysub;
04692 newotri->tri[8] = (triangle) m->dummysub;
04693 }
04694 for (i = 0; i < m->eextras; i++) {
04695 setelemattribute(*newotri, i, 0.0);
04696 }
04697 if (b->vararea) {
04698 setareabound(*newotri, -1.0);
04699 }
04700
04701 newotri->orient = 0;
04702 }
04703
04704
04705
04706
04707
04708
04709
04710 #ifdef ANSI_DECLARATORS
04711 void makesubseg(struct mesh *m, struct osub *newsubseg)
04712 #else
04713 void makesubseg(m, newsubseg)
04714 struct mesh *m;
04715 struct osub *newsubseg;
04716 #endif
04717
04718 {
04719 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
04720
04721
04722 newsubseg->ss[0] = (subseg) m->dummysub;
04723 newsubseg->ss[1] = (subseg) m->dummysub;
04724
04725 newsubseg->ss[2] = (subseg) NULL;
04726 newsubseg->ss[3] = (subseg) NULL;
04727 newsubseg->ss[4] = (subseg) NULL;
04728 newsubseg->ss[5] = (subseg) NULL;
04729
04730 newsubseg->ss[6] = (subseg) m->dummytri;
04731 newsubseg->ss[7] = (subseg) m->dummytri;
04732
04733 setmark(*newsubseg, 0);
04734
04735 newsubseg->ssorient = 0;
04736 }
04737
04740
04741
04742
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755
04756
04757
04758
04759 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775 #define Fast_Two_Sum_Tail(a, b, x, y) \
04776 bvirt = x - a; \
04777 y = b - bvirt
04778
04779 #define Fast_Two_Sum(a, b, x, y) \
04780 x = (REAL) (a + b); \
04781 Fast_Two_Sum_Tail(a, b, x, y)
04782
04783 #define Two_Sum_Tail(a, b, x, y) \
04784 bvirt = (REAL) (x - a); \
04785 avirt = x - bvirt; \
04786 bround = b - bvirt; \
04787 around = a - avirt; \
04788 y = around + bround
04789
04790 #define Two_Sum(a, b, x, y) \
04791 x = (REAL) (a + b); \
04792 Two_Sum_Tail(a, b, x, y)
04793
04794 #define Two_Diff_Tail(a, b, x, y) \
04795 bvirt = (REAL) (a - x); \
04796 avirt = x + bvirt; \
04797 bround = bvirt - b; \
04798 around = a - avirt; \
04799 y = around + bround
04800
04801 #define Two_Diff(a, b, x, y) \
04802 x = (REAL) (a - b); \
04803 Two_Diff_Tail(a, b, x, y)
04804
04805 #define Split(a, ahi, alo) \
04806 c = (REAL) (splitter * a); \
04807 abig = (REAL) (c - a); \
04808 ahi = c - abig; \
04809 alo = a - ahi
04810
04811 #define Two_Product_Tail(a, b, x, y) \
04812 Split(a, ahi, alo); \
04813 Split(b, bhi, blo); \
04814 err1 = x - (ahi * bhi); \
04815 err2 = err1 - (alo * bhi); \
04816 err3 = err2 - (ahi * blo); \
04817 y = (alo * blo) - err3
04818
04819 #define Two_Product(a, b, x, y) \
04820 x = (REAL) (a * b); \
04821 Two_Product_Tail(a, b, x, y)
04822
04823
04824
04825
04826 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
04827 x = (REAL) (a * b); \
04828 Split(a, ahi, alo); \
04829 err1 = x - (ahi * bhi); \
04830 err2 = err1 - (alo * bhi); \
04831 err3 = err2 - (ahi * blo); \
04832 y = (alo * blo) - err3
04833
04834
04835
04836 #define Square_Tail(a, x, y) \
04837 Split(a, ahi, alo); \
04838 err1 = x - (ahi * ahi); \
04839 err3 = err1 - ((ahi + ahi) * alo); \
04840 y = (alo * alo) - err3
04841
04842 #define Square(a, x, y) \
04843 x = (REAL) (a * a); \
04844 Square_Tail(a, x, y)
04845
04846
04847
04848
04849 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
04850 Two_Sum(a0, b , _i, x0); \
04851 Two_Sum(a1, _i, x2, x1)
04852
04853 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
04854 Two_Diff(a0, b , _i, x0); \
04855 Two_Sum( a1, _i, x2, x1)
04856
04857 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
04858 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
04859 Two_One_Sum(_j, _0, b1, x3, x2, x1)
04860
04861 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
04862 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
04863 Two_One_Diff(_j, _0, b1, x3, x2, x1)
04864
04865
04866
04867 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
04868 Split(b, bhi, blo); \
04869 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
04870 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
04871 Two_Sum(_i, _0, _k, x1); \
04872 Fast_Two_Sum(_j, _k, x3, x2)
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893 void exactinit()
04894 {
04895 REAL half;
04896 REAL check, lastcheck;
04897 int every_other;
04898 #ifdef LINUX
04899 int cword;
04900 #endif
04901
04902 #ifdef CPU86
04903 #ifdef SINGLE
04904 _control87(_PC_24, _MCW_PC);
04905 #else
04906 _control87(_PC_53, _MCW_PC);
04907 #endif
04908 #endif
04909 #ifdef LINUX
04910 #ifdef SINGLE
04911
04912 cword = 4210;
04913 #else
04914
04915 cword = 4722;
04916 #endif
04917 _FPU_SETCW(cword);
04918 #endif
04919
04920 every_other = 1;
04921 half = 0.5;
04922 epsilon = 1.0;
04923 splitter = 1.0;
04924 check = 1.0;
04925
04926
04927
04928
04929 do {
04930 lastcheck = check;
04931 epsilon *= half;
04932 if (every_other) {
04933 splitter *= 2.0;
04934 }
04935 every_other = !every_other;
04936 check = 1.0 + epsilon;
04937 } while ((check != 1.0) && (check != lastcheck));
04938 splitter += 1.0;
04939
04940 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
04941 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
04942 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
04943 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
04944 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
04945 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
04946 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
04947 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
04948 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
04949 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
04950 }
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966 #ifdef ANSI_DECLARATORS
04967 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
04968 #else
04969 int fast_expansion_sum_zeroelim(elen, e, flen, f, h)
04970 int elen;
04971 REAL *e;
04972 int flen;
04973 REAL *f;
04974 REAL *h;
04975 #endif
04976
04977 {
04978 REAL Q;
04979 INEXACT REAL Qnew;
04980 INEXACT REAL hh;
04981 INEXACT REAL bvirt;
04982 REAL avirt, bround, around;
04983 int eindex, findex, hindex;
04984 REAL enow, fnow;
04985
04986 enow = e[0];
04987 fnow = f[0];
04988 eindex = findex = 0;
04989 if ((fnow > enow) == (fnow > -enow)) {
04990 Q = enow;
04991 enow = e[++eindex];
04992 } else {
04993 Q = fnow;
04994 fnow = f[++findex];
04995 }
04996 hindex = 0;
04997 if ((eindex < elen) && (findex < flen)) {
04998 if ((fnow > enow) == (fnow > -enow)) {
04999 Fast_Two_Sum(enow, Q, Qnew, hh);
05000 enow = e[++eindex];
05001 } else {
05002 Fast_Two_Sum(fnow, Q, Qnew, hh);
05003 fnow = f[++findex];
05004 }
05005 Q = Qnew;
05006 if (hh != 0.0) {
05007 h[hindex++] = hh;
05008 }
05009 while ((eindex < elen) && (findex < flen)) {
05010 if ((fnow > enow) == (fnow > -enow)) {
05011 Two_Sum(Q, enow, Qnew, hh);
05012 enow = e[++eindex];
05013 } else {
05014 Two_Sum(Q, fnow, Qnew, hh);
05015 fnow = f[++findex];
05016 }
05017 Q = Qnew;
05018 if (hh != 0.0) {
05019 h[hindex++] = hh;
05020 }
05021 }
05022 }
05023 while (eindex < elen) {
05024 Two_Sum(Q, enow, Qnew, hh);
05025 enow = e[++eindex];
05026 Q = Qnew;
05027 if (hh != 0.0) {
05028 h[hindex++] = hh;
05029 }
05030 }
05031 while (findex < flen) {
05032 Two_Sum(Q, fnow, Qnew, hh);
05033 fnow = f[++findex];
05034 Q = Qnew;
05035 if (hh != 0.0) {
05036 h[hindex++] = hh;
05037 }
05038 }
05039 if ((Q != 0.0) || (hindex == 0)) {
05040 h[hindex++] = Q;
05041 }
05042 return hindex;
05043 }
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060 #ifdef ANSI_DECLARATORS
05061 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
05062 #else
05063 int scale_expansion_zeroelim(elen, e, b, h)
05064 int elen;
05065 REAL *e;
05066 REAL b;
05067 REAL *h;
05068 #endif
05069
05070 {
05071 INEXACT REAL Q, sum;
05072 REAL hh;
05073 INEXACT REAL product1;
05074 REAL product0;
05075 int eindex, hindex;
05076 REAL enow;
05077 INEXACT REAL bvirt;
05078 REAL avirt, bround, around;
05079 INEXACT REAL c;
05080 INEXACT REAL abig;
05081 REAL ahi, alo, bhi, blo;
05082 REAL err1, err2, err3;
05083
05084 Split(b, bhi, blo);
05085 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
05086 hindex = 0;
05087 if (hh != 0) {
05088 h[hindex++] = hh;
05089 }
05090 for (eindex = 1; eindex < elen; eindex++) {
05091 enow = e[eindex];
05092 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
05093 Two_Sum(Q, product0, sum, hh);
05094 if (hh != 0) {
05095 h[hindex++] = hh;
05096 }
05097 Fast_Two_Sum(product1, sum, Q, hh);
05098 if (hh != 0) {
05099 h[hindex++] = hh;
05100 }
05101 }
05102 if ((Q != 0.0) || (hindex == 0)) {
05103 h[hindex++] = Q;
05104 }
05105 return hindex;
05106 }
05107
05108
05109
05110
05111
05112
05113
05114
05115
05116 #ifdef ANSI_DECLARATORS
05117 REAL estimate(int elen, REAL *e)
05118 #else
05119 REAL estimate(elen, e)
05120 int elen;
05121 REAL *e;
05122 #endif
05123
05124 {
05125 REAL Q;
05126 int eindex;
05127
05128 Q = e[0];
05129 for (eindex = 1; eindex < elen; eindex++) {
05130 Q += e[eindex];
05131 }
05132 return Q;
05133 }
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155 #ifdef ANSI_DECLARATORS
05156 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
05157 #else
05158 REAL counterclockwiseadapt(pa, pb, pc, detsum)
05159 vertex pa;
05160 vertex pb;
05161 vertex pc;
05162 REAL detsum;
05163 #endif
05164
05165 {
05166 INEXACT REAL acx, acy, bcx, bcy;
05167 REAL acxtail, acytail, bcxtail, bcytail;
05168 INEXACT REAL detleft, detright;
05169 REAL detlefttail, detrighttail;
05170 REAL det, errbound;
05171 REAL B[4], C1[8], C2[12], D[16];
05172 INEXACT REAL B3;
05173 int C1length, C2length, Dlength;
05174 REAL u[4];
05175 INEXACT REAL u3;
05176 INEXACT REAL s1, t1;
05177 REAL s0, t0;
05178
05179 INEXACT REAL bvirt;
05180 REAL avirt, bround, around;
05181 INEXACT REAL c;
05182 INEXACT REAL abig;
05183 REAL ahi, alo, bhi, blo;
05184 REAL err1, err2, err3;
05185 INEXACT REAL _i, _j;
05186 REAL _0;
05187
05188 acx = (REAL) (pa[0] - pc[0]);
05189 bcx = (REAL) (pb[0] - pc[0]);
05190 acy = (REAL) (pa[1] - pc[1]);
05191 bcy = (REAL) (pb[1] - pc[1]);
05192
05193 Two_Product(acx, bcy, detleft, detlefttail);
05194 Two_Product(acy, bcx, detright, detrighttail);
05195
05196 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
05197 B3, B[2], B[1], B[0]);
05198 B[3] = B3;
05199
05200 det = estimate(4, B);
05201 errbound = ccwerrboundB * detsum;
05202 if ((det >= errbound) || (-det >= errbound)) {
05203 return det;
05204 }
05205
05206 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
05207 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
05208 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
05209 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
05210
05211 if ((acxtail == 0.0) && (acytail == 0.0)
05212 && (bcxtail == 0.0) && (bcytail == 0.0)) {
05213 return det;
05214 }
05215
05216 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
05217 det += (acx * bcytail + bcy * acxtail)
05218 - (acy * bcxtail + bcx * acytail);
05219 if ((det >= errbound) || (-det >= errbound)) {
05220 return det;
05221 }
05222
05223 Two_Product(acxtail, bcy, s1, s0);
05224 Two_Product(acytail, bcx, t1, t0);
05225 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05226 u[3] = u3;
05227 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
05228
05229 Two_Product(acx, bcytail, s1, s0);
05230 Two_Product(acy, bcxtail, t1, t0);
05231 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05232 u[3] = u3;
05233 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
05234
05235 Two_Product(acxtail, bcytail, s1, s0);
05236 Two_Product(acytail, bcxtail, t1, t0);
05237 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05238 u[3] = u3;
05239 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
05240
05241 return(D[Dlength - 1]);
05242 }
05243
05244 #ifdef ANSI_DECLARATORS
05245 REAL counterclockwise(struct mesh *m, struct behavior *b,
05246 vertex pa, vertex pb, vertex pc)
05247 #else
05248 REAL counterclockwise(m, b, pa, pb, pc)
05249 struct mesh *m;
05250 struct behavior *b;
05251 vertex pa;
05252 vertex pb;
05253 vertex pc;
05254 #endif
05255
05256 {
05257 REAL detleft, detright, det;
05258 REAL detsum, errbound;
05259
05260 m->counterclockcount++;
05261
05262 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
05263 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
05264 det = detleft - detright;
05265
05266 if (b->noexact) {
05267 return det;
05268 }
05269
05270 if (detleft > 0.0) {
05271 if (detright <= 0.0) {
05272 return det;
05273 } else {
05274 detsum = detleft + detright;
05275 }
05276 } else if (detleft < 0.0) {
05277 if (detright >= 0.0) {
05278 return det;
05279 } else {
05280 detsum = -detleft - detright;
05281 }
05282 } else {
05283 return det;
05284 }
05285
05286 errbound = ccwerrboundA * detsum;
05287 if ((det >= errbound) || (-det >= errbound)) {
05288 return det;
05289 }
05290
05291 return counterclockwiseadapt(pa, pb, pc, detsum);
05292 }
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310
05311
05312
05313 #ifdef ANSI_DECLARATORS
05314 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
05315 #else
05316 REAL incircleadapt(pa, pb, pc, pd, permanent)
05317 vertex pa;
05318 vertex pb;
05319 vertex pc;
05320 vertex pd;
05321 REAL permanent;
05322 #endif
05323
05324 {
05325 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
05326 REAL det, errbound;
05327
05328 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05329 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05330 REAL bc[4], ca[4], ab[4];
05331 INEXACT REAL bc3, ca3, ab3;
05332 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
05333 int axbclen, axxbclen, aybclen, ayybclen, alen;
05334 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
05335 int bxcalen, bxxcalen, bycalen, byycalen, blen;
05336 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
05337 int cxablen, cxxablen, cyablen, cyyablen, clen;
05338 REAL abdet[64];
05339 int ablen;
05340 REAL fin1[1152], fin2[1152];
05341 REAL *finnow, *finother, *finswap;
05342 int finlength;
05343
05344 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
05345 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
05346 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
05347 REAL aa[4], bb[4], cc[4];
05348 INEXACT REAL aa3, bb3, cc3;
05349 INEXACT REAL ti1, tj1;
05350 REAL ti0, tj0;
05351 REAL u[4], v[4];
05352 INEXACT REAL u3, v3;
05353 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
05354 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
05355 int temp8len, temp16alen, temp16blen, temp16clen;
05356 int temp32alen, temp32blen, temp48len, temp64len;
05357 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
05358 int axtbblen, axtcclen, aytbblen, aytcclen;
05359 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
05360 int bxtaalen, bxtcclen, bytaalen, bytcclen;
05361 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
05362 int cxtaalen, cxtbblen, cytaalen, cytbblen;
05363 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
05364 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
05365 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
05366 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
05367 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
05368 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
05369 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
05370 REAL abt[8], bct[8], cat[8];
05371 int abtlen, bctlen, catlen;
05372 REAL abtt[4], bctt[4], catt[4];
05373 int abttlen, bcttlen, cattlen;
05374 INEXACT REAL abtt3, bctt3, catt3;
05375 REAL negate;
05376
05377 INEXACT REAL bvirt;
05378 REAL avirt, bround, around;
05379 INEXACT REAL c;
05380 INEXACT REAL abig;
05381 REAL ahi, alo, bhi, blo;
05382 REAL err1, err2, err3;
05383 INEXACT REAL _i, _j;
05384 REAL _0;
05385
05386 adx = (REAL) (pa[0] - pd[0]);
05387 bdx = (REAL) (pb[0] - pd[0]);
05388 cdx = (REAL) (pc[0] - pd[0]);
05389 ady = (REAL) (pa[1] - pd[1]);
05390 bdy = (REAL) (pb[1] - pd[1]);
05391 cdy = (REAL) (pc[1] - pd[1]);
05392
05393 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
05394 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
05395 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
05396 bc[3] = bc3;
05397 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
05398 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
05399 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
05400 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
05401 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
05402
05403 Two_Product(cdx, ady, cdxady1, cdxady0);
05404 Two_Product(adx, cdy, adxcdy1, adxcdy0);
05405 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
05406 ca[3] = ca3;
05407 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
05408 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
05409 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
05410 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
05411 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
05412
05413 Two_Product(adx, bdy, adxbdy1, adxbdy0);
05414 Two_Product(bdx, ady, bdxady1, bdxady0);
05415 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
05416 ab[3] = ab3;
05417 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
05418 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
05419 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
05420 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
05421 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
05422
05423 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
05424 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
05425
05426 det = estimate(finlength, fin1);
05427 errbound = iccerrboundB * permanent;
05428 if ((det >= errbound) || (-det >= errbound)) {
05429 return det;
05430 }
05431
05432 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
05433 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
05434 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
05435 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
05436 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
05437 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
05438 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
05439 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
05440 return det;
05441 }
05442
05443 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
05444 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
05445 - (bdy * cdxtail + cdx * bdytail))
05446 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
05447 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
05448 - (cdy * adxtail + adx * cdytail))
05449 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
05450 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
05451 - (ady * bdxtail + bdx * adytail))
05452 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
05453 if ((det >= errbound) || (-det >= errbound)) {
05454 return det;
05455 }
05456
05457 finnow = fin1;
05458 finother = fin2;
05459
05460 if ((bdxtail != 0.0) || (bdytail != 0.0)
05461 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05462 Square(adx, adxadx1, adxadx0);
05463 Square(ady, adyady1, adyady0);
05464 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
05465 aa[3] = aa3;
05466 }
05467 if ((cdxtail != 0.0) || (cdytail != 0.0)
05468 || (adxtail != 0.0) || (adytail != 0.0)) {
05469 Square(bdx, bdxbdx1, bdxbdx0);
05470 Square(bdy, bdybdy1, bdybdy0);
05471 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
05472 bb[3] = bb3;
05473 }
05474 if ((adxtail != 0.0) || (adytail != 0.0)
05475 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05476 Square(cdx, cdxcdx1, cdxcdx0);
05477 Square(cdy, cdycdy1, cdycdy0);
05478 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
05479 cc[3] = cc3;
05480 }
05481
05482 if (adxtail != 0.0) {
05483 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
05484 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
05485 temp16a);
05486
05487 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
05488 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
05489
05490 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
05491 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
05492
05493 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05494 temp16blen, temp16b, temp32a);
05495 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05496 temp32alen, temp32a, temp48);
05497 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05498 temp48, finother);
05499 finswap = finnow; finnow = finother; finother = finswap;
05500 }
05501 if (adytail != 0.0) {
05502 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
05503 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
05504 temp16a);
05505
05506 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
05507 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
05508
05509 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
05510 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
05511
05512 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05513 temp16blen, temp16b, temp32a);
05514 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05515 temp32alen, temp32a, temp48);
05516 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05517 temp48, finother);
05518 finswap = finnow; finnow = finother; finother = finswap;
05519 }
05520 if (bdxtail != 0.0) {
05521 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
05522 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
05523 temp16a);
05524
05525 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
05526 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
05527
05528 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
05529 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
05530
05531 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05532 temp16blen, temp16b, temp32a);
05533 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05534 temp32alen, temp32a, temp48);
05535 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05536 temp48, finother);
05537 finswap = finnow; finnow = finother; finother = finswap;
05538 }
05539 if (bdytail != 0.0) {
05540 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
05541 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
05542 temp16a);
05543
05544 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
05545 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
05546
05547 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
05548 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
05549
05550 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05551 temp16blen, temp16b, temp32a);
05552 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05553 temp32alen, temp32a, temp48);
05554 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05555 temp48, finother);
05556 finswap = finnow; finnow = finother; finother = finswap;
05557 }
05558 if (cdxtail != 0.0) {
05559 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
05560 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
05561 temp16a);
05562
05563 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
05564 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
05565
05566 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
05567 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
05568
05569 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05570 temp16blen, temp16b, temp32a);
05571 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05572 temp32alen, temp32a, temp48);
05573 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05574 temp48, finother);
05575 finswap = finnow; finnow = finother; finother = finswap;
05576 }
05577 if (cdytail != 0.0) {
05578 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
05579 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
05580 temp16a);
05581
05582 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
05583 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
05584
05585 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
05586 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
05587
05588 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05589 temp16blen, temp16b, temp32a);
05590 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05591 temp32alen, temp32a, temp48);
05592 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05593 temp48, finother);
05594 finswap = finnow; finnow = finother; finother = finswap;
05595 }
05596
05597 if ((adxtail != 0.0) || (adytail != 0.0)) {
05598 if ((bdxtail != 0.0) || (bdytail != 0.0)
05599 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05600 Two_Product(bdxtail, cdy, ti1, ti0);
05601 Two_Product(bdx, cdytail, tj1, tj0);
05602 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05603 u[3] = u3;
05604 negate = -bdy;
05605 Two_Product(cdxtail, negate, ti1, ti0);
05606 negate = -bdytail;
05607 Two_Product(cdx, negate, tj1, tj0);
05608 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05609 v[3] = v3;
05610 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
05611
05612 Two_Product(bdxtail, cdytail, ti1, ti0);
05613 Two_Product(cdxtail, bdytail, tj1, tj0);
05614 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
05615 bctt[3] = bctt3;
05616 bcttlen = 4;
05617 } else {
05618 bct[0] = 0.0;
05619 bctlen = 1;
05620 bctt[0] = 0.0;
05621 bcttlen = 1;
05622 }
05623
05624 if (adxtail != 0.0) {
05625 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
05626 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
05627 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
05628 temp32a);
05629 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05630 temp32alen, temp32a, temp48);
05631 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05632 temp48, finother);
05633 finswap = finnow; finnow = finother; finother = finswap;
05634 if (bdytail != 0.0) {
05635 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
05636 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05637 temp16a);
05638 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05639 temp16a, finother);
05640 finswap = finnow; finnow = finother; finother = finswap;
05641 }
05642 if (cdytail != 0.0) {
05643 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
05644 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05645 temp16a);
05646 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05647 temp16a, finother);
05648 finswap = finnow; finnow = finother; finother = finswap;
05649 }
05650
05651 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
05652 temp32a);
05653 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
05654 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
05655 temp16a);
05656 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
05657 temp16b);
05658 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05659 temp16blen, temp16b, temp32b);
05660 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05661 temp32blen, temp32b, temp64);
05662 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05663 temp64, finother);
05664 finswap = finnow; finnow = finother; finother = finswap;
05665 }
05666 if (adytail != 0.0) {
05667 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
05668 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
05669 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
05670 temp32a);
05671 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05672 temp32alen, temp32a, temp48);
05673 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05674 temp48, finother);
05675 finswap = finnow; finnow = finother; finother = finswap;
05676
05677
05678 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
05679 temp32a);
05680 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
05681 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
05682 temp16a);
05683 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
05684 temp16b);
05685 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05686 temp16blen, temp16b, temp32b);
05687 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05688 temp32blen, temp32b, temp64);
05689 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05690 temp64, finother);
05691 finswap = finnow; finnow = finother; finother = finswap;
05692 }
05693 }
05694 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
05695 if ((cdxtail != 0.0) || (cdytail != 0.0)
05696 || (adxtail != 0.0) || (adytail != 0.0)) {
05697 Two_Product(cdxtail, ady, ti1, ti0);
05698 Two_Product(cdx, adytail, tj1, tj0);
05699 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05700 u[3] = u3;
05701 negate = -cdy;
05702 Two_Product(adxtail, negate, ti1, ti0);
05703 negate = -cdytail;
05704 Two_Product(adx, negate, tj1, tj0);
05705 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05706 v[3] = v3;
05707 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
05708
05709 Two_Product(cdxtail, adytail, ti1, ti0);
05710 Two_Product(adxtail, cdytail, tj1, tj0);
05711 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
05712 catt[3] = catt3;
05713 cattlen = 4;
05714 } else {
05715 cat[0] = 0.0;
05716 catlen = 1;
05717 catt[0] = 0.0;
05718 cattlen = 1;
05719 }
05720
05721 if (bdxtail != 0.0) {
05722 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
05723 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
05724 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
05725 temp32a);
05726 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05727 temp32alen, temp32a, temp48);
05728 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05729 temp48, finother);
05730 finswap = finnow; finnow = finother; finother = finswap;
05731 if (cdytail != 0.0) {
05732 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
05733 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05734 temp16a);
05735 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05736 temp16a, finother);
05737 finswap = finnow; finnow = finother; finother = finswap;
05738 }
05739 if (adytail != 0.0) {
05740 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
05741 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05742 temp16a);
05743 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05744 temp16a, finother);
05745 finswap = finnow; finnow = finother; finother = finswap;
05746 }
05747
05748 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
05749 temp32a);
05750 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
05751 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
05752 temp16a);
05753 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
05754 temp16b);
05755 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05756 temp16blen, temp16b, temp32b);
05757 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05758 temp32blen, temp32b, temp64);
05759 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05760 temp64, finother);
05761 finswap = finnow; finnow = finother; finother = finswap;
05762 }
05763 if (bdytail != 0.0) {
05764 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
05765 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
05766 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
05767 temp32a);
05768 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05769 temp32alen, temp32a, temp48);
05770 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05771 temp48, finother);
05772 finswap = finnow; finnow = finother; finother = finswap;
05773
05774
05775 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
05776 temp32a);
05777 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
05778 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
05779 temp16a);
05780 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
05781 temp16b);
05782 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05783 temp16blen, temp16b, temp32b);
05784 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05785 temp32blen, temp32b, temp64);
05786 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05787 temp64, finother);
05788 finswap = finnow; finnow = finother; finother = finswap;
05789 }
05790 }
05791 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
05792 if ((adxtail != 0.0) || (adytail != 0.0)
05793 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05794 Two_Product(adxtail, bdy, ti1, ti0);
05795 Two_Product(adx, bdytail, tj1, tj0);
05796 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05797 u[3] = u3;
05798 negate = -ady;
05799 Two_Product(bdxtail, negate, ti1, ti0);
05800 negate = -adytail;
05801 Two_Product(bdx, negate, tj1, tj0);
05802 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05803 v[3] = v3;
05804 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
05805
05806 Two_Product(adxtail, bdytail, ti1, ti0);
05807 Two_Product(bdxtail, adytail, tj1, tj0);
05808 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
05809 abtt[3] = abtt3;
05810 abttlen = 4;
05811 } else {
05812 abt[0] = 0.0;
05813 abtlen = 1;
05814 abtt[0] = 0.0;
05815 abttlen = 1;
05816 }
05817
05818 if (cdxtail != 0.0) {
05819 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
05820 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
05821 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
05822 temp32a);
05823 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05824 temp32alen, temp32a, temp48);
05825 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05826 temp48, finother);
05827 finswap = finnow; finnow = finother; finother = finswap;
05828 if (adytail != 0.0) {
05829 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
05830 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05831 temp16a);
05832 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05833 temp16a, finother);
05834 finswap = finnow; finnow = finother; finother = finswap;
05835 }
05836 if (bdytail != 0.0) {
05837 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
05838 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05839 temp16a);
05840 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05841 temp16a, finother);
05842 finswap = finnow; finnow = finother; finother = finswap;
05843 }
05844
05845 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
05846 temp32a);
05847 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
05848 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
05849 temp16a);
05850 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
05851 temp16b);
05852 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05853 temp16blen, temp16b, temp32b);
05854 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05855 temp32blen, temp32b, temp64);
05856 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05857 temp64, finother);
05858 finswap = finnow; finnow = finother; finother = finswap;
05859 }
05860 if (cdytail != 0.0) {
05861 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
05862 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
05863 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
05864 temp32a);
05865 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05866 temp32alen, temp32a, temp48);
05867 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05868 temp48, finother);
05869 finswap = finnow; finnow = finother; finother = finswap;
05870
05871
05872 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
05873 temp32a);
05874 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
05875 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
05876 temp16a);
05877 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
05878 temp16b);
05879 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05880 temp16blen, temp16b, temp32b);
05881 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05882 temp32blen, temp32b, temp64);
05883 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05884 temp64, finother);
05885 finswap = finnow; finnow = finother; finother = finswap;
05886 }
05887 }
05888
05889 return finnow[finlength - 1];
05890 }
05891
05892 #ifdef ANSI_DECLARATORS
05893 REAL incircle(struct mesh *m, struct behavior *b,
05894 vertex pa, vertex pb, vertex pc, vertex pd)
05895 #else
05896 REAL incircle(m, b, pa, pb, pc, pd)
05897 struct mesh *m;
05898 struct behavior *b;
05899 vertex pa;
05900 vertex pb;
05901 vertex pc;
05902 vertex pd;
05903 #endif
05904
05905 {
05906 REAL adx, bdx, cdx, ady, bdy, cdy;
05907 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
05908 REAL alift, blift, clift;
05909 REAL det;
05910 REAL permanent, errbound;
05911
05912 m->incirclecount++;
05913
05914 adx = pa[0] - pd[0];
05915 bdx = pb[0] - pd[0];
05916 cdx = pc[0] - pd[0];
05917 ady = pa[1] - pd[1];
05918 bdy = pb[1] - pd[1];
05919 cdy = pc[1] - pd[1];
05920
05921 bdxcdy = bdx * cdy;
05922 cdxbdy = cdx * bdy;
05923 alift = adx * adx + ady * ady;
05924
05925 cdxady = cdx * ady;
05926 adxcdy = adx * cdy;
05927 blift = bdx * bdx + bdy * bdy;
05928
05929 adxbdy = adx * bdy;
05930 bdxady = bdx * ady;
05931 clift = cdx * cdx + cdy * cdy;
05932
05933 det = alift * (bdxcdy - cdxbdy)
05934 + blift * (cdxady - adxcdy)
05935 + clift * (adxbdy - bdxady);
05936
05937 if (b->noexact) {
05938 return det;
05939 }
05940
05941 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
05942 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
05943 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
05944 errbound = iccerrboundA * permanent;
05945 if ((det > errbound) || (-det > errbound)) {
05946 return det;
05947 }
05948
05949 return incircleadapt(pa, pb, pc, pd, permanent);
05950 }
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973
05974 #ifdef ANSI_DECLARATORS
05975 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
05976 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
05977 REAL permanent)
05978 #else
05979 REAL orient3dadapt(pa, pb, pc, pd,
05980 aheight, bheight, cheight, dheight, permanent)
05981 vertex pa;
05982 vertex pb;
05983 vertex pc;
05984 vertex pd;
05985 REAL aheight;
05986 REAL bheight;
05987 REAL cheight;
05988 REAL dheight;
05989 REAL permanent;
05990 #endif
05991
05992 {
05993 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
05994 REAL det, errbound;
05995
05996 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05997 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05998 REAL bc[4], ca[4], ab[4];
05999 INEXACT REAL bc3, ca3, ab3;
06000 REAL adet[8], bdet[8], cdet[8];
06001 int alen, blen, clen;
06002 REAL abdet[16];
06003 int ablen;
06004 REAL *finnow, *finother, *finswap;
06005 REAL fin1[192], fin2[192];
06006 int finlength;
06007
06008 REAL adxtail, bdxtail, cdxtail;
06009 REAL adytail, bdytail, cdytail;
06010 REAL adheighttail, bdheighttail, cdheighttail;
06011 INEXACT REAL at_blarge, at_clarge;
06012 INEXACT REAL bt_clarge, bt_alarge;
06013 INEXACT REAL ct_alarge, ct_blarge;
06014 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
06015 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
06016 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
06017 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
06018 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
06019 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
06020 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
06021 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
06022 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
06023 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
06024 REAL bct[8], cat[8], abt[8];
06025 int bctlen, catlen, abtlen;
06026 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
06027 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
06028 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
06029 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
06030 REAL u[4], v[12], w[16];
06031 INEXACT REAL u3;
06032 int vlength, wlength;
06033 REAL negate;
06034
06035 INEXACT REAL bvirt;
06036 REAL avirt, bround, around;
06037 INEXACT REAL c;
06038 INEXACT REAL abig;
06039 REAL ahi, alo, bhi, blo;
06040 REAL err1, err2, err3;
06041 INEXACT REAL _i, _j, _k;
06042 REAL _0;
06043
06044 adx = (REAL) (pa[0] - pd[0]);
06045 bdx = (REAL) (pb[0] - pd[0]);
06046 cdx = (REAL) (pc[0] - pd[0]);
06047 ady = (REAL) (pa[1] - pd[1]);
06048 bdy = (REAL) (pb[1] - pd[1]);
06049 cdy = (REAL) (pc[1] - pd[1]);
06050 adheight = (REAL) (aheight - dheight);
06051 bdheight = (REAL) (bheight - dheight);
06052 cdheight = (REAL) (cheight - dheight);
06053
06054 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
06055 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
06056 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
06057 bc[3] = bc3;
06058 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
06059
06060 Two_Product(cdx, ady, cdxady1, cdxady0);
06061 Two_Product(adx, cdy, adxcdy1, adxcdy0);
06062 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
06063 ca[3] = ca3;
06064 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
06065
06066 Two_Product(adx, bdy, adxbdy1, adxbdy0);
06067 Two_Product(bdx, ady, bdxady1, bdxady0);
06068 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
06069 ab[3] = ab3;
06070 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
06071
06072 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
06073 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
06074
06075 det = estimate(finlength, fin1);
06076 errbound = o3derrboundB * permanent;
06077 if ((det >= errbound) || (-det >= errbound)) {
06078 return det;
06079 }
06080
06081 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
06082 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
06083 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
06084 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
06085 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
06086 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
06087 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
06088 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
06089 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
06090
06091 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
06092 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
06093 (adheighttail == 0.0) &&
06094 (bdheighttail == 0.0) &&
06095 (cdheighttail == 0.0)) {
06096 return det;
06097 }
06098
06099 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
06100 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
06101 (bdy * cdxtail + cdx * bdytail)) +
06102 adheighttail * (bdx * cdy - bdy * cdx)) +
06103 (bdheight * ((cdx * adytail + ady * cdxtail) -
06104 (cdy * adxtail + adx * cdytail)) +
06105 bdheighttail * (cdx * ady - cdy * adx)) +
06106 (cdheight * ((adx * bdytail + bdy * adxtail) -
06107 (ady * bdxtail + bdx * adytail)) +
06108 cdheighttail * (adx * bdy - ady * bdx));
06109 if ((det >= errbound) || (-det >= errbound)) {
06110 return det;
06111 }
06112
06113 finnow = fin1;
06114 finother = fin2;
06115
06116 if (adxtail == 0.0) {
06117 if (adytail == 0.0) {
06118 at_b[0] = 0.0;
06119 at_blen = 1;
06120 at_c[0] = 0.0;
06121 at_clen = 1;
06122 } else {
06123 negate = -adytail;
06124 Two_Product(negate, bdx, at_blarge, at_b[0]);
06125 at_b[1] = at_blarge;
06126 at_blen = 2;
06127 Two_Product(adytail, cdx, at_clarge, at_c[0]);
06128 at_c[1] = at_clarge;
06129 at_clen = 2;
06130 }
06131 } else {
06132 if (adytail == 0.0) {
06133 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
06134 at_b[1] = at_blarge;
06135 at_blen = 2;
06136 negate = -adxtail;
06137 Two_Product(negate, cdy, at_clarge, at_c[0]);
06138 at_c[1] = at_clarge;
06139 at_clen = 2;
06140 } else {
06141 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
06142 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
06143 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
06144 at_blarge, at_b[2], at_b[1], at_b[0]);
06145 at_b[3] = at_blarge;
06146 at_blen = 4;
06147 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
06148 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
06149 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
06150 at_clarge, at_c[2], at_c[1], at_c[0]);
06151 at_c[3] = at_clarge;
06152 at_clen = 4;
06153 }
06154 }
06155 if (bdxtail == 0.0) {
06156 if (bdytail == 0.0) {
06157 bt_c[0] = 0.0;
06158 bt_clen = 1;
06159 bt_a[0] = 0.0;
06160 bt_alen = 1;
06161 } else {
06162 negate = -bdytail;
06163 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
06164 bt_c[1] = bt_clarge;
06165 bt_clen = 2;
06166 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
06167 bt_a[1] = bt_alarge;
06168 bt_alen = 2;
06169 }
06170 } else {
06171 if (bdytail == 0.0) {
06172 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
06173 bt_c[1] = bt_clarge;
06174 bt_clen = 2;
06175 negate = -bdxtail;
06176 Two_Product(negate, ady, bt_alarge, bt_a[0]);
06177 bt_a[1] = bt_alarge;
06178 bt_alen = 2;
06179 } else {
06180 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
06181 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
06182 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
06183 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
06184 bt_c[3] = bt_clarge;
06185 bt_clen = 4;
06186 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
06187 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
06188 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
06189 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
06190 bt_a[3] = bt_alarge;
06191 bt_alen = 4;
06192 }
06193 }
06194 if (cdxtail == 0.0) {
06195 if (cdytail == 0.0) {
06196 ct_a[0] = 0.0;
06197 ct_alen = 1;
06198 ct_b[0] = 0.0;
06199 ct_blen = 1;
06200 } else {
06201 negate = -cdytail;
06202 Two_Product(negate, adx, ct_alarge, ct_a[0]);
06203 ct_a[1] = ct_alarge;
06204 ct_alen = 2;
06205 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
06206 ct_b[1] = ct_blarge;
06207 ct_blen = 2;
06208 }
06209 } else {
06210 if (cdytail == 0.0) {
06211 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
06212 ct_a[1] = ct_alarge;
06213 ct_alen = 2;
06214 negate = -cdxtail;
06215 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
06216 ct_b[1] = ct_blarge;
06217 ct_blen = 2;
06218 } else {
06219 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
06220 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
06221 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
06222 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
06223 ct_a[3] = ct_alarge;
06224 ct_alen = 4;
06225 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
06226 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
06227 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
06228 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
06229 ct_b[3] = ct_blarge;
06230 ct_blen = 4;
06231 }
06232 }
06233
06234 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
06235 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
06236 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06237 finother);
06238 finswap = finnow; finnow = finother; finother = finswap;
06239
06240 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
06241 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
06242 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06243 finother);
06244 finswap = finnow; finnow = finother; finother = finswap;
06245
06246 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
06247 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
06248 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06249 finother);
06250 finswap = finnow; finnow = finother; finother = finswap;
06251
06252 if (adheighttail != 0.0) {
06253 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
06254 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06255 finother);
06256 finswap = finnow; finnow = finother; finother = finswap;
06257 }
06258 if (bdheighttail != 0.0) {
06259 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
06260 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06261 finother);
06262 finswap = finnow; finnow = finother; finother = finswap;
06263 }
06264 if (cdheighttail != 0.0) {
06265 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
06266 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06267 finother);
06268 finswap = finnow; finnow = finother; finother = finswap;
06269 }
06270
06271 if (adxtail != 0.0) {
06272 if (bdytail != 0.0) {
06273 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
06274 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
06275 u[3] = u3;
06276 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06277 finother);
06278 finswap = finnow; finnow = finother; finother = finswap;
06279 if (cdheighttail != 0.0) {
06280 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
06281 u3, u[2], u[1], u[0]);
06282 u[3] = u3;
06283 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06284 finother);
06285 finswap = finnow; finnow = finother; finother = finswap;
06286 }
06287 }
06288 if (cdytail != 0.0) {
06289 negate = -adxtail;
06290 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
06291 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
06292 u[3] = u3;
06293 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06294 finother);
06295 finswap = finnow; finnow = finother; finother = finswap;
06296 if (bdheighttail != 0.0) {
06297 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
06298 u3, u[2], u[1], u[0]);
06299 u[3] = u3;
06300 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06301 finother);
06302 finswap = finnow; finnow = finother; finother = finswap;
06303 }
06304 }
06305 }
06306 if (bdxtail != 0.0) {
06307 if (cdytail != 0.0) {
06308 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
06309 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
06310 u[3] = u3;
06311 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06312 finother);
06313 finswap = finnow; finnow = finother; finother = finswap;
06314 if (adheighttail != 0.0) {
06315 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
06316 u3, u[2], u[1], u[0]);
06317 u[3] = u3;
06318 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06319 finother);
06320 finswap = finnow; finnow = finother; finother = finswap;
06321 }
06322 }
06323 if (adytail != 0.0) {
06324 negate = -bdxtail;
06325 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
06326 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
06327 u[3] = u3;
06328 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06329 finother);
06330 finswap = finnow; finnow = finother; finother = finswap;
06331 if (cdheighttail != 0.0) {
06332 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
06333 u3, u[2], u[1], u[0]);
06334 u[3] = u3;
06335 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06336 finother);
06337 finswap = finnow; finnow = finother; finother = finswap;
06338 }
06339 }
06340 }
06341 if (cdxtail != 0.0) {
06342 if (adytail != 0.0) {
06343 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
06344 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
06345 u[3] = u3;
06346 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06347 finother);
06348 finswap = finnow; finnow = finother; finother = finswap;
06349 if (bdheighttail != 0.0) {
06350 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
06351 u3, u[2], u[1], u[0]);
06352 u[3] = u3;
06353 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06354 finother);
06355 finswap = finnow; finnow = finother; finother = finswap;
06356 }
06357 }
06358 if (bdytail != 0.0) {
06359 negate = -cdxtail;
06360 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
06361 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
06362 u[3] = u3;
06363 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06364 finother);
06365 finswap = finnow; finnow = finother; finother = finswap;
06366 if (adheighttail != 0.0) {
06367 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
06368 u3, u[2], u[1], u[0]);
06369 u[3] = u3;
06370 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06371 finother);
06372 finswap = finnow; finnow = finother; finother = finswap;
06373 }
06374 }
06375 }
06376
06377 if (adheighttail != 0.0) {
06378 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
06379 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06380 finother);
06381 finswap = finnow; finnow = finother; finother = finswap;
06382 }
06383 if (bdheighttail != 0.0) {
06384 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
06385 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06386 finother);
06387 finswap = finnow; finnow = finother; finother = finswap;
06388 }
06389 if (cdheighttail != 0.0) {
06390 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
06391 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06392 finother);
06393 finswap = finnow; finnow = finother; finother = finswap;
06394 }
06395
06396 return finnow[finlength - 1];
06397 }
06398
06399 #ifdef ANSI_DECLARATORS
06400 REAL orient3d(struct mesh *m, struct behavior *b,
06401 vertex pa, vertex pb, vertex pc, vertex pd,
06402 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
06403 #else
06404 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
06405 struct mesh *m;
06406 struct behavior *b;
06407 vertex pa;
06408 vertex pb;
06409 vertex pc;
06410 vertex pd;
06411 REAL aheight;
06412 REAL bheight;
06413 REAL cheight;
06414 REAL dheight;
06415 #endif
06416
06417 {
06418 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06419 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
06420 REAL det;
06421 REAL permanent, errbound;
06422
06423 m->orient3dcount++;
06424
06425 adx = pa[0] - pd[0];
06426 bdx = pb[0] - pd[0];
06427 cdx = pc[0] - pd[0];
06428 ady = pa[1] - pd[1];
06429 bdy = pb[1] - pd[1];
06430 cdy = pc[1] - pd[1];
06431 adheight = aheight - dheight;
06432 bdheight = bheight - dheight;
06433 cdheight = cheight - dheight;
06434
06435 bdxcdy = bdx * cdy;
06436 cdxbdy = cdx * bdy;
06437
06438 cdxady = cdx * ady;
06439 adxcdy = adx * cdy;
06440
06441 adxbdy = adx * bdy;
06442 bdxady = bdx * ady;
06443
06444 det = adheight * (bdxcdy - cdxbdy)
06445 + bdheight * (cdxady - adxcdy)
06446 + cdheight * (adxbdy - bdxady);
06447
06448 if (b->noexact) {
06449 return det;
06450 }
06451
06452 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
06453 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
06454 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
06455 errbound = o3derrboundA * permanent;
06456 if ((det > errbound) || (-det > errbound)) {
06457 return det;
06458 }
06459
06460 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
06461 permanent);
06462 }
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482 #ifdef ANSI_DECLARATORS
06483 REAL nonregular(struct mesh *m, struct behavior *b,
06484 vertex pa, vertex pb, vertex pc, vertex pd)
06485 #else
06486 REAL nonregular(m, b, pa, pb, pc, pd)
06487 struct mesh *m;
06488 struct behavior *b;
06489 vertex pa;
06490 vertex pb;
06491 vertex pc;
06492 vertex pd;
06493 #endif
06494
06495 {
06496 if (b->weighted == 0) {
06497 return incircle(m, b, pa, pb, pc, pd);
06498 } else if (b->weighted == 1) {
06499 return orient3d(m, b, pa, pb, pc, pd,
06500 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
06501 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
06502 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
06503 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
06504 } else {
06505 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
06506 }
06507 }
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517
06518
06519
06520
06521
06522
06523 #ifdef ANSI_DECLARATORS
06524 void findcircumcenter(struct mesh *m, struct behavior *b,
06525 vertex torg, vertex tdest, vertex tapex,
06526 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
06527 #else
06528 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
06529 offcenter)
06530 struct mesh *m;
06531 struct behavior *b;
06532 vertex torg;
06533 vertex tdest;
06534 vertex tapex;
06535 vertex circumcenter;
06536 REAL *xi;
06537 REAL *eta;
06538 int offcenter;
06539 #endif
06540
06541 {
06542 REAL xdo, ydo, xao, yao;
06543 REAL dodist, aodist, dadist;
06544 REAL denominator;
06545 REAL dx, dy, dxoff, dyoff;
06546
06547 m->circumcentercount++;
06548
06549
06550 xdo = tdest[0] - torg[0];
06551 ydo = tdest[1] - torg[1];
06552 xao = tapex[0] - torg[0];
06553 yao = tapex[1] - torg[1];
06554 dodist = xdo * xdo + ydo * ydo;
06555 aodist = xao * xao + yao * yao;
06556 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
06557 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
06558 if (b->noexact) {
06559 denominator = 0.5 / (xdo * yao - xao * ydo);
06560 } else {
06561
06562
06563
06564 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
06565
06566 m->counterclockcount--;
06567 }
06568 dx = (yao * dodist - ydo * aodist) * denominator;
06569 dy = (xdo * aodist - xao * dodist) * denominator;
06570
06571
06572
06573
06574
06575
06576 if ((dodist < aodist) && (dodist < dadist)) {
06577 if (offcenter && (b->offconstant > 0.0)) {
06578
06579 dxoff = 0.5 * xdo - b->offconstant * ydo;
06580 dyoff = 0.5 * ydo + b->offconstant * xdo;
06581
06582
06583 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06584 dx = dxoff;
06585 dy = dyoff;
06586 }
06587 }
06588 } else if (aodist < dadist) {
06589 if (offcenter && (b->offconstant > 0.0)) {
06590 dxoff = 0.5 * xao + b->offconstant * yao;
06591 dyoff = 0.5 * yao - b->offconstant * xao;
06592
06593
06594 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06595 dx = dxoff;
06596 dy = dyoff;
06597 }
06598 }
06599 } else {
06600 if (offcenter && (b->offconstant > 0.0)) {
06601 dxoff = 0.5 * (tapex[0] - tdest[0]) -
06602 b->offconstant * (tapex[1] - tdest[1]);
06603 dyoff = 0.5 * (tapex[1] - tdest[1]) +
06604 b->offconstant * (tapex[0] - tdest[0]);
06605
06606
06607 if (dxoff * dxoff + dyoff * dyoff <
06608 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
06609 dx = xdo + dxoff;
06610 dy = ydo + dyoff;
06611 }
06612 }
06613 }
06614
06615 circumcenter[0] = torg[0] + dx;
06616 circumcenter[1] = torg[1] + dy;
06617
06618
06619
06620
06621
06622
06623 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
06624 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
06625 }
06626
06629
06630
06631
06632
06633
06634
06635
06636
06637 #ifdef ANSI_DECLARATORS
06638 void triangleinit(struct mesh *m)
06639 #else
06640 void triangleinit(m)
06641 struct mesh *m;
06642 #endif
06643
06644 {
06645 poolzero(&m->vertices);
06646 poolzero(&m->triangles);
06647 poolzero(&m->subsegs);
06648 poolzero(&m->viri);
06649 poolzero(&m->badsubsegs);
06650 poolzero(&m->badtriangles);
06651 poolzero(&m->flipstackers);
06652 poolzero(&m->splaynodes);
06653
06654 m->recenttri.tri = (triangle *) NULL;
06655 m->undeads = 0;
06656 m->samples = 1;
06657 m->checksegments = 0;
06658 m->checkquality = 0;
06659 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
06660 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
06661 randomseed = 1;
06662
06663 exactinit();
06664 }
06665
06666
06667
06668
06669
06670
06671
06672
06673
06674
06675
06676 #ifdef ANSI_DECLARATORS
06677 unsigned long randomnation(unsigned int choices)
06678 #else
06679 unsigned long randomnation(choices)
06680 unsigned int choices;
06681 #endif
06682
06683 {
06684 randomseed = (randomseed * 1366l + 150889l) % 714025l;
06685 return randomseed / (714025l / choices + 1);
06686 }
06687
06688
06692
06693
06694
06695
06696
06697
06698 #ifndef REDUCED
06699
06700 #ifdef ANSI_DECLARATORS
06701 void checkmesh(struct mesh *m, struct behavior *b)
06702 #else
06703 void checkmesh(m, b)
06704 struct mesh *m;
06705 struct behavior *b;
06706 #endif
06707
06708 {
06709 struct otri triangleloop;
06710 struct otri oppotri, oppooppotri;
06711 vertex triorg, tridest, triapex;
06712 vertex oppoorg, oppodest;
06713 int horrors;
06714 int saveexact;
06715 triangle ptr;
06716
06717
06718 saveexact = b->noexact;
06719 b->noexact = 0;
06720 if (!b->quiet) {
06721 printf(" Checking consistency of mesh...\n");
06722 }
06723 horrors = 0;
06724
06725 traversalinit(&m->triangles);
06726 triangleloop.tri = triangletraverse(m);
06727 while (triangleloop.tri != (triangle *) NULL) {
06728
06729 for (triangleloop.orient = 0; triangleloop.orient < 3;
06730 triangleloop.orient++) {
06731 org(triangleloop, triorg);
06732 dest(triangleloop, tridest);
06733 if (triangleloop.orient == 0) {
06734
06735 apex(triangleloop, triapex);
06736 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
06737 printf(" !! !! Inverted ");
06738 printtriangle(m, b, &triangleloop);
06739 horrors++;
06740 }
06741 }
06742
06743 sym(triangleloop, oppotri);
06744 if (oppotri.tri != m->dummytri) {
06745
06746 sym(oppotri, oppooppotri);
06747 if ((triangleloop.tri != oppooppotri.tri)
06748 || (triangleloop.orient != oppooppotri.orient)) {
06749 printf(" !! !! Asymmetric triangle-triangle bond:\n");
06750 if (triangleloop.tri == oppooppotri.tri) {
06751 printf(" (Right triangle, wrong orientation)\n");
06752 }
06753 printf(" First ");
06754 printtriangle(m, b, &triangleloop);
06755 printf(" Second (nonreciprocating) ");
06756 printtriangle(m, b, &oppotri);
06757 horrors++;
06758 }
06759
06760
06761 org(oppotri, oppoorg);
06762 dest(oppotri, oppodest);
06763 if ((triorg != oppodest) || (tridest != oppoorg)) {
06764 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
06765 );
06766 printf(" First mismatched ");
06767 printtriangle(m, b, &triangleloop);
06768 printf(" Second mismatched ");
06769 printtriangle(m, b, &oppotri);
06770 horrors++;
06771 }
06772 }
06773 }
06774 triangleloop.tri = triangletraverse(m);
06775 }
06776 if (horrors == 0) {
06777 if (!b->quiet) {
06778 printf(" In my studied opinion, the mesh appears to be consistent.\n");
06779 }
06780 } else if (horrors == 1) {
06781 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
06782 } else {
06783 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
06784 }
06785
06786 b->noexact = saveexact;
06787 }
06788
06789 #endif
06790
06791
06792
06793
06794
06795
06796
06797 #ifndef REDUCED
06798
06799 #ifdef ANSI_DECLARATORS
06800 void checkdelaunay(struct mesh *m, struct behavior *b)
06801 #else
06802 void checkdelaunay(m, b)
06803 struct mesh *m;
06804 struct behavior *b;
06805 #endif
06806
06807 {
06808 struct otri triangleloop;
06809 struct otri oppotri;
06810 struct osub opposubseg;
06811 vertex triorg, tridest, triapex;
06812 vertex oppoapex;
06813 int shouldbedelaunay;
06814 int horrors;
06815 int saveexact;
06816 triangle ptr;
06817 subseg sptr;
06818
06819
06820 saveexact = b->noexact;
06821 b->noexact = 0;
06822 if (!b->quiet) {
06823 printf(" Checking Delaunay property of mesh...\n");
06824 }
06825 horrors = 0;
06826
06827 traversalinit(&m->triangles);
06828 triangleloop.tri = triangletraverse(m);
06829 while (triangleloop.tri != (triangle *) NULL) {
06830
06831 for (triangleloop.orient = 0; triangleloop.orient < 3;
06832 triangleloop.orient++) {
06833 org(triangleloop, triorg);
06834 dest(triangleloop, tridest);
06835 apex(triangleloop, triapex);
06836 sym(triangleloop, oppotri);
06837 apex(oppotri, oppoapex);
06838
06839
06840
06841 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
06842 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
06843 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
06844 (triorg != m->infvertex3) &&
06845 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
06846 (tridest != m->infvertex3) &&
06847 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
06848 (triapex != m->infvertex3) &&
06849 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
06850 (oppoapex != m->infvertex3);
06851 if (m->checksegments && shouldbedelaunay) {
06852
06853
06854 tspivot(triangleloop, opposubseg);
06855 if (opposubseg.ss != m->dummysub){
06856 shouldbedelaunay = 0;
06857 }
06858 }
06859 if (shouldbedelaunay) {
06860 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
06861 if (!b->weighted) {
06862 printf(" !! !! Non-Delaunay pair of triangles:\n");
06863 printf(" First non-Delaunay ");
06864 printtriangle(m, b, &triangleloop);
06865 printf(" Second non-Delaunay ");
06866 } else {
06867 printf(" !! !! Non-regular pair of triangles:\n");
06868 printf(" First non-regular ");
06869 printtriangle(m, b, &triangleloop);
06870 printf(" Second non-regular ");
06871 }
06872 printtriangle(m, b, &oppotri);
06873 horrors++;
06874 }
06875 }
06876 }
06877 triangleloop.tri = triangletraverse(m);
06878 }
06879 if (horrors == 0) {
06880 if (!b->quiet) {
06881 printf(
06882 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
06883 }
06884 } else if (horrors == 1) {
06885 printf(
06886 " !! !! !! !! Precisely one terrifying transgression identified.\n");
06887 } else {
06888 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
06889 }
06890
06891 b->noexact = saveexact;
06892 }
06893
06894 #endif
06895
06896
06897
06898
06899
06900
06901
06902
06903
06904
06905
06906
06907 #ifndef CDT_ONLY
06908
06909 #ifdef ANSI_DECLARATORS
06910 void enqueuebadtriang(struct mesh *m, struct behavior *b,
06911 struct badtriang *badtri)
06912 #else
06913 void enqueuebadtriang(m, b, badtri)
06914 struct mesh *m;
06915 struct behavior *b;
06916 struct badtriang *badtri;
06917 #endif
06918
06919 {
06920 REAL length, multiplier;
06921 int exponent, expincrement;
06922 int queuenumber;
06923 int posexponent;
06924 int i;
06925
06926 if (b->verbose > 2) {
06927 printf(" Queueing bad triangle:\n");
06928 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
06929 badtri->triangorg[0], badtri->triangorg[1],
06930 badtri->triangdest[0], badtri->triangdest[1],
06931 badtri->triangapex[0], badtri->triangapex[1]);
06932 }
06933
06934
06935
06936 if (badtri->key >= 1.0) {
06937 length = badtri->key;
06938 posexponent = 1;
06939 } else {
06940
06941
06942 length = 1.0 / badtri->key;
06943 posexponent = 0;
06944 }
06945
06946
06947 exponent = 0;
06948 while (length > 2.0) {
06949
06950 expincrement = 1;
06951 multiplier = 0.5;
06952 while (length * multiplier * multiplier > 1.0) {
06953 expincrement *= 2;
06954 multiplier *= multiplier;
06955 }
06956
06957 exponent += expincrement;
06958 length *= multiplier;
06959 }
06960
06961 exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
06962
06963
06964
06965 if (posexponent) {
06966 queuenumber = 2047 - exponent;
06967 } else {
06968 queuenumber = 2048 + exponent;
06969 }
06970
06971
06972 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
06973
06974
06975 if (queuenumber > m->firstnonemptyq) {
06976
06977 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
06978 m->firstnonemptyq = queuenumber;
06979 } else {
06980
06981
06982 i = queuenumber + 1;
06983 while (m->queuefront[i] == (struct badtriang *) NULL) {
06984 i++;
06985 }
06986
06987 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
06988 m->nextnonemptyq[i] = queuenumber;
06989 }
06990
06991 m->queuefront[queuenumber] = badtri;
06992 } else {
06993
06994 m->queuetail[queuenumber]->nexttriang = badtri;
06995 }
06996
06997 m->queuetail[queuenumber] = badtri;
06998
06999 badtri->nexttriang = (struct badtriang *) NULL;
07000 }
07001
07002 #endif
07003
07004
07005
07006
07007
07008
07009
07010
07011
07012
07013 #ifndef CDT_ONLY
07014
07015 #ifdef ANSI_DECLARATORS
07016 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
07017 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
07018 #else
07019 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
07020 struct mesh *m;
07021 struct behavior *b;
07022 struct otri *enqtri;
07023 REAL minedge;
07024 vertex enqapex;
07025 vertex enqorg;
07026 vertex enqdest;
07027 #endif
07028
07029 {
07030 struct badtriang *newbad;
07031
07032
07033 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
07034 newbad->poortri = encode(*enqtri);
07035 newbad->key = minedge;
07036 newbad->triangapex = enqapex;
07037 newbad->triangorg = enqorg;
07038 newbad->triangdest = enqdest;
07039 enqueuebadtriang(m, b, newbad);
07040 }
07041
07042 #endif
07043
07044
07045
07046
07047
07048
07049
07050 #ifndef CDT_ONLY
07051
07052 #ifdef ANSI_DECLARATORS
07053 struct badtriang *dequeuebadtriang(struct mesh *m)
07054 #else
07055 struct badtriang *dequeuebadtriang(m)
07056 struct mesh *m;
07057 #endif
07058
07059 {
07060 struct badtriang *result;
07061
07062
07063 if (m->firstnonemptyq < 0) {
07064 return (struct badtriang *) NULL;
07065 }
07066
07067 result = m->queuefront[m->firstnonemptyq];
07068
07069 m->queuefront[m->firstnonemptyq] = result->nexttriang;
07070
07071
07072 if (result == m->queuetail[m->firstnonemptyq]) {
07073 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
07074 }
07075 return result;
07076 }
07077
07078 #endif
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097
07098
07099
07100
07101
07102
07103 #ifndef CDT_ONLY
07104
07105 #ifdef ANSI_DECLARATORS
07106 int checkseg4encroach(struct mesh *m, struct behavior *b,
07107 struct osub *testsubseg)
07108 #else
07109 int checkseg4encroach(m, b, testsubseg)
07110 struct mesh *m;
07111 struct behavior *b;
07112 struct osub *testsubseg;
07113 #endif
07114
07115 {
07116 struct otri neighbortri;
07117 struct osub testsym;
07118 struct badsubseg *encroachedseg;
07119 REAL dotproduct;
07120 int encroached;
07121 int sides;
07122 vertex eorg, edest, eapex;
07123 triangle ptr;
07124
07125 encroached = 0;
07126 sides = 0;
07127
07128 sorg(*testsubseg, eorg);
07129 sdest(*testsubseg, edest);
07130
07131 stpivot(*testsubseg, neighbortri);
07132
07133 if (neighbortri.tri != m->dummytri) {
07134 sides++;
07135
07136 apex(neighbortri, eapex);
07137
07138
07139
07140
07141
07142 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07143 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07144 if (dotproduct < 0.0) {
07145 if (b->conformdel ||
07146 (dotproduct * dotproduct >=
07147 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07148 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07149 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07150 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07151 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07152 encroached = 1;
07153 }
07154 }
07155 }
07156
07157 ssym(*testsubseg, testsym);
07158 stpivot(testsym, neighbortri);
07159
07160 if (neighbortri.tri != m->dummytri) {
07161 sides++;
07162
07163 apex(neighbortri, eapex);
07164
07165
07166 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07167 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07168 if (dotproduct < 0.0) {
07169 if (b->conformdel ||
07170 (dotproduct * dotproduct >=
07171 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07172 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07173 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07174 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07175 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07176 encroached += 2;
07177 }
07178 }
07179 }
07180
07181 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
07182 if (b->verbose > 2) {
07183 printf(
07184 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
07185 eorg[0], eorg[1], edest[0], edest[1]);
07186 }
07187
07188
07189 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
07190 if (encroached == 1) {
07191 encroachedseg->encsubseg = sencode(*testsubseg);
07192 encroachedseg->subsegorg = eorg;
07193 encroachedseg->subsegdest = edest;
07194 } else {
07195 encroachedseg->encsubseg = sencode(testsym);
07196 encroachedseg->subsegorg = edest;
07197 encroachedseg->subsegdest = eorg;
07198 }
07199 }
07200
07201 return encroached;
07202 }
07203
07204 #endif
07205
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216 #ifndef CDT_ONLY
07217
07218 #ifdef ANSI_DECLARATORS
07219 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
07220 #else
07221 void testtriangle(m, b, testtri)
07222 struct mesh *m;
07223 struct behavior *b;
07224 struct otri *testtri;
07225 #endif
07226
07227 {
07228 struct otri tri1, tri2;
07229 struct osub testsub;
07230 vertex torg, tdest, tapex;
07231 vertex base1, base2;
07232 vertex org1, dest1, org2, dest2;
07233 vertex joinvertex;
07234 REAL dxod, dyod, dxda, dyda, dxao, dyao;
07235 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
07236 REAL apexlen, orglen, destlen, minedge;
07237 REAL angle;
07238 REAL area;
07239 REAL dist1, dist2;
07240 subseg sptr;
07241 triangle ptr;
07242
07243 org(*testtri, torg);
07244 dest(*testtri, tdest);
07245 apex(*testtri, tapex);
07246 dxod = torg[0] - tdest[0];
07247 dyod = torg[1] - tdest[1];
07248 dxda = tdest[0] - tapex[0];
07249 dyda = tdest[1] - tapex[1];
07250 dxao = tapex[0] - torg[0];
07251 dyao = tapex[1] - torg[1];
07252 dxod2 = dxod * dxod;
07253 dyod2 = dyod * dyod;
07254 dxda2 = dxda * dxda;
07255 dyda2 = dyda * dyda;
07256 dxao2 = dxao * dxao;
07257 dyao2 = dyao * dyao;
07258
07259 apexlen = dxod2 + dyod2;
07260 orglen = dxda2 + dyda2;
07261 destlen = dxao2 + dyao2;
07262
07263 if ((apexlen < orglen) && (apexlen < destlen)) {
07264
07265 minedge = apexlen;
07266
07267 angle = dxda * dxao + dyda * dyao;
07268 angle = angle * angle / (orglen * destlen);
07269 base1 = torg;
07270 base2 = tdest;
07271 otricopy(*testtri, tri1);
07272 } else if (orglen < destlen) {
07273
07274 minedge = orglen;
07275
07276 angle = dxod * dxao + dyod * dyao;
07277 angle = angle * angle / (apexlen * destlen);
07278 base1 = tdest;
07279 base2 = tapex;
07280 lnext(*testtri, tri1);
07281 } else {
07282
07283 minedge = destlen;
07284
07285 angle = dxod * dxda + dyod * dyda;
07286 angle = angle * angle / (apexlen * orglen);
07287 base1 = tapex;
07288 base2 = torg;
07289 lprev(*testtri, tri1);
07290 }
07291
07292 if (b->vararea || b->fixedarea || b->usertest) {
07293
07294 area = 0.5 * (dxod * dyda - dyod * dxda);
07295 if (b->fixedarea && (area > b->maxarea)) {
07296
07297 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07298 return;
07299 }
07300
07301
07302 if ((b->vararea) && (area > areabound(*testtri)) &&
07303 (areabound(*testtri) > 0.0)) {
07304
07305 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07306 return;
07307 }
07308
07309 if (b->usertest) {
07310
07311 if (triunsuitable(torg, tdest, tapex, area)) {
07312 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07313 return;
07314 }
07315 }
07316 }
07317
07318
07319 if (angle > b->goodangle) {
07320
07321
07322
07323
07324
07325
07326
07327
07328
07329 if ((vertextype(base1) == SEGMENTVERTEX) &&
07330 (vertextype(base2) == SEGMENTVERTEX)) {
07331
07332
07333 tspivot(tri1, testsub);
07334 if (testsub.ss == m->dummysub) {
07335
07336 otricopy(tri1, tri2);
07337 do {
07338 oprevself(tri1);
07339 tspivot(tri1, testsub);
07340 } while (testsub.ss == m->dummysub);
07341
07342 segorg(testsub, org1);
07343 segdest(testsub, dest1);
07344
07345 do {
07346 dnextself(tri2);
07347 tspivot(tri2, testsub);
07348 } while (testsub.ss == m->dummysub);
07349
07350 segorg(testsub, org2);
07351 segdest(testsub, dest2);
07352
07353 joinvertex = (vertex) NULL;
07354 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
07355 joinvertex = dest1;
07356 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
07357 joinvertex = org1;
07358 }
07359 if (joinvertex != (vertex) NULL) {
07360
07361
07362 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
07363 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
07364 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
07365 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
07366
07367 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
07368
07369 return;
07370 }
07371 }
07372 }
07373 }
07374
07375
07376 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07377 }
07378 }
07379
07380 #endif
07381
07384
07385
07386
07390
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400
07401
07402
07403
07404 #ifdef ANSI_DECLARATORS
07405 void makevertexmap(struct mesh *m, struct behavior *b)
07406 #else
07407 void makevertexmap(m, b)
07408 struct mesh *m;
07409 struct behavior *b;
07410 #endif
07411
07412 {
07413 struct otri triangleloop;
07414 vertex triorg;
07415
07416 if (b->verbose) {
07417 printf(" Constructing mapping from vertices to triangles.\n");
07418 }
07419 traversalinit(&m->triangles);
07420 triangleloop.tri = triangletraverse(m);
07421 while (triangleloop.tri != (triangle *) NULL) {
07422
07423 for (triangleloop.orient = 0; triangleloop.orient < 3;
07424 triangleloop.orient++) {
07425 org(triangleloop, triorg);
07426 setvertex2tri(triorg, encode(triangleloop));
07427 }
07428 triangleloop.tri = triangletraverse(m);
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
07496
07497
07498
07499 #ifdef ANSI_DECLARATORS
07500 enum locateresult preciselocate(struct mesh *m, struct behavior *b,
07501 vertex searchpoint, struct otri *searchtri,
07502 int stopatsubsegment)
07503 #else
07504 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
07505 struct mesh *m;
07506 struct behavior *b;
07507 vertex searchpoint;
07508 struct otri *searchtri;
07509 int stopatsubsegment;
07510 #endif
07511
07512 {
07513 struct otri backtracktri;
07514 struct osub checkedge;
07515 vertex forg, fdest, fapex;
07516 REAL orgorient, destorient;
07517 int moveleft;
07518 triangle ptr;
07519 subseg sptr;
07520
07521 if (b->verbose > 2) {
07522 printf(" Searching for point (%.12g, %.12g).\n",
07523 searchpoint[0], searchpoint[1]);
07524 }
07525
07526 org(*searchtri, forg);
07527 dest(*searchtri, fdest);
07528 apex(*searchtri, fapex);
07529 while (1) {
07530 if (b->verbose > 2) {
07531 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07532 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
07533 }
07534
07535 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
07536 lprevself(*searchtri);
07537 return ONVERTEX;
07538 }
07539
07540
07541 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
07542
07543
07544 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
07545 if (destorient > 0.0) {
07546 if (orgorient > 0.0) {
07547
07548
07549
07550
07551
07552 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
07553 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
07554 } else {
07555 moveleft = 1;
07556 }
07557 } else {
07558 if (orgorient > 0.0) {
07559 moveleft = 0;
07560 } else {
07561
07562
07563 if (destorient == 0.0) {
07564 lprevself(*searchtri);
07565 return ONEDGE;
07566 }
07567 if (orgorient == 0.0) {
07568 lnextself(*searchtri);
07569 return ONEDGE;
07570 }
07571 return INTRIANGLE;
07572 }
07573 }
07574
07575
07576
07577
07578 if (moveleft) {
07579 lprev(*searchtri, backtracktri);
07580 fdest = fapex;
07581 } else {
07582 lnext(*searchtri, backtracktri);
07583 forg = fapex;
07584 }
07585 sym(backtracktri, *searchtri);
07586
07587 if (m->checksegments && stopatsubsegment) {
07588
07589 tspivot(backtracktri, checkedge);
07590 if (checkedge.ss != m->dummysub) {
07591
07592 otricopy(backtracktri, *searchtri);
07593 return OUTSIDE;
07594 }
07595 }
07596
07597 if (searchtri->tri == m->dummytri) {
07598
07599 otricopy(backtracktri, *searchtri);
07600 return OUTSIDE;
07601 }
07602
07603 apex(*searchtri, fapex);
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
07640
07641
07642
07643 #ifdef ANSI_DECLARATORS
07644 enum locateresult locate(struct mesh *m, struct behavior *b,
07645 vertex searchpoint, struct otri *searchtri)
07646 #else
07647 enum locateresult locate(m, b, searchpoint, searchtri)
07648 struct mesh *m;
07649 struct behavior *b;
07650 vertex searchpoint;
07651 struct otri *searchtri;
07652 #endif
07653
07654 {
07655 VOID **sampleblock;
07656 char *firsttri;
07657 struct otri sampletri;
07658 vertex torg, tdest;
07659 unsigned long alignptr;
07660 REAL searchdist, dist;
07661 REAL ahead;
07662 long samplesperblock, totalsamplesleft, samplesleft;
07663 long population, totalpopulation;
07664 triangle ptr;
07665
07666 if (b->verbose > 2) {
07667 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
07668 searchpoint[0], searchpoint[1]);
07669 }
07670
07671
07672 org(*searchtri, torg);
07673 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07674 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07675 if (b->verbose > 2) {
07676 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
07677 torg[0], torg[1]);
07678 }
07679
07680
07681
07682 if (m->recenttri.tri != (triangle *) NULL) {
07683 if (!deadtri(m->recenttri.tri)) {
07684 org(m->recenttri, torg);
07685 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07686 otricopy(m->recenttri, *searchtri);
07687 return ONVERTEX;
07688 }
07689 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07690 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07691 if (dist < searchdist) {
07692 otricopy(m->recenttri, *searchtri);
07693 searchdist = dist;
07694 if (b->verbose > 2) {
07695 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
07696 torg[0], torg[1]);
07697 }
07698 }
07699 }
07700 }
07701
07702
07703
07704
07705
07706 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
07707 m->triangles.items) {
07708 m->samples++;
07709 }
07710
07711
07712
07713
07714
07715 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
07716
07717
07718 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
07719 m->triangles.maxitems + 1;
07720 totalsamplesleft = m->samples;
07721 population = m->triangles.itemsfirstblock;
07722 totalpopulation = m->triangles.maxitems;
07723 sampleblock = m->triangles.firstblock;
07724 sampletri.orient = 0;
07725 while (totalsamplesleft > 0) {
07726
07727 if (population > totalpopulation) {
07728 population = totalpopulation;
07729 }
07730
07731 alignptr = (unsigned long) (sampleblock + 1);
07732 firsttri = (char *) (alignptr +
07733 (unsigned long) m->triangles.alignbytes -
07734 (alignptr %
07735 (unsigned long) m->triangles.alignbytes));
07736
07737
07738 do {
07739 sampletri.tri = (triangle *) (firsttri +
07740 (randomnation((unsigned int) population) *
07741 m->triangles.itembytes));
07742 if (!deadtri(sampletri.tri)) {
07743 org(sampletri, torg);
07744 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07745 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07746 if (dist < searchdist) {
07747 otricopy(sampletri, *searchtri);
07748 searchdist = dist;
07749 if (b->verbose > 2) {
07750 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
07751 torg[0], torg[1]);
07752 }
07753 }
07754 }
07755
07756 samplesleft--;
07757 totalsamplesleft--;
07758 } while ((samplesleft > 0) && (totalsamplesleft > 0));
07759
07760 if (totalsamplesleft > 0) {
07761 sampleblock = (VOID **) *sampleblock;
07762 samplesleft = samplesperblock;
07763 totalpopulation -= population;
07764 population = TRIPERBLOCK;
07765 }
07766 }
07767
07768
07769 org(*searchtri, torg);
07770 dest(*searchtri, tdest);
07771
07772 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07773 return ONVERTEX;
07774 }
07775 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
07776 lnextself(*searchtri);
07777 return ONVERTEX;
07778 }
07779
07780 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
07781 if (ahead < 0.0) {
07782
07783
07784 symself(*searchtri);
07785 } else if (ahead == 0.0) {
07786
07787 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
07788 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
07789 return ONEDGE;
07790 }
07791 }
07792 return preciselocate(m, b, searchpoint, searchtri, 0);
07793 }
07794
07797
07798
07799
07803
07804
07805
07806
07807
07808
07809
07810
07811
07812
07813
07814 #ifdef ANSI_DECLARATORS
07815 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
07816 int subsegmark)
07817 #else
07818 void insertsubseg(m, b, tri, subsegmark)
07819 struct mesh *m;
07820 struct behavior *b;
07821 struct otri *tri;
07822 int subsegmark;
07823 #endif
07824
07825 {
07826 struct otri oppotri;
07827 struct osub newsubseg;
07828 vertex triorg, tridest;
07829 triangle ptr;
07830 subseg sptr;
07831
07832 org(*tri, triorg);
07833 dest(*tri, tridest);
07834
07835 if (vertexmark(triorg) == 0) {
07836 setvertexmark(triorg, subsegmark);
07837 }
07838 if (vertexmark(tridest) == 0) {
07839 setvertexmark(tridest, subsegmark);
07840 }
07841
07842 tspivot(*tri, newsubseg);
07843 if (newsubseg.ss == m->dummysub) {
07844
07845 makesubseg(m, &newsubseg);
07846 setsorg(newsubseg, tridest);
07847 setsdest(newsubseg, triorg);
07848 setsegorg(newsubseg, tridest);
07849 setsegdest(newsubseg, triorg);
07850
07851
07852
07853
07854 tsbond(*tri, newsubseg);
07855 sym(*tri, oppotri);
07856 ssymself(newsubseg);
07857 tsbond(oppotri, newsubseg);
07858 setmark(newsubseg, subsegmark);
07859 if (b->verbose > 2) {
07860 printf(" Inserting new ");
07861 printsubseg(m, b, &newsubseg);
07862 }
07863 } else {
07864 if (mark(newsubseg) == 0) {
07865 setmark(newsubseg, subsegmark);
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
07915
07916
07917
07918 #ifdef ANSI_DECLARATORS
07919 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
07920 #else
07921 void flip(m, b, flipedge)
07922 struct mesh *m;
07923 struct behavior *b;
07924 struct otri *flipedge;
07925 #endif
07926
07927 {
07928 struct otri botleft, botright;
07929 struct otri topleft, topright;
07930 struct otri top;
07931 struct otri botlcasing, botrcasing;
07932 struct otri toplcasing, toprcasing;
07933 struct osub botlsubseg, botrsubseg;
07934 struct osub toplsubseg, toprsubseg;
07935 vertex leftvertex, rightvertex, botvertex;
07936 vertex farvertex;
07937 triangle ptr;
07938 subseg sptr;
07939
07940
07941 org(*flipedge, rightvertex);
07942 dest(*flipedge, leftvertex);
07943 apex(*flipedge, botvertex);
07944 sym(*flipedge, top);
07945 #ifdef SELF_CHECK
07946 if (top.tri == m->dummytri) {
07947 printf("Internal error in flip(): Attempt to flip on boundary.\n");
07948 lnextself(*flipedge);
07949 return;
07950 }
07951 if (m->checksegments) {
07952 tspivot(*flipedge, toplsubseg);
07953 if (toplsubseg.ss != m->dummysub) {
07954 printf("Internal error in flip(): Attempt to flip a segment.\n");
07955 lnextself(*flipedge);
07956 return;
07957 }
07958 }
07959 #endif
07960 apex(top, farvertex);
07961
07962
07963 lprev(top, topleft);
07964 sym(topleft, toplcasing);
07965 lnext(top, topright);
07966 sym(topright, toprcasing);
07967 lnext(*flipedge, botleft);
07968 sym(botleft, botlcasing);
07969 lprev(*flipedge, botright);
07970 sym(botright, botrcasing);
07971
07972 bond(topleft, botlcasing);
07973 bond(botleft, botrcasing);
07974 bond(botright, toprcasing);
07975 bond(topright, toplcasing);
07976
07977 if (m->checksegments) {
07978
07979 tspivot(topleft, toplsubseg);
07980 tspivot(botleft, botlsubseg);
07981 tspivot(botright, botrsubseg);
07982 tspivot(topright, toprsubseg);
07983 if (toplsubseg.ss == m->dummysub) {
07984 tsdissolve(topright);
07985 } else {
07986 tsbond(topright, toplsubseg);
07987 }
07988 if (botlsubseg.ss == m->dummysub) {
07989 tsdissolve(topleft);
07990 } else {
07991 tsbond(topleft, botlsubseg);
07992 }
07993 if (botrsubseg.ss == m->dummysub) {
07994 tsdissolve(botleft);
07995 } else {
07996 tsbond(botleft, botrsubseg);
07997 }
07998 if (toprsubseg.ss == m->dummysub) {
07999 tsdissolve(botright);
08000 } else {
08001 tsbond(botright, toprsubseg);
08002 }
08003 }
08004
08005
08006 setorg(*flipedge, farvertex);
08007 setdest(*flipedge, botvertex);
08008 setapex(*flipedge, rightvertex);
08009 setorg(top, botvertex);
08010 setdest(top, farvertex);
08011 setapex(top, leftvertex);
08012 if (b->verbose > 2) {
08013 printf(" Edge flip results in left ");
08014 printtriangle(m, b, &top);
08015 printf(" and right ");
08016 printtriangle(m, b, flipedge);
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
08050
08051
08052
08053 #ifdef ANSI_DECLARATORS
08054 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
08055 #else
08056 void unflip(m, b, flipedge)
08057 struct mesh *m;
08058 struct behavior *b;
08059 struct otri *flipedge;
08060 #endif
08061
08062 {
08063 struct otri botleft, botright;
08064 struct otri topleft, topright;
08065 struct otri top;
08066 struct otri botlcasing, botrcasing;
08067 struct otri toplcasing, toprcasing;
08068 struct osub botlsubseg, botrsubseg;
08069 struct osub toplsubseg, toprsubseg;
08070 vertex leftvertex, rightvertex, botvertex;
08071 vertex farvertex;
08072 triangle ptr;
08073 subseg sptr;
08074
08075
08076 org(*flipedge, rightvertex);
08077 dest(*flipedge, leftvertex);
08078 apex(*flipedge, botvertex);
08079 sym(*flipedge, top);
08080 #ifdef SELF_CHECK
08081 if (top.tri == m->dummytri) {
08082 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
08083 lnextself(*flipedge);
08084 return;
08085 }
08086 if (m->checksegments) {
08087 tspivot(*flipedge, toplsubseg);
08088 if (toplsubseg.ss != m->dummysub) {
08089 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
08090 lnextself(*flipedge);
08091 return;
08092 }
08093 }
08094 #endif
08095 apex(top, farvertex);
08096
08097
08098 lprev(top, topleft);
08099 sym(topleft, toplcasing);
08100 lnext(top, topright);
08101 sym(topright, toprcasing);
08102 lnext(*flipedge, botleft);
08103 sym(botleft, botlcasing);
08104 lprev(*flipedge, botright);
08105 sym(botright, botrcasing);
08106
08107 bond(topleft, toprcasing);
08108 bond(botleft, toplcasing);
08109 bond(botright, botlcasing);
08110 bond(topright, botrcasing);
08111
08112 if (m->checksegments) {
08113
08114 tspivot(topleft, toplsubseg);
08115 tspivot(botleft, botlsubseg);
08116 tspivot(botright, botrsubseg);
08117 tspivot(topright, toprsubseg);
08118 if (toplsubseg.ss == m->dummysub) {
08119 tsdissolve(botleft);
08120 } else {
08121 tsbond(botleft, toplsubseg);
08122 }
08123 if (botlsubseg.ss == m->dummysub) {
08124 tsdissolve(botright);
08125 } else {
08126 tsbond(botright, botlsubseg);
08127 }
08128 if (botrsubseg.ss == m->dummysub) {
08129 tsdissolve(topright);
08130 } else {
08131 tsbond(topright, botrsubseg);
08132 }
08133 if (toprsubseg.ss == m->dummysub) {
08134 tsdissolve(topleft);
08135 } else {
08136 tsbond(topleft, toprsubseg);
08137 }
08138 }
08139
08140
08141 setorg(*flipedge, botvertex);
08142 setdest(*flipedge, farvertex);
08143 setapex(*flipedge, leftvertex);
08144 setorg(top, farvertex);
08145 setdest(top, botvertex);
08146 setapex(top, rightvertex);
08147 if (b->verbose > 2) {
08148 printf(" Edge unflip results in left ");
08149 printtriangle(m, b, flipedge);
08150 printf(" and right ");
08151 printtriangle(m, b, &top);
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
08199
08200
08201
08202 #ifdef ANSI_DECLARATORS
08203 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
08204 vertex newvertex, struct otri *searchtri,
08205 struct osub *splitseg,
08206 int segmentflaws, int triflaws)
08207 #else
08208 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
08209 segmentflaws, triflaws)
08210 struct mesh *m;
08211 struct behavior *b;
08212 vertex newvertex;
08213 struct otri *searchtri;
08214 struct osub *splitseg;
08215 int segmentflaws;
08216 int triflaws;
08217 #endif
08218
08219 {
08220 struct otri horiz;
08221 struct otri top;
08222 struct otri botleft, botright;
08223 struct otri topleft, topright;
08224 struct otri newbotleft, newbotright;
08225 struct otri newtopright;
08226 struct otri botlcasing, botrcasing;
08227 struct otri toplcasing, toprcasing;
08228 struct otri testtri;
08229 struct osub botlsubseg, botrsubseg;
08230 struct osub toplsubseg, toprsubseg;
08231 struct osub brokensubseg;
08232 struct osub checksubseg;
08233 struct osub rightsubseg;
08234 struct osub newsubseg;
08235 struct badsubseg *encroached;
08236 struct flipstacker *newflip;
08237 vertex first;
08238 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
08239 vertex segmentorg, segmentdest;
08240 REAL attrib;
08241 REAL area;
08242 enum insertvertexresult success;
08243 enum locateresult intersect;
08244 int doflip;
08245 int mirrorflag;
08246 int enq;
08247 int i;
08248 triangle ptr;
08249 subseg sptr;
08250
08251 if (b->verbose > 1) {
08252 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
08253 }
08254
08255 if (splitseg == (struct osub *) NULL) {
08256
08257
08258 if (searchtri->tri == m->dummytri) {
08259
08260 horiz.tri = m->dummytri;
08261 horiz.orient = 0;
08262 symself(horiz);
08263
08264 intersect = locate(m, b, newvertex, &horiz);
08265 } else {
08266
08267 otricopy(*searchtri, horiz);
08268 intersect = preciselocate(m, b, newvertex, &horiz, 1);
08269 }
08270 } else {
08271
08272
08273 otricopy(*searchtri, horiz);
08274 intersect = ONEDGE;
08275 }
08276
08277 if (intersect == ONVERTEX) {
08278
08279
08280 otricopy(horiz, *searchtri);
08281 otricopy(horiz, m->recenttri);
08282 return DUPLICATEVERTEX;
08283 }
08284 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
08285
08286 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
08287
08288 tspivot(horiz, brokensubseg);
08289 if (brokensubseg.ss != m->dummysub) {
08290
08291 if (segmentflaws) {
08292 enq = b->nobisect != 2;
08293 if (enq && (b->nobisect == 1)) {
08294
08295
08296 sym(horiz, testtri);
08297 enq = testtri.tri != m->dummytri;
08298 }
08299 if (enq) {
08300
08301 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
08302 encroached->encsubseg = sencode(brokensubseg);
08303 sorg(brokensubseg, encroached->subsegorg);
08304 sdest(brokensubseg, encroached->subsegdest);
08305 if (b->verbose > 2) {
08306 printf(
08307 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
08308 encroached->subsegorg[0], encroached->subsegorg[1],
08309 encroached->subsegdest[0], encroached->subsegdest[1]);
08310 }
08311 }
08312 }
08313
08314
08315 otricopy(horiz, *searchtri);
08316 otricopy(horiz, m->recenttri);
08317 return VIOLATINGVERTEX;
08318 }
08319 }
08320
08321
08322
08323 lprev(horiz, botright);
08324 sym(botright, botrcasing);
08325 sym(horiz, topright);
08326
08327 mirrorflag = topright.tri != m->dummytri;
08328 if (mirrorflag) {
08329 lnextself(topright);
08330 sym(topright, toprcasing);
08331 maketriangle(m, b, &newtopright);
08332 } else {
08333
08334 m->hullsize++;
08335 }
08336 maketriangle(m, b, &newbotright);
08337
08338
08339 org(horiz, rightvertex);
08340 dest(horiz, leftvertex);
08341 apex(horiz, botvertex);
08342 setorg(newbotright, botvertex);
08343 setdest(newbotright, rightvertex);
08344 setapex(newbotright, newvertex);
08345 setorg(horiz, newvertex);
08346 for (i = 0; i < m->eextras; i++) {
08347
08348 setelemattribute(newbotright, i, elemattribute(botright, i));
08349 }
08350 if (b->vararea) {
08351
08352 setareabound(newbotright, areabound(botright));
08353 }
08354 if (mirrorflag) {
08355 dest(topright, topvertex);
08356 setorg(newtopright, rightvertex);
08357 setdest(newtopright, topvertex);
08358 setapex(newtopright, newvertex);
08359 setorg(topright, newvertex);
08360 for (i = 0; i < m->eextras; i++) {
08361
08362 setelemattribute(newtopright, i, elemattribute(topright, i));
08363 }
08364 if (b->vararea) {
08365
08366 setareabound(newtopright, areabound(topright));
08367 }
08368 }
08369
08370
08371
08372 if (m->checksegments) {
08373 tspivot(botright, botrsubseg);
08374 if (botrsubseg.ss != m->dummysub) {
08375 tsdissolve(botright);
08376 tsbond(newbotright, botrsubseg);
08377 }
08378 if (mirrorflag) {
08379 tspivot(topright, toprsubseg);
08380 if (toprsubseg.ss != m->dummysub) {
08381 tsdissolve(topright);
08382 tsbond(newtopright, toprsubseg);
08383 }
08384 }
08385 }
08386
08387
08388 bond(newbotright, botrcasing);
08389 lprevself(newbotright);
08390 bond(newbotright, botright);
08391 lprevself(newbotright);
08392 if (mirrorflag) {
08393 bond(newtopright, toprcasing);
08394 lnextself(newtopright);
08395 bond(newtopright, topright);
08396 lnextself(newtopright);
08397 bond(newtopright, newbotright);
08398 }
08399
08400 if (splitseg != (struct osub *) NULL) {
08401
08402 setsdest(*splitseg, newvertex);
08403 segorg(*splitseg, segmentorg);
08404 segdest(*splitseg, segmentdest);
08405 ssymself(*splitseg);
08406 spivot(*splitseg, rightsubseg);
08407 insertsubseg(m, b, &newbotright, mark(*splitseg));
08408 tspivot(newbotright, newsubseg);
08409 setsegorg(newsubseg, segmentorg);
08410 setsegdest(newsubseg, segmentdest);
08411 sbond(*splitseg, newsubseg);
08412 ssymself(newsubseg);
08413 sbond(newsubseg, rightsubseg);
08414 ssymself(*splitseg);
08415
08416
08417 if (vertexmark(newvertex) == 0) {
08418 setvertexmark(newvertex, mark(*splitseg));
08419 }
08420 }
08421
08422 if (m->checkquality) {
08423 poolrestart(&m->flipstackers);
08424 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08425 m->lastflip->flippedtri = encode(horiz);
08426 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
08427 }
08428
08429 #ifdef SELF_CHECK
08430 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08431 printf("Internal error in insertvertex():\n");
08432 printf(
08433 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
08434 }
08435 if (mirrorflag) {
08436 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
08437 printf("Internal error in insertvertex():\n");
08438 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
08439 }
08440 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
08441 printf("Internal error in insertvertex():\n");
08442 printf(
08443 " Clockwise triangle after edge vertex insertion (top right).\n");
08444 }
08445 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
08446 printf("Internal error in insertvertex():\n");
08447 printf(
08448 " Clockwise triangle after edge vertex insertion (top left).\n");
08449 }
08450 }
08451 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08452 printf("Internal error in insertvertex():\n");
08453 printf(
08454 " Clockwise triangle after edge vertex insertion (bottom left).\n");
08455 }
08456 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08457 printf("Internal error in insertvertex():\n");
08458 printf(
08459 " Clockwise triangle after edge vertex insertion (bottom right).\n");
08460 }
08461 #endif
08462 if (b->verbose > 2) {
08463 printf(" Updating bottom left ");
08464 printtriangle(m, b, &botright);
08465 if (mirrorflag) {
08466 printf(" Updating top left ");
08467 printtriangle(m, b, &topright);
08468 printf(" Creating top right ");
08469 printtriangle(m, b, &newtopright);
08470 }
08471 printf(" Creating bottom right ");
08472 printtriangle(m, b, &newbotright);
08473 }
08474
08475
08476
08477 lnextself(horiz);
08478 } else {
08479
08480 lnext(horiz, botleft);
08481 lprev(horiz, botright);
08482 sym(botleft, botlcasing);
08483 sym(botright, botrcasing);
08484 maketriangle(m, b, &newbotleft);
08485 maketriangle(m, b, &newbotright);
08486
08487
08488 org(horiz, rightvertex);
08489 dest(horiz, leftvertex);
08490 apex(horiz, botvertex);
08491 setorg(newbotleft, leftvertex);
08492 setdest(newbotleft, botvertex);
08493 setapex(newbotleft, newvertex);
08494 setorg(newbotright, botvertex);
08495 setdest(newbotright, rightvertex);
08496 setapex(newbotright, newvertex);
08497 setapex(horiz, newvertex);
08498 for (i = 0; i < m->eextras; i++) {
08499
08500 attrib = elemattribute(horiz, i);
08501 setelemattribute(newbotleft, i, attrib);
08502 setelemattribute(newbotright, i, attrib);
08503 }
08504 if (b->vararea) {
08505
08506 area = areabound(horiz);
08507 setareabound(newbotleft, area);
08508 setareabound(newbotright, area);
08509 }
08510
08511
08512
08513 if (m->checksegments) {
08514 tspivot(botleft, botlsubseg);
08515 if (botlsubseg.ss != m->dummysub) {
08516 tsdissolve(botleft);
08517 tsbond(newbotleft, botlsubseg);
08518 }
08519 tspivot(botright, botrsubseg);
08520 if (botrsubseg.ss != m->dummysub) {
08521 tsdissolve(botright);
08522 tsbond(newbotright, botrsubseg);
08523 }
08524 }
08525
08526
08527 bond(newbotleft, botlcasing);
08528 bond(newbotright, botrcasing);
08529 lnextself(newbotleft);
08530 lprevself(newbotright);
08531 bond(newbotleft, newbotright);
08532 lnextself(newbotleft);
08533 bond(botleft, newbotleft);
08534 lprevself(newbotright);
08535 bond(botright, newbotright);
08536
08537 if (m->checkquality) {
08538 poolrestart(&m->flipstackers);
08539 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08540 m->lastflip->flippedtri = encode(horiz);
08541 m->lastflip->prevflip = (struct flipstacker *) NULL;
08542 }
08543
08544 #ifdef SELF_CHECK
08545 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08546 printf("Internal error in insertvertex():\n");
08547 printf(" Clockwise triangle prior to vertex insertion.\n");
08548 }
08549 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
08550 printf("Internal error in insertvertex():\n");
08551 printf(" Clockwise triangle after vertex insertion (top).\n");
08552 }
08553 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08554 printf("Internal error in insertvertex():\n");
08555 printf(" Clockwise triangle after vertex insertion (left).\n");
08556 }
08557 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08558 printf("Internal error in insertvertex():\n");
08559 printf(" Clockwise triangle after vertex insertion (right).\n");
08560 }
08561 #endif
08562 if (b->verbose > 2) {
08563 printf(" Updating top ");
08564 printtriangle(m, b, &horiz);
08565 printf(" Creating left ");
08566 printtriangle(m, b, &newbotleft);
08567 printf(" Creating right ");
08568 printtriangle(m, b, &newbotright);
08569 }
08570 }
08571
08572
08573
08574 success = SUCCESSFULVERTEX;
08575
08576
08577
08578
08579 org(horiz, first);
08580 rightvertex = first;
08581 dest(horiz, leftvertex);
08582
08583 while (1) {
08584
08585 doflip = 1;
08586
08587 if (m->checksegments) {
08588
08589 tspivot(horiz, checksubseg);
08590 if (checksubseg.ss != m->dummysub) {
08591
08592 doflip = 0;
08593 #ifndef CDT_ONLY
08594 if (segmentflaws) {
08595
08596 if (checkseg4encroach(m, b, &checksubseg)) {
08597 success = ENCROACHINGVERTEX;
08598 }
08599 }
08600 #endif
08601 }
08602 }
08603
08604 if (doflip) {
08605
08606 sym(horiz, top);
08607 if (top.tri == m->dummytri) {
08608
08609 doflip = 0;
08610 } else {
08611
08612 apex(top, farvertex);
08613
08614
08615
08616
08617
08618 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
08619 (leftvertex == m->infvertex3)) {
08620
08621
08622
08623
08624 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
08625 > 0.0;
08626 } else if ((rightvertex == m->infvertex1) ||
08627 (rightvertex == m->infvertex2) ||
08628 (rightvertex == m->infvertex3)) {
08629
08630
08631
08632
08633 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
08634 > 0.0;
08635 } else if ((farvertex == m->infvertex1) ||
08636 (farvertex == m->infvertex2) ||
08637 (farvertex == m->infvertex3)) {
08638
08639
08640 doflip = 0;
08641 } else {
08642
08643 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
08644 farvertex) > 0.0;
08645 }
08646 if (doflip) {
08647
08648
08649
08650 lprev(top, topleft);
08651 sym(topleft, toplcasing);
08652 lnext(top, topright);
08653 sym(topright, toprcasing);
08654 lnext(horiz, botleft);
08655 sym(botleft, botlcasing);
08656 lprev(horiz, botright);
08657 sym(botright, botrcasing);
08658
08659 bond(topleft, botlcasing);
08660 bond(botleft, botrcasing);
08661 bond(botright, toprcasing);
08662 bond(topright, toplcasing);
08663 if (m->checksegments) {
08664
08665 tspivot(topleft, toplsubseg);
08666 tspivot(botleft, botlsubseg);
08667 tspivot(botright, botrsubseg);
08668 tspivot(topright, toprsubseg);
08669 if (toplsubseg.ss == m->dummysub) {
08670 tsdissolve(topright);
08671 } else {
08672 tsbond(topright, toplsubseg);
08673 }
08674 if (botlsubseg.ss == m->dummysub) {
08675 tsdissolve(topleft);
08676 } else {
08677 tsbond(topleft, botlsubseg);
08678 }
08679 if (botrsubseg.ss == m->dummysub) {
08680 tsdissolve(botleft);
08681 } else {
08682 tsbond(botleft, botrsubseg);
08683 }
08684 if (toprsubseg.ss == m->dummysub) {
08685 tsdissolve(botright);
08686 } else {
08687 tsbond(botright, toprsubseg);
08688 }
08689 }
08690
08691 setorg(horiz, farvertex);
08692 setdest(horiz, newvertex);
08693 setapex(horiz, rightvertex);
08694 setorg(top, newvertex);
08695 setdest(top, farvertex);
08696 setapex(top, leftvertex);
08697 for (i = 0; i < m->eextras; i++) {
08698
08699 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
08700 setelemattribute(top, i, attrib);
08701 setelemattribute(horiz, i, attrib);
08702 }
08703 if (b->vararea) {
08704 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
08705 area = -1.0;
08706 } else {
08707
08708
08709
08710 area = 0.5 * (areabound(top) + areabound(horiz));
08711 }
08712 setareabound(top, area);
08713 setareabound(horiz, area);
08714 }
08715
08716 if (m->checkquality) {
08717 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08718 newflip->flippedtri = encode(horiz);
08719 newflip->prevflip = m->lastflip;
08720 m->lastflip = newflip;
08721 }
08722
08723 #ifdef SELF_CHECK
08724 if (newvertex != (vertex) NULL) {
08725 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
08726 0.0) {
08727 printf("Internal error in insertvertex():\n");
08728 printf(" Clockwise triangle prior to edge flip (bottom).\n");
08729 }
08730
08731
08732
08733
08734
08735
08736
08737
08738
08739
08740 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
08741 0.0) {
08742 printf("Internal error in insertvertex():\n");
08743 printf(" Clockwise triangle after edge flip (left).\n");
08744 }
08745 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
08746 0.0) {
08747 printf("Internal error in insertvertex():\n");
08748 printf(" Clockwise triangle after edge flip (right).\n");
08749 }
08750 }
08751 #endif
08752 if (b->verbose > 2) {
08753 printf(" Edge flip results in left ");
08754 lnextself(topleft);
08755 printtriangle(m, b, &topleft);
08756 printf(" and right ");
08757 printtriangle(m, b, &horiz);
08758 }
08759
08760
08761
08762 lprevself(horiz);
08763 leftvertex = farvertex;
08764 }
08765 }
08766 }
08767 if (!doflip) {
08768
08769 #ifndef CDT_ONLY
08770 if (triflaws) {
08771
08772 testtriangle(m, b, &horiz);
08773 }
08774 #endif
08775
08776 lnextself(horiz);
08777 sym(horiz, testtri);
08778
08779
08780
08781 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
08782
08783 lnext(horiz, *searchtri);
08784 lnext(horiz, m->recenttri);
08785 return success;
08786 }
08787
08788 lnext(testtri, horiz);
08789 rightvertex = leftvertex;
08790 dest(horiz, leftvertex);
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
08856
08857
08858
08859 #ifdef ANSI_DECLARATORS
08860 void triangulatepolygon(struct mesh *m, struct behavior *b,
08861 struct otri *firstedge, struct otri *lastedge,
08862 int edgecount, int doflip, int triflaws)
08863 #else
08864 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
08865 struct mesh *m;
08866 struct behavior *b;
08867 struct otri *firstedge;
08868 struct otri *lastedge;
08869 int edgecount;
08870 int doflip;
08871 int triflaws;
08872 #endif
08873
08874 {
08875 struct otri testtri;
08876 struct otri besttri;
08877 struct otri tempedge;
08878 vertex leftbasevertex, rightbasevertex;
08879 vertex testvertex;
08880 vertex bestvertex;
08881 int bestnumber;
08882 int i;
08883 triangle ptr;
08884
08885
08886 apex(*lastedge, leftbasevertex);
08887 dest(*firstedge, rightbasevertex);
08888 if (b->verbose > 2) {
08889 printf(" Triangulating interior polygon at edge\n");
08890 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
08891 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
08892 }
08893
08894 onext(*firstedge, besttri);
08895 dest(besttri, bestvertex);
08896 otricopy(besttri, testtri);
08897 bestnumber = 1;
08898 for (i = 2; i <= edgecount - 2; i++) {
08899 onextself(testtri);
08900 dest(testtri, testvertex);
08901
08902 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
08903 testvertex) > 0.0) {
08904 otricopy(testtri, besttri);
08905 bestvertex = testvertex;
08906 bestnumber = i;
08907 }
08908 }
08909 if (b->verbose > 2) {
08910 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
08911 bestvertex[1]);
08912 }
08913 if (bestnumber > 1) {
08914
08915 oprev(besttri, tempedge);
08916 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
08917 triflaws);
08918 }
08919 if (bestnumber < edgecount - 2) {
08920
08921 sym(besttri, tempedge);
08922 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
08923 triflaws);
08924
08925 sym(tempedge, besttri);
08926 }
08927 if (doflip) {
08928
08929 flip(m, b, &besttri);
08930 #ifndef CDT_ONLY
08931 if (triflaws) {
08932
08933 sym(besttri, testtri);
08934 testtriangle(m, b, &testtri);
08935 }
08936 #endif
08937 }
08938
08939 otricopy(besttri, *lastedge);
08940 }
08941
08942
08943
08944
08945
08946
08947
08948
08949
08950
08951
08952
08953
08954
08955
08956 #ifndef CDT_ONLY
08957
08958 #ifdef ANSI_DECLARATORS
08959 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
08960 #else
08961 void deletevertex(m, b, deltri)
08962 struct mesh *m;
08963 struct behavior *b;
08964 struct otri *deltri;
08965 #endif
08966
08967 {
08968 struct otri countingtri;
08969 struct otri firstedge, lastedge;
08970 struct otri deltriright;
08971 struct otri lefttri, righttri;
08972 struct otri leftcasing, rightcasing;
08973 struct osub leftsubseg, rightsubseg;
08974 vertex delvertex;
08975 vertex neworg;
08976 int edgecount;
08977 triangle ptr;
08978 subseg sptr;
08979
08980 org(*deltri, delvertex);
08981 if (b->verbose > 1) {
08982 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
08983 }
08984 vertexdealloc(m, delvertex);
08985
08986
08987 onext(*deltri, countingtri);
08988 edgecount = 1;
08989 while (!otriequal(*deltri, countingtri)) {
08990 #ifdef SELF_CHECK
08991 if (countingtri.tri == m->dummytri) {
08992 printf("Internal error in deletevertex():\n");
08993 printf(" Attempt to delete boundary vertex.\n");
08994 internalerror();
08995 }
08996 #endif
08997 edgecount++;
08998 onextself(countingtri);
08999 }
09000
09001 #ifdef SELF_CHECK
09002 if (edgecount < 3) {
09003 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
09004 edgecount);
09005 internalerror();
09006 }
09007 #endif
09008 if (edgecount > 3) {
09009
09010
09011
09012 onext(*deltri, firstedge);
09013 oprev(*deltri, lastedge);
09014 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
09015 !b->nobisect);
09016 }
09017
09018 lprev(*deltri, deltriright);
09019 dnext(*deltri, lefttri);
09020 sym(lefttri, leftcasing);
09021 oprev(deltriright, righttri);
09022 sym(righttri, rightcasing);
09023 bond(*deltri, leftcasing);
09024 bond(deltriright, rightcasing);
09025 tspivot(lefttri, leftsubseg);
09026 if (leftsubseg.ss != m->dummysub) {
09027 tsbond(*deltri, leftsubseg);
09028 }
09029 tspivot(righttri, rightsubseg);
09030 if (rightsubseg.ss != m->dummysub) {
09031 tsbond(deltriright, rightsubseg);
09032 }
09033
09034
09035 org(lefttri, neworg);
09036 setorg(*deltri, neworg);
09037 if (!b->nobisect) {
09038 testtriangle(m, b, deltri);
09039 }
09040
09041
09042 triangledealloc(m, lefttri.tri);
09043 triangledealloc(m, righttri.tri);
09044 }
09045
09046 #endif
09047
09048
09049
09050
09051
09052
09053
09054
09055
09056
09057
09058
09059 #ifndef CDT_ONLY
09060
09061 #ifdef ANSI_DECLARATORS
09062 void undovertex(struct mesh *m, struct behavior *b)
09063 #else
09064 void undovertex(m, b)
09065 struct mesh *m;
09066 struct behavior *b;
09067 #endif
09068
09069 {
09070 struct otri fliptri;
09071 struct otri botleft, botright, topright;
09072 struct otri botlcasing, botrcasing, toprcasing;
09073 struct otri gluetri;
09074 struct osub botlsubseg, botrsubseg, toprsubseg;
09075 vertex botvertex, rightvertex;
09076 triangle ptr;
09077 subseg sptr;
09078
09079
09080
09081 while (m->lastflip != (struct flipstacker *) NULL) {
09082
09083 decode(m->lastflip->flippedtri, fliptri);
09084
09085
09086
09087
09088
09089 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
09090
09091
09092 dprev(fliptri, botleft);
09093 lnextself(botleft);
09094 onext(fliptri, botright);
09095 lprevself(botright);
09096 sym(botleft, botlcasing);
09097 sym(botright, botrcasing);
09098 dest(botleft, botvertex);
09099
09100 setapex(fliptri, botvertex);
09101 lnextself(fliptri);
09102 bond(fliptri, botlcasing);
09103 tspivot(botleft, botlsubseg);
09104 tsbond(fliptri, botlsubseg);
09105 lnextself(fliptri);
09106 bond(fliptri, botrcasing);
09107 tspivot(botright, botrsubseg);
09108 tsbond(fliptri, botrsubseg);
09109
09110
09111 triangledealloc(m, botleft.tri);
09112 triangledealloc(m, botright.tri);
09113 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
09114
09115
09116 lprev(fliptri, gluetri);
09117 sym(gluetri, botright);
09118 lnextself(botright);
09119 sym(botright, botrcasing);
09120 dest(botright, rightvertex);
09121
09122 setorg(fliptri, rightvertex);
09123 bond(gluetri, botrcasing);
09124 tspivot(botright, botrsubseg);
09125 tsbond(gluetri, botrsubseg);
09126
09127
09128 triangledealloc(m, botright.tri);
09129
09130 sym(fliptri, gluetri);
09131 if (gluetri.tri != m->dummytri) {
09132 lnextself(gluetri);
09133 dnext(gluetri, topright);
09134 sym(topright, toprcasing);
09135
09136 setorg(gluetri, rightvertex);
09137 bond(gluetri, toprcasing);
09138 tspivot(topright, toprsubseg);
09139 tsbond(gluetri, toprsubseg);
09140
09141
09142 triangledealloc(m, topright.tri);
09143 }
09144
09145
09146 m->lastflip->prevflip = (struct flipstacker *) NULL;
09147 } else {
09148
09149 unflip(m, b, &fliptri);
09150 }
09151
09152
09153 m->lastflip = m->lastflip->prevflip;
09154 }
09155 }
09156
09157 #endif
09158
09161
09162
09163
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
09205
09206
09207
09208 #ifdef ANSI_DECLARATORS
09209 void vertexsort(vertex *sortarray, int arraysize)
09210 #else
09211 void vertexsort(sortarray, arraysize)
09212 vertex *sortarray;
09213 int arraysize;
09214 #endif
09215
09216 {
09217 int left, right;
09218 int pivot;
09219 REAL pivotx, pivoty;
09220 vertex temp;
09221
09222 if (arraysize == 2) {
09223
09224 if ((sortarray[0][0] > sortarray[1][0]) ||
09225 ((sortarray[0][0] == sortarray[1][0]) &&
09226 (sortarray[0][1] > sortarray[1][1]))) {
09227 temp = sortarray[1];
09228 sortarray[1] = sortarray[0];
09229 sortarray[0] = temp;
09230 }
09231 return;
09232 }
09233
09234 pivot = (int) randomnation((unsigned int) arraysize);
09235 pivotx = sortarray[pivot][0];
09236 pivoty = sortarray[pivot][1];
09237
09238 left = -1;
09239 right = arraysize;
09240 while (left < right) {
09241
09242 do {
09243 left++;
09244 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
09245 ((sortarray[left][0] == pivotx) &&
09246 (sortarray[left][1] < pivoty))));
09247
09248 do {
09249 right--;
09250 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
09251 ((sortarray[right][0] == pivotx) &&
09252 (sortarray[right][1] > pivoty))));
09253 if (left < right) {
09254
09255 temp = sortarray[left];
09256 sortarray[left] = sortarray[right];
09257 sortarray[right] = temp;
09258 }
09259 }
09260 if (left > 1) {
09261
09262 vertexsort(sortarray, left);
09263 }
09264 if (right < arraysize - 2) {
09265
09266 vertexsort(&sortarray[right + 1], arraysize - right - 1);
09267 }
09268 }
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282 #ifdef ANSI_DECLARATORS
09283 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
09284 #else
09285 void vertexmedian(sortarray, arraysize, median, axis)
09286 vertex *sortarray;
09287 int arraysize;
09288 int median;
09289 int axis;
09290 #endif
09291
09292 {
09293 int left, right;
09294 int pivot;
09295 REAL pivot1, pivot2;
09296 vertex temp;
09297
09298 if (arraysize == 2) {
09299
09300 if ((sortarray[0][axis] > sortarray[1][axis]) ||
09301 ((sortarray[0][axis] == sortarray[1][axis]) &&
09302 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
09303 temp = sortarray[1];
09304 sortarray[1] = sortarray[0];
09305 sortarray[0] = temp;
09306 }
09307 return;
09308 }
09309
09310 pivot = (int) randomnation((unsigned int) arraysize);
09311 pivot1 = sortarray[pivot][axis];
09312 pivot2 = sortarray[pivot][1 - axis];
09313
09314 left = -1;
09315 right = arraysize;
09316 while (left < right) {
09317
09318 do {
09319 left++;
09320 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
09321 ((sortarray[left][axis] == pivot1) &&
09322 (sortarray[left][1 - axis] < pivot2))));
09323
09324 do {
09325 right--;
09326 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
09327 ((sortarray[right][axis] == pivot1) &&
09328 (sortarray[right][1 - axis] > pivot2))));
09329 if (left < right) {
09330
09331 temp = sortarray[left];
09332 sortarray[left] = sortarray[right];
09333 sortarray[right] = temp;
09334 }
09335 }
09336
09337
09338 if (left > median) {
09339
09340 vertexmedian(sortarray, left, median, axis);
09341 }
09342 if (right < median - 1) {
09343
09344 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
09345 median - right - 1, axis);
09346 }
09347 }
09348
09349
09350
09351
09352
09353
09354
09355
09356
09357
09358
09359
09360 #ifdef ANSI_DECLARATORS
09361 void alternateaxes(vertex *sortarray, int arraysize, int axis)
09362 #else
09363 void alternateaxes(sortarray, arraysize, axis)
09364 vertex *sortarray;
09365 int arraysize;
09366 int axis;
09367 #endif
09368
09369 {
09370 int divider;
09371
09372 divider = arraysize >> 1;
09373 if (arraysize <= 3) {
09374
09375
09376 axis = 0;
09377 }
09378
09379 vertexmedian(sortarray, arraysize, divider, axis);
09380
09381 if (arraysize - divider >= 2) {
09382 if (divider >= 2) {
09383 alternateaxes(sortarray, divider, 1 - axis);
09384 }
09385 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
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
09421
09422
09423
09424 #ifdef ANSI_DECLARATORS
09425 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
09426 struct otri *innerleft, struct otri *innerright,
09427 struct otri *farright, int axis)
09428 #else
09429 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
09430 struct mesh *m;
09431 struct behavior *b;
09432 struct otri *farleft;
09433 struct otri *innerleft;
09434 struct otri *innerright;
09435 struct otri *farright;
09436 int axis;
09437 #endif
09438
09439 {
09440 struct otri leftcand, rightcand;
09441 struct otri baseedge;
09442 struct otri nextedge;
09443 struct otri sidecasing, topcasing, outercasing;
09444 struct otri checkedge;
09445 vertex innerleftdest;
09446 vertex innerrightorg;
09447 vertex innerleftapex, innerrightapex;
09448 vertex farleftpt, farrightpt;
09449 vertex farleftapex, farrightapex;
09450 vertex lowerleft, lowerright;
09451 vertex upperleft, upperright;
09452 vertex nextapex;
09453 vertex checkvertex;
09454 int changemade;
09455 int badedge;
09456 int leftfinished, rightfinished;
09457 triangle ptr;
09458
09459 dest(*innerleft, innerleftdest);
09460 apex(*innerleft, innerleftapex);
09461 org(*innerright, innerrightorg);
09462 apex(*innerright, innerrightapex);
09463
09464 if (b->dwyer && (axis == 1)) {
09465 org(*farleft, farleftpt);
09466 apex(*farleft, farleftapex);
09467 dest(*farright, farrightpt);
09468 apex(*farright, farrightapex);
09469
09470
09471
09472 while (farleftapex[1] < farleftpt[1]) {
09473 lnextself(*farleft);
09474 symself(*farleft);
09475 farleftpt = farleftapex;
09476 apex(*farleft, farleftapex);
09477 }
09478 sym(*innerleft, checkedge);
09479 apex(checkedge, checkvertex);
09480 while (checkvertex[1] > innerleftdest[1]) {
09481 lnext(checkedge, *innerleft);
09482 innerleftapex = innerleftdest;
09483 innerleftdest = checkvertex;
09484 sym(*innerleft, checkedge);
09485 apex(checkedge, checkvertex);
09486 }
09487 while (innerrightapex[1] < innerrightorg[1]) {
09488 lnextself(*innerright);
09489 symself(*innerright);
09490 innerrightorg = innerrightapex;
09491 apex(*innerright, innerrightapex);
09492 }
09493 sym(*farright, checkedge);
09494 apex(checkedge, checkvertex);
09495 while (checkvertex[1] > farrightpt[1]) {
09496 lnext(checkedge, *farright);
09497 farrightapex = farrightpt;
09498 farrightpt = checkvertex;
09499 sym(*farright, checkedge);
09500 apex(checkedge, checkvertex);
09501 }
09502 }
09503
09504 do {
09505 changemade = 0;
09506
09507 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
09508 0.0) {
09509 lprevself(*innerleft);
09510 symself(*innerleft);
09511 innerleftdest = innerleftapex;
09512 apex(*innerleft, innerleftapex);
09513 changemade = 1;
09514 }
09515
09516 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
09517 0.0) {
09518 lnextself(*innerright);
09519 symself(*innerright);
09520 innerrightorg = innerrightapex;
09521 apex(*innerright, innerrightapex);
09522 changemade = 1;
09523 }
09524 } while (changemade);
09525
09526 sym(*innerleft, leftcand);
09527 sym(*innerright, rightcand);
09528
09529 maketriangle(m, b, &baseedge);
09530
09531 bond(baseedge, *innerleft);
09532 lnextself(baseedge);
09533 bond(baseedge, *innerright);
09534 lnextself(baseedge);
09535 setorg(baseedge, innerrightorg);
09536 setdest(baseedge, innerleftdest);
09537
09538 if (b->verbose > 2) {
09539 printf(" Creating base bounding ");
09540 printtriangle(m, b, &baseedge);
09541 }
09542
09543 org(*farleft, farleftpt);
09544 if (innerleftdest == farleftpt) {
09545 lnext(baseedge, *farleft);
09546 }
09547 dest(*farright, farrightpt);
09548 if (innerrightorg == farrightpt) {
09549 lprev(baseedge, *farright);
09550 }
09551
09552 lowerleft = innerleftdest;
09553 lowerright = innerrightorg;
09554
09555 apex(leftcand, upperleft);
09556 apex(rightcand, upperright);
09557
09558 while (1) {
09559
09560
09561
09562
09563 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
09564 0.0;
09565 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
09566 <= 0.0;
09567 if (leftfinished && rightfinished) {
09568
09569 maketriangle(m, b, &nextedge);
09570 setorg(nextedge, lowerleft);
09571 setdest(nextedge, lowerright);
09572
09573
09574 bond(nextedge, baseedge);
09575 lnextself(nextedge);
09576 bond(nextedge, rightcand);
09577 lnextself(nextedge);
09578 bond(nextedge, leftcand);
09579 if (b->verbose > 2) {
09580 printf(" Creating top bounding ");
09581 printtriangle(m, b, &nextedge);
09582 }
09583
09584 if (b->dwyer && (axis == 1)) {
09585 org(*farleft, farleftpt);
09586 apex(*farleft, farleftapex);
09587 dest(*farright, farrightpt);
09588 apex(*farright, farrightapex);
09589 sym(*farleft, checkedge);
09590 apex(checkedge, checkvertex);
09591
09592
09593
09594 while (checkvertex[0] < farleftpt[0]) {
09595 lprev(checkedge, *farleft);
09596 farleftapex = farleftpt;
09597 farleftpt = checkvertex;
09598 sym(*farleft, checkedge);
09599 apex(checkedge, checkvertex);
09600 }
09601 while (farrightapex[0] > farrightpt[0]) {
09602 lprevself(*farright);
09603 symself(*farright);
09604 farrightpt = farrightapex;
09605 apex(*farright, farrightapex);
09606 }
09607 }
09608 return;
09609 }
09610
09611 if (!leftfinished) {
09612
09613 lprev(leftcand, nextedge);
09614 symself(nextedge);
09615 apex(nextedge, nextapex);
09616
09617
09618 if (nextapex != (vertex) NULL) {
09619
09620 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
09621 0.0;
09622 while (badedge) {
09623
09624
09625 lnextself(nextedge);
09626 sym(nextedge, topcasing);
09627 lnextself(nextedge);
09628 sym(nextedge, sidecasing);
09629 bond(nextedge, topcasing);
09630 bond(leftcand, sidecasing);
09631 lnextself(leftcand);
09632 sym(leftcand, outercasing);
09633 lprevself(nextedge);
09634 bond(nextedge, outercasing);
09635
09636 setorg(leftcand, lowerleft);
09637 setdest(leftcand, NULL);
09638 setapex(leftcand, nextapex);
09639 setorg(nextedge, NULL);
09640 setdest(nextedge, upperleft);
09641 setapex(nextedge, nextapex);
09642
09643 upperleft = nextapex;
09644
09645 otricopy(sidecasing, nextedge);
09646 apex(nextedge, nextapex);
09647 if (nextapex != (vertex) NULL) {
09648
09649 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
09650 nextapex) > 0.0;
09651 } else {
09652
09653 badedge = 0;
09654 }
09655 }
09656 }
09657 }
09658
09659 if (!rightfinished) {
09660
09661 lnext(rightcand, nextedge);
09662 symself(nextedge);
09663 apex(nextedge, nextapex);
09664
09665
09666 if (nextapex != (vertex) NULL) {
09667
09668 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
09669 0.0;
09670 while (badedge) {
09671
09672
09673 lprevself(nextedge);
09674 sym(nextedge, topcasing);
09675 lprevself(nextedge);
09676 sym(nextedge, sidecasing);
09677 bond(nextedge, topcasing);
09678 bond(rightcand, sidecasing);
09679 lprevself(rightcand);
09680 sym(rightcand, outercasing);
09681 lnextself(nextedge);
09682 bond(nextedge, outercasing);
09683
09684 setorg(rightcand, NULL);
09685 setdest(rightcand, lowerright);
09686 setapex(rightcand, nextapex);
09687 setorg(nextedge, upperright);
09688 setdest(nextedge, NULL);
09689 setapex(nextedge, nextapex);
09690
09691 upperright = nextapex;
09692
09693 otricopy(sidecasing, nextedge);
09694 apex(nextedge, nextapex);
09695 if (nextapex != (vertex) NULL) {
09696
09697 badedge = incircle(m, b, lowerleft, lowerright, upperright,
09698 nextapex) > 0.0;
09699 } else {
09700
09701 badedge = 0;
09702 }
09703 }
09704 }
09705 }
09706 if (leftfinished || (!rightfinished &&
09707 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
09708 0.0))) {
09709
09710
09711 bond(baseedge, rightcand);
09712 lprev(rightcand, baseedge);
09713 setdest(baseedge, lowerleft);
09714 lowerright = upperright;
09715 sym(baseedge, rightcand);
09716 apex(rightcand, upperright);
09717 } else {
09718
09719
09720 bond(baseedge, leftcand);
09721 lnext(leftcand, baseedge);
09722 setorg(baseedge, lowerright);
09723 lowerleft = upperleft;
09724 sym(baseedge, leftcand);
09725 apex(leftcand, upperleft);
09726 }
09727 if (b->verbose > 2) {
09728 printf(" Connecting ");
09729 printtriangle(m, b, &baseedge);
09730 }
09731 }
09732 }
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744
09745
09746
09747
09748
09749
09750
09751 #ifdef ANSI_DECLARATORS
09752 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
09753 int vertices, int axis,
09754 struct otri *farleft, struct otri *farright)
09755 #else
09756 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
09757 struct mesh *m;
09758 struct behavior *b;
09759 vertex *sortarray;
09760 int vertices;
09761 int axis;
09762 struct otri *farleft;
09763 struct otri *farright;
09764 #endif
09765
09766 {
09767 struct otri midtri, tri1, tri2, tri3;
09768 struct otri innerleft, innerright;
09769 REAL area;
09770 int divider;
09771
09772 if (b->verbose > 2) {
09773 printf(" Triangulating %d vertices.\n", vertices);
09774 }
09775 if (vertices == 2) {
09776
09777
09778 maketriangle(m, b, farleft);
09779 setorg(*farleft, sortarray[0]);
09780 setdest(*farleft, sortarray[1]);
09781
09782 maketriangle(m, b, farright);
09783 setorg(*farright, sortarray[1]);
09784 setdest(*farright, sortarray[0]);
09785
09786 bond(*farleft, *farright);
09787 lprevself(*farleft);
09788 lnextself(*farright);
09789 bond(*farleft, *farright);
09790 lprevself(*farleft);
09791 lnextself(*farright);
09792 bond(*farleft, *farright);
09793 if (b->verbose > 2) {
09794 printf(" Creating ");
09795 printtriangle(m, b, farleft);
09796 printf(" Creating ");
09797 printtriangle(m, b, farright);
09798 }
09799
09800 lprev(*farright, *farleft);
09801 return;
09802 } else if (vertices == 3) {
09803
09804
09805
09806 maketriangle(m, b, &midtri);
09807 maketriangle(m, b, &tri1);
09808 maketriangle(m, b, &tri2);
09809 maketriangle(m, b, &tri3);
09810 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
09811 if (area == 0.0) {
09812
09813 setorg(midtri, sortarray[0]);
09814 setdest(midtri, sortarray[1]);
09815 setorg(tri1, sortarray[1]);
09816 setdest(tri1, sortarray[0]);
09817 setorg(tri2, sortarray[2]);
09818 setdest(tri2, sortarray[1]);
09819 setorg(tri3, sortarray[1]);
09820 setdest(tri3, sortarray[2]);
09821
09822 bond(midtri, tri1);
09823 bond(tri2, tri3);
09824 lnextself(midtri);
09825 lprevself(tri1);
09826 lnextself(tri2);
09827 lprevself(tri3);
09828 bond(midtri, tri3);
09829 bond(tri1, tri2);
09830 lnextself(midtri);
09831 lprevself(tri1);
09832 lnextself(tri2);
09833 lprevself(tri3);
09834 bond(midtri, tri1);
09835 bond(tri2, tri3);
09836
09837 otricopy(tri1, *farleft);
09838
09839 otricopy(tri2, *farright);
09840 } else {
09841
09842
09843 setorg(midtri, sortarray[0]);
09844 setdest(tri1, sortarray[0]);
09845 setorg(tri3, sortarray[0]);
09846
09847 if (area > 0.0) {
09848
09849 setdest(midtri, sortarray[1]);
09850 setorg(tri1, sortarray[1]);
09851 setdest(tri2, sortarray[1]);
09852 setapex(midtri, sortarray[2]);
09853 setorg(tri2, sortarray[2]);
09854 setdest(tri3, sortarray[2]);
09855 } else {
09856
09857 setdest(midtri, sortarray[2]);
09858 setorg(tri1, sortarray[2]);
09859 setdest(tri2, sortarray[2]);
09860 setapex(midtri, sortarray[1]);
09861 setorg(tri2, sortarray[1]);
09862 setdest(tri3, sortarray[1]);
09863 }
09864
09865 bond(midtri, tri1);
09866 lnextself(midtri);
09867 bond(midtri, tri2);
09868 lnextself(midtri);
09869 bond(midtri, tri3);
09870 lprevself(tri1);
09871 lnextself(tri2);
09872 bond(tri1, tri2);
09873 lprevself(tri1);
09874 lprevself(tri3);
09875 bond(tri1, tri3);
09876 lnextself(tri2);
09877 lprevself(tri3);
09878 bond(tri2, tri3);
09879
09880 otricopy(tri1, *farleft);
09881
09882 if (area > 0.0) {
09883 otricopy(tri2, *farright);
09884 } else {
09885 lnext(*farleft, *farright);
09886 }
09887 }
09888 if (b->verbose > 2) {
09889 printf(" Creating ");
09890 printtriangle(m, b, &midtri);
09891 printf(" Creating ");
09892 printtriangle(m, b, &tri1);
09893 printf(" Creating ");
09894 printtriangle(m, b, &tri2);
09895 printf(" Creating ");
09896 printtriangle(m, b, &tri3);
09897 }
09898 return;
09899 } else {
09900
09901 divider = vertices >> 1;
09902
09903 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
09904 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
09905 &innerright, farright);
09906 if (b->verbose > 1) {
09907 printf(" Joining triangulations with %d and %d vertices.\n", divider,
09908 vertices - divider);
09909 }
09910
09911 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
09912 }
09913 }
09914
09915 #ifdef ANSI_DECLARATORS
09916 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
09917 #else
09918 long removeghosts(m, b, startghost)
09919 struct mesh *m;
09920 struct behavior *b;
09921 struct otri *startghost;
09922 #endif
09923
09924 {
09925 struct otri searchedge;
09926 struct otri dissolveedge;
09927 struct otri deadtriangle;
09928 vertex markorg;
09929 long hullsize;
09930 triangle ptr;
09931
09932 if (b->verbose) {
09933 printf(" Removing ghost triangles.\n");
09934 }
09935
09936 lprev(*startghost, searchedge);
09937 symself(searchedge);
09938 m->dummytri[0] = encode(searchedge);
09939
09940 otricopy(*startghost, dissolveedge);
09941 hullsize = 0;
09942 do {
09943 hullsize++;
09944 lnext(dissolveedge, deadtriangle);
09945 lprevself(dissolveedge);
09946 symself(dissolveedge);
09947
09948
09949 if (!b->poly) {
09950
09951 if (dissolveedge.tri != m->dummytri) {
09952 org(dissolveedge, markorg);
09953 if (vertexmark(markorg) == 0) {
09954 setvertexmark(markorg, 1);
09955 }
09956 }
09957 }
09958
09959 dissolve(dissolveedge);
09960
09961 sym(deadtriangle, dissolveedge);
09962
09963 triangledealloc(m, deadtriangle.tri);
09964 } while (!otriequal(dissolveedge, *startghost));
09965 return hullsize;
09966 }
09967
09968
09969
09970
09971
09972
09973
09974
09975
09976
09977
09978 #ifdef ANSI_DECLARATORS
09979 long divconqdelaunay(struct mesh *m, struct behavior *b)
09980 #else
09981 long divconqdelaunay(m, b)
09982 struct mesh *m;
09983 struct behavior *b;
09984 #endif
09985
09986 {
09987 vertex *sortarray;
09988 struct otri hullleft, hullright;
09989 int divider;
09990 int i, j;
09991
09992 if (b->verbose) {
09993 printf(" Sorting vertices.\n");
09994 }
09995
09996
09997 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
09998 traversalinit(&m->vertices);
09999 for (i = 0; i < m->invertices; i++) {
10000 sortarray[i] = vertextraverse(m);
10001 }
10002
10003 vertexsort(sortarray, m->invertices);
10004
10005 i = 0;
10006 for (j = 1; j < m->invertices; j++) {
10007 if ((sortarray[i][0] == sortarray[j][0])
10008 && (sortarray[i][1] == sortarray[j][1])) {
10009 if (!b->quiet) {
10010 printf(
10011 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10012 sortarray[j][0], sortarray[j][1]);
10013 }
10014 setvertextype(sortarray[j], UNDEADVERTEX);
10015 m->undeads++;
10016 } else {
10017 i++;
10018 sortarray[i] = sortarray[j];
10019 }
10020 }
10021 i++;
10022 if (b->dwyer) {
10023
10024 divider = i >> 1;
10025 if (i - divider >= 2) {
10026 if (divider >= 2) {
10027 alternateaxes(sortarray, divider, 1);
10028 }
10029 alternateaxes(&sortarray[divider], i - divider, 1);
10030 }
10031 }
10032
10033 if (b->verbose) {
10034 printf(" Forming triangulation.\n");
10035 }
10036
10037
10038 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10039 trifree((VOID *) sortarray);
10040
10041 return removeghosts(m, b, &hullleft);
10042 }
10043
10046
10047
10048
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062
10063 #ifndef REDUCED
10064
10065 #ifdef ANSI_DECLARATORS
10066 void boundingbox(struct mesh *m, struct behavior *b)
10067 #else
10068 void boundingbox(m, b)
10069 struct mesh *m;
10070 struct behavior *b;
10071 #endif
10072
10073 {
10074 struct otri inftri;
10075 REAL width;
10076
10077 if (b->verbose) {
10078 printf(" Creating triangular bounding box.\n");
10079 }
10080
10081 width = m->xmax - m->xmin;
10082 if (m->ymax - m->ymin > width) {
10083 width = m->ymax - m->ymin;
10084 }
10085 if (width == 0.0) {
10086 width = 1.0;
10087 }
10088
10089 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10090 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10091 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10092 m->infvertex1[0] = m->xmin - 50.0 * width;
10093 m->infvertex1[1] = m->ymin - 40.0 * width;
10094 m->infvertex2[0] = m->xmax + 50.0 * width;
10095 m->infvertex2[1] = m->ymin - 40.0 * width;
10096 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10097 m->infvertex3[1] = m->ymax + 60.0 * width;
10098
10099
10100 maketriangle(m, b, &inftri);
10101 setorg(inftri, m->infvertex1);
10102 setdest(inftri, m->infvertex2);
10103 setapex(inftri, m->infvertex3);
10104
10105
10106 m->dummytri[0] = (triangle) inftri.tri;
10107 if (b->verbose > 2) {
10108 printf(" Creating ");
10109 printtriangle(m, b, &inftri);
10110 }
10111 }
10112
10113 #endif
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
10129 #ifndef REDUCED
10130
10131 #ifdef ANSI_DECLARATORS
10132 long removebox(struct mesh *m, struct behavior *b)
10133 #else
10134 long removebox(m, b)
10135 struct mesh *m;
10136 struct behavior *b;
10137 #endif
10138
10139 {
10140 struct otri deadtriangle;
10141 struct otri searchedge;
10142 struct otri checkedge;
10143 struct otri nextedge, finaledge, dissolveedge;
10144 vertex markorg;
10145 long hullsize;
10146 triangle ptr;
10147
10148 if (b->verbose) {
10149 printf(" Removing triangular bounding box.\n");
10150 }
10151
10152 nextedge.tri = m->dummytri;
10153 nextedge.orient = 0;
10154 symself(nextedge);
10155
10156 lprev(nextedge, finaledge);
10157 lnextself(nextedge);
10158 symself(nextedge);
10159
10160
10161 lprev(nextedge, searchedge);
10162 symself(searchedge);
10163
10164
10165 lnext(nextedge, checkedge);
10166 symself(checkedge);
10167 if (checkedge.tri == m->dummytri) {
10168
10169
10170
10171 lprevself(searchedge);
10172 symself(searchedge);
10173 }
10174
10175
10176 m->dummytri[0] = encode(searchedge);
10177 hullsize = -2l;
10178 while (!otriequal(nextedge, finaledge)) {
10179 hullsize++;
10180 lprev(nextedge, dissolveedge);
10181 symself(dissolveedge);
10182
10183
10184 if (!b->poly) {
10185
10186
10187
10188
10189 if (dissolveedge.tri != m->dummytri) {
10190 org(dissolveedge, markorg);
10191 if (vertexmark(markorg) == 0) {
10192 setvertexmark(markorg, 1);
10193 }
10194 }
10195 }
10196
10197 dissolve(dissolveedge);
10198 lnext(nextedge, deadtriangle);
10199 sym(deadtriangle, nextedge);
10200
10201 triangledealloc(m, deadtriangle.tri);
10202
10203 if (nextedge.tri == m->dummytri) {
10204
10205 otricopy(dissolveedge, nextedge);
10206 }
10207 }
10208 triangledealloc(m, finaledge.tri);
10209
10210 trifree((VOID *) m->infvertex1);
10211 trifree((VOID *) m->infvertex2);
10212 trifree((VOID *) m->infvertex3);
10213
10214 return hullsize;
10215 }
10216
10217 #endif
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227
10228 #ifndef REDUCED
10229
10230 #ifdef ANSI_DECLARATORS
10231 long incrementaldelaunay(struct mesh *m, struct behavior *b)
10232 #else
10233 long incrementaldelaunay(m, b)
10234 struct mesh *m;
10235 struct behavior *b;
10236 #endif
10237
10238 {
10239 struct otri starttri;
10240 vertex vertexloop;
10241
10242
10243 boundingbox(m, b);
10244 if (b->verbose) {
10245 printf(" Incrementally inserting vertices.\n");
10246 }
10247 traversalinit(&m->vertices);
10248 vertexloop = vertextraverse(m);
10249 while (vertexloop != (vertex) NULL) {
10250 starttri.tri = m->dummytri;
10251 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10252 == DUPLICATEVERTEX) {
10253 if (!b->quiet) {
10254 printf(
10255 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10256 vertexloop[0], vertexloop[1]);
10257 }
10258 setvertextype(vertexloop, UNDEADVERTEX);
10259 m->undeads++;
10260 }
10261 vertexloop = vertextraverse(m);
10262 }
10263
10264 return removebox(m, b);
10265 }
10266
10267 #endif
10268
10271
10272
10273
10277 #ifndef REDUCED
10278
10279 #ifdef ANSI_DECLARATORS
10280 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10281 #else
10282 void eventheapinsert(heap, heapsize, newevent)
10283 struct event **heap;
10284 int heapsize;
10285 struct event *newevent;
10286 #endif
10287
10288 {
10289 REAL eventx, eventy;
10290 int eventnum;
10291 int parent;
10292 int notdone;
10293
10294 eventx = newevent->xkey;
10295 eventy = newevent->ykey;
10296 eventnum = heapsize;
10297 notdone = eventnum > 0;
10298 while (notdone) {
10299 parent = (eventnum - 1) >> 1;
10300 if ((heap[parent]->ykey < eventy) ||
10301 ((heap[parent]->ykey == eventy)
10302 && (heap[parent]->xkey <= eventx))) {
10303 notdone = 0;
10304 } else {
10305 heap[eventnum] = heap[parent];
10306 heap[eventnum]->heapposition = eventnum;
10307
10308 eventnum = parent;
10309 notdone = eventnum > 0;
10310 }
10311 }
10312 heap[eventnum] = newevent;
10313 newevent->heapposition = eventnum;
10314 }
10315
10316 #endif
10317
10318 #ifndef REDUCED
10319
10320 #ifdef ANSI_DECLARATORS
10321 void eventheapify(struct event **heap, int heapsize, int eventnum)
10322 #else
10323 void eventheapify(heap, heapsize, eventnum)
10324 struct event **heap;
10325 int heapsize;
10326 int eventnum;
10327 #endif
10328
10329 {
10330 struct event *thisevent;
10331 REAL eventx, eventy;
10332 int leftchild, rightchild;
10333 int smallest;
10334 int notdone;
10335
10336 thisevent = heap[eventnum];
10337 eventx = thisevent->xkey;
10338 eventy = thisevent->ykey;
10339 leftchild = 2 * eventnum + 1;
10340 notdone = leftchild < heapsize;
10341 while (notdone) {
10342 if ((heap[leftchild]->ykey < eventy) ||
10343 ((heap[leftchild]->ykey == eventy)
10344 && (heap[leftchild]->xkey < eventx))) {
10345 smallest = leftchild;
10346 } else {
10347 smallest = eventnum;
10348 }
10349 rightchild = leftchild + 1;
10350 if (rightchild < heapsize) {
10351 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10352 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10353 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10354 smallest = rightchild;
10355 }
10356 }
10357 if (smallest == eventnum) {
10358 notdone = 0;
10359 } else {
10360 heap[eventnum] = heap[smallest];
10361 heap[eventnum]->heapposition = eventnum;
10362 heap[smallest] = thisevent;
10363 thisevent->heapposition = smallest;
10364
10365 eventnum = smallest;
10366 leftchild = 2 * eventnum + 1;
10367 notdone = leftchild < heapsize;
10368 }
10369 }
10370 }
10371
10372 #endif
10373
10374 #ifndef REDUCED
10375
10376 #ifdef ANSI_DECLARATORS
10377 void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10378 #else
10379 void eventheapdelete(heap, heapsize, eventnum)
10380 struct event **heap;
10381 int heapsize;
10382 int eventnum;
10383 #endif
10384
10385 {
10386 struct event *moveevent;
10387 REAL eventx, eventy;
10388 int parent;
10389 int notdone;
10390
10391 moveevent = heap[heapsize - 1];
10392 if (eventnum > 0) {
10393 eventx = moveevent->xkey;
10394 eventy = moveevent->ykey;
10395 do {
10396 parent = (eventnum - 1) >> 1;
10397 if ((heap[parent]->ykey < eventy) ||
10398 ((heap[parent]->ykey == eventy)
10399 && (heap[parent]->xkey <= eventx))) {
10400 notdone = 0;
10401 } else {
10402 heap[eventnum] = heap[parent];
10403 heap[eventnum]->heapposition = eventnum;
10404
10405 eventnum = parent;
10406 notdone = eventnum > 0;
10407 }
10408 } while (notdone);
10409 }
10410 heap[eventnum] = moveevent;
10411 moveevent->heapposition = eventnum;
10412 eventheapify(heap, heapsize - 1, eventnum);
10413 }
10414
10415 #endif
10416
10417 #ifndef REDUCED
10418
10419 #ifdef ANSI_DECLARATORS
10420 void createeventheap(struct mesh *m, struct event ***eventheap,
10421 struct event **events, struct event **freeevents)
10422 #else
10423 void createeventheap(m, eventheap, events, freeevents)
10424 struct mesh *m;
10425 struct event ***eventheap;
10426 struct event **events;
10427 struct event **freeevents;
10428 #endif
10429
10430 {
10431 vertex thisvertex;
10432 int maxevents;
10433 int i;
10434
10435 maxevents = (3 * m->invertices) / 2;
10436 *eventheap = (struct event **) trimalloc(maxevents *
10437 (int) sizeof(struct event *));
10438 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10439 traversalinit(&m->vertices);
10440 for (i = 0; i < m->invertices; i++) {
10441 thisvertex = vertextraverse(m);
10442 (*events)[i].eventptr = (VOID *) thisvertex;
10443 (*events)[i].xkey = thisvertex[0];
10444 (*events)[i].ykey = thisvertex[1];
10445 eventheapinsert(*eventheap, i, *events + i);
10446 }
10447 *freeevents = (struct event *) NULL;
10448 for (i = maxevents - 1; i >= m->invertices; i--) {
10449 (*events)[i].eventptr = (VOID *) *freeevents;
10450 *freeevents = *events + i;
10451 }
10452 }
10453
10454 #endif
10455
10456 #ifndef REDUCED
10457
10458 #ifdef ANSI_DECLARATORS
10459 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10460 #else
10461 int rightofhyperbola(m, fronttri, newsite)
10462 struct mesh *m;
10463 struct otri *fronttri;
10464 vertex newsite;
10465 #endif
10466
10467 {
10468 vertex leftvertex, rightvertex;
10469 REAL dxa, dya, dxb, dyb;
10470
10471 m->hyperbolacount++;
10472
10473 dest(*fronttri, leftvertex);
10474 apex(*fronttri, rightvertex);
10475 if ((leftvertex[1] < rightvertex[1]) ||
10476 ((leftvertex[1] == rightvertex[1]) &&
10477 (leftvertex[0] < rightvertex[0]))) {
10478 if (newsite[0] >= rightvertex[0]) {
10479 return 1;
10480 }
10481 } else {
10482 if (newsite[0] <= leftvertex[0]) {
10483 return 0;
10484 }
10485 }
10486 dxa = leftvertex[0] - newsite[0];
10487 dya = leftvertex[1] - newsite[1];
10488 dxb = rightvertex[0] - newsite[0];
10489 dyb = rightvertex[1] - newsite[1];
10490 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10491 }
10492
10493 #endif
10494
10495 #ifndef REDUCED
10496
10497 #ifdef ANSI_DECLARATORS
10498 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10499 #else
10500 REAL circletop(m, pa, pb, pc, ccwabc)
10501 struct mesh *m;
10502 vertex pa;
10503 vertex pb;
10504 vertex pc;
10505 REAL ccwabc;
10506 #endif
10507
10508 {
10509 REAL xac, yac, xbc, ybc, xab, yab;
10510 REAL aclen2, bclen2, ablen2;
10511
10512 m->circletopcount++;
10513
10514 xac = pa[0] - pc[0];
10515 yac = pa[1] - pc[1];
10516 xbc = pb[0] - pc[0];
10517 ybc = pb[1] - pc[1];
10518 xab = pa[0] - pb[0];
10519 yab = pa[1] - pb[1];
10520 aclen2 = xac * xac + yac * yac;
10521 bclen2 = xbc * xbc + ybc * ybc;
10522 ablen2 = xab * xab + yab * yab;
10523 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10524 / (2.0 * ccwabc);
10525 }
10526
10527 #endif
10528
10529 #ifndef REDUCED
10530
10531 #ifdef ANSI_DECLARATORS
10532 void check4deadevent(struct otri *checktri, struct event **freeevents,
10533 struct event **eventheap, int *heapsize)
10534 #else
10535 void check4deadevent(checktri, freeevents, eventheap, heapsize)
10536 struct otri *checktri;
10537 struct event **freeevents;
10538 struct event **eventheap;
10539 int *heapsize;
10540 #endif
10541
10542 {
10543 struct event *deadevent;
10544 vertex eventvertex;
10545 int eventnum;
10546
10547 org(*checktri, eventvertex);
10548 if (eventvertex != (vertex) NULL) {
10549 deadevent = (struct event *) eventvertex;
10550 eventnum = deadevent->heapposition;
10551 deadevent->eventptr = (VOID *) *freeevents;
10552 *freeevents = deadevent;
10553 eventheapdelete(eventheap, *heapsize, eventnum);
10554 (*heapsize)--;
10555 setorg(*checktri, NULL);
10556 }
10557 }
10558
10559 #endif
10560
10561 #ifndef REDUCED
10562
10563 #ifdef ANSI_DECLARATORS
10564 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10565 vertex searchpoint, struct otri *searchtri)
10566 #else
10567 struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10568 struct mesh *m;
10569 struct splaynode *splaytree;
10570 vertex searchpoint;
10571 struct otri *searchtri;
10572 #endif
10573
10574 {
10575 struct splaynode *child, *grandchild;
10576 struct splaynode *lefttree, *righttree;
10577 struct splaynode *leftright;
10578 vertex checkvertex;
10579 int rightofroot, rightofchild;
10580
10581 if (splaytree == (struct splaynode *) NULL) {
10582 return (struct splaynode *) NULL;
10583 }
10584 dest(splaytree->keyedge, checkvertex);
10585 if (checkvertex == splaytree->keydest) {
10586 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10587 if (rightofroot) {
10588 otricopy(splaytree->keyedge, *searchtri);
10589 child = splaytree->rchild;
10590 } else {
10591 child = splaytree->lchild;
10592 }
10593 if (child == (struct splaynode *) NULL) {
10594 return splaytree;
10595 }
10596 dest(child->keyedge, checkvertex);
10597 if (checkvertex != child->keydest) {
10598 child = splay(m, child, searchpoint, searchtri);
10599 if (child == (struct splaynode *) NULL) {
10600 if (rightofroot) {
10601 splaytree->rchild = (struct splaynode *) NULL;
10602 } else {
10603 splaytree->lchild = (struct splaynode *) NULL;
10604 }
10605 return splaytree;
10606 }
10607 }
10608 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10609 if (rightofchild) {
10610 otricopy(child->keyedge, *searchtri);
10611 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10612 child->rchild = grandchild;
10613 } else {
10614 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10615 child->lchild = grandchild;
10616 }
10617 if (grandchild == (struct splaynode *) NULL) {
10618 if (rightofroot) {
10619 splaytree->rchild = child->lchild;
10620 child->lchild = splaytree;
10621 } else {
10622 splaytree->lchild = child->rchild;
10623 child->rchild = splaytree;
10624 }
10625 return child;
10626 }
10627 if (rightofchild) {
10628 if (rightofroot) {
10629 splaytree->rchild = child->lchild;
10630 child->lchild = splaytree;
10631 } else {
10632 splaytree->lchild = grandchild->rchild;
10633 grandchild->rchild = splaytree;
10634 }
10635 child->rchild = grandchild->lchild;
10636 grandchild->lchild = child;
10637 } else {
10638 if (rightofroot) {
10639 splaytree->rchild = grandchild->lchild;
10640 grandchild->lchild = splaytree;
10641 } else {
10642 splaytree->lchild = child->rchild;
10643 child->rchild = splaytree;
10644 }
10645 child->lchild = grandchild->rchild;
10646 grandchild->rchild = child;
10647 }
10648 return grandchild;
10649 } else {
10650 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10651 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10652
10653 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10654 if (lefttree == (struct splaynode *) NULL) {
10655 return righttree;
10656 } else if (righttree == (struct splaynode *) NULL) {
10657 return lefttree;
10658 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10659 lefttree->rchild = righttree->lchild;
10660 righttree->lchild = lefttree;
10661 return righttree;
10662 } else if (righttree->lchild == (struct splaynode *) NULL) {
10663 righttree->lchild = lefttree->rchild;
10664 lefttree->rchild = righttree;
10665 return lefttree;
10666 } else {
10667
10668 leftright = lefttree->rchild;
10669 while (leftright->rchild != (struct splaynode *) NULL) {
10670 leftright = leftright->rchild;
10671 }
10672 leftright->rchild = righttree;
10673 return lefttree;
10674 }
10675 }
10676 }
10677
10678 #endif
10679
10680 #ifndef REDUCED
10681
10682 #ifdef ANSI_DECLARATORS
10683 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10684 struct otri *newkey, vertex searchpoint)
10685 #else
10686 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10687 struct mesh *m;
10688 struct splaynode *splayroot;
10689 struct otri *newkey;
10690 vertex searchpoint;
10691 #endif
10692
10693 {
10694 struct splaynode *newsplaynode;
10695
10696 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10697 otricopy(*newkey, newsplaynode->keyedge);
10698 dest(*newkey, newsplaynode->keydest);
10699 if (splayroot == (struct splaynode *) NULL) {
10700 newsplaynode->lchild = (struct splaynode *) NULL;
10701 newsplaynode->rchild = (struct splaynode *) NULL;
10702 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10703 newsplaynode->lchild = splayroot;
10704 newsplaynode->rchild = splayroot->rchild;
10705 splayroot->rchild = (struct splaynode *) NULL;
10706 } else {
10707 newsplaynode->lchild = splayroot->lchild;
10708 newsplaynode->rchild = splayroot;
10709 splayroot->lchild = (struct splaynode *) NULL;
10710 }
10711 return newsplaynode;
10712 }
10713
10714 #endif
10715
10716 #ifndef REDUCED
10717
10718 #ifdef ANSI_DECLARATORS
10719 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10720 struct splaynode *splayroot,
10721 struct otri *newkey,
10722 vertex pa, vertex pb, vertex pc, REAL topy)
10723 #else
10724 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10725 struct mesh *m;
10726 struct behavior *b;
10727 struct splaynode *splayroot;
10728 struct otri *newkey;
10729 vertex pa;
10730 vertex pb;
10731 vertex pc;
10732 REAL topy;
10733 #endif
10734
10735 {
10736 REAL ccwabc;
10737 REAL xac, yac, xbc, ybc;
10738 REAL aclen2, bclen2;
10739 REAL searchpoint[2];
10740 struct otri dummytri;
10741
10742 ccwabc = counterclockwise(m, b, pa, pb, pc);
10743 xac = pa[0] - pc[0];
10744 yac = pa[1] - pc[1];
10745 xbc = pb[0] - pc[0];
10746 ybc = pb[1] - pc[1];
10747 aclen2 = xac * xac + yac * yac;
10748 bclen2 = xbc * xbc + ybc * ybc;
10749 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10750 searchpoint[1] = topy;
10751 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10752 newkey, (vertex) searchpoint);
10753 }
10754
10755 #endif
10756
10757 #ifndef REDUCED
10758
10759 #ifdef ANSI_DECLARATORS
10760 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10761 struct otri *bottommost, vertex searchvertex,
10762 struct otri *searchtri, int *farright)
10763 #else
10764 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10765 searchtri, farright)
10766 struct mesh *m;
10767 struct splaynode *splayroot;
10768 struct otri *bottommost;
10769 vertex searchvertex;
10770 struct otri *searchtri;
10771 int *farright;
10772 #endif
10773
10774 {
10775 int farrightflag;
10776 triangle ptr;
10777
10778 otricopy(*bottommost, *searchtri);
10779 splayroot = splay(m, splayroot, searchvertex, searchtri);
10780
10781 farrightflag = 0;
10782 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10783 onextself(*searchtri);
10784 farrightflag = otriequal(*searchtri, *bottommost);
10785 }
10786 *farright = farrightflag;
10787 return splayroot;
10788 }
10789
10790 #endif
10791
10792 #ifndef REDUCED
10793
10794 #ifdef ANSI_DECLARATORS
10795 long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10796 #else
10797 long sweeplinedelaunay(m, b)
10798 struct mesh *m;
10799 struct behavior *b;
10800 #endif
10801
10802 {
10803 struct event **eventheap;
10804 struct event *events;
10805 struct event *freeevents;
10806 struct event *nextevent;
10807 struct event *newevent;
10808 struct splaynode *splayroot;
10809 struct otri bottommost;
10810 struct otri searchtri;
10811 struct otri fliptri;
10812 struct otri lefttri, righttri, farlefttri, farrighttri;
10813 struct otri inserttri;
10814 vertex firstvertex, secondvertex;
10815 vertex nextvertex, lastvertex;
10816 vertex connectvertex;
10817 vertex leftvertex, midvertex, rightvertex;
10818 REAL lefttest, righttest;
10819 int heapsize;
10820 int check4events, farrightflag;
10821 triangle ptr;
10822
10823 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10824 SPLAYNODEPERBLOCK, 0);
10825 splayroot = (struct splaynode *) NULL;
10826
10827 if (b->verbose) {
10828 printf(" Placing vertices in event heap.\n");
10829 }
10830 createeventheap(m, &eventheap, &events, &freeevents);
10831 heapsize = m->invertices;
10832
10833 if (b->verbose) {
10834 printf(" Forming triangulation.\n");
10835 }
10836 maketriangle(m, b, &lefttri);
10837 maketriangle(m, b, &righttri);
10838 bond(lefttri, righttri);
10839 lnextself(lefttri);
10840 lprevself(righttri);
10841 bond(lefttri, righttri);
10842 lnextself(lefttri);
10843 lprevself(righttri);
10844 bond(lefttri, righttri);
10845 firstvertex = (vertex) eventheap[0]->eventptr;
10846 eventheap[0]->eventptr = (VOID *) freeevents;
10847 freeevents = eventheap[0];
10848 eventheapdelete(eventheap, heapsize, 0);
10849 heapsize--;
10850 do {
10851 if (heapsize == 0) {
10852 printf("Error: Input vertices are all identical.\n");
10853 triexit(1);
10854 }
10855 secondvertex = (vertex) eventheap[0]->eventptr;
10856 eventheap[0]->eventptr = (VOID *) freeevents;
10857 freeevents = eventheap[0];
10858 eventheapdelete(eventheap, heapsize, 0);
10859 heapsize--;
10860 if ((firstvertex[0] == secondvertex[0]) &&
10861 (firstvertex[1] == secondvertex[1])) {
10862 if (!b->quiet) {
10863 printf(
10864 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10865 secondvertex[0], secondvertex[1]);
10866 }
10867 setvertextype(secondvertex, UNDEADVERTEX);
10868 m->undeads++;
10869 }
10870 } while ((firstvertex[0] == secondvertex[0]) &&
10871 (firstvertex[1] == secondvertex[1]));
10872 setorg(lefttri, firstvertex);
10873 setdest(lefttri, secondvertex);
10874 setorg(righttri, secondvertex);
10875 setdest(righttri, firstvertex);
10876 lprev(lefttri, bottommost);
10877 lastvertex = secondvertex;
10878 while (heapsize > 0) {
10879 nextevent = eventheap[0];
10880 eventheapdelete(eventheap, heapsize, 0);
10881 heapsize--;
10882 check4events = 1;
10883 if (nextevent->xkey < m->xmin) {
10884 decode(nextevent->eventptr, fliptri);
10885 oprev(fliptri, farlefttri);
10886 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10887 onext(fliptri, farrighttri);
10888 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10889
10890 if (otriequal(farlefttri, bottommost)) {
10891 lprev(fliptri, bottommost);
10892 }
10893 flip(m, b, &fliptri);
10894 setapex(fliptri, NULL);
10895 lprev(fliptri, lefttri);
10896 lnext(fliptri, righttri);
10897 sym(lefttri, farlefttri);
10898
10899 if (randomnation(SAMPLERATE) == 0) {
10900 symself(fliptri);
10901 dest(fliptri, leftvertex);
10902 apex(fliptri, midvertex);
10903 org(fliptri, rightvertex);
10904 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10905 midvertex, rightvertex, nextevent->ykey);
10906 }
10907 } else {
10908 nextvertex = (vertex) nextevent->eventptr;
10909 if ((nextvertex[0] == lastvertex[0]) &&
10910 (nextvertex[1] == lastvertex[1])) {
10911 if (!b->quiet) {
10912 printf(
10913 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10914 nextvertex[0], nextvertex[1]);
10915 }
10916 setvertextype(nextvertex, UNDEADVERTEX);
10917 m->undeads++;
10918 check4events = 0;
10919 } else {
10920 lastvertex = nextvertex;
10921
10922 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10923 &searchtri, &farrightflag);
10924
10925
10926
10927
10928
10929
10930
10931
10932
10933 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10934
10935 otricopy(searchtri, farrighttri);
10936 sym(searchtri, farlefttri);
10937 maketriangle(m, b, &lefttri);
10938 maketriangle(m, b, &righttri);
10939 dest(farrighttri, connectvertex);
10940 setorg(lefttri, connectvertex);
10941 setdest(lefttri, nextvertex);
10942 setorg(righttri, nextvertex);
10943 setdest(righttri, connectvertex);
10944 bond(lefttri, righttri);
10945 lnextself(lefttri);
10946 lprevself(righttri);
10947 bond(lefttri, righttri);
10948 lnextself(lefttri);
10949 lprevself(righttri);
10950 bond(lefttri, farlefttri);
10951 bond(righttri, farrighttri);
10952 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10953 otricopy(lefttri, bottommost);
10954 }
10955
10956 if (randomnation(SAMPLERATE) == 0) {
10957 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10958 } else if (randomnation(SAMPLERATE) == 0) {
10959 lnext(righttri, inserttri);
10960 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10961 }
10962 }
10963 }
10964 nextevent->eventptr = (VOID *) freeevents;
10965 freeevents = nextevent;
10966
10967 if (check4events) {
10968 apex(farlefttri, leftvertex);
10969 dest(lefttri, midvertex);
10970 apex(lefttri, rightvertex);
10971 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10972 if (lefttest > 0.0) {
10973 newevent = freeevents;
10974 freeevents = (struct event *) freeevents->eventptr;
10975 newevent->xkey = m->xminextreme;
10976 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10977 lefttest);
10978 newevent->eventptr = (VOID *) encode(lefttri);
10979 eventheapinsert(eventheap, heapsize, newevent);
10980 heapsize++;
10981 setorg(lefttri, newevent);
10982 }
10983 apex(righttri, leftvertex);
10984 org(righttri, midvertex);
10985 apex(farrighttri, rightvertex);
10986 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10987 if (righttest > 0.0) {
10988 newevent = freeevents;
10989 freeevents = (struct event *) freeevents->eventptr;
10990 newevent->xkey = m->xminextreme;
10991 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10992 righttest);
10993 newevent->eventptr = (VOID *) encode(farrighttri);
10994 eventheapinsert(eventheap, heapsize, newevent);
10995 heapsize++;
10996 setorg(farrighttri, newevent);
10997 }
10998 }
10999 }
11000
11001 pooldeinit(&m->splaynodes);
11002 lprevself(bottommost);
11003 return removeghosts(m, b, &bottommost);
11004 }
11005
11006 #endif
11007
11010
11011
11012
11016
11017
11018
11019
11020
11021
11022 #ifdef ANSI_DECLARATORS
11023 long delaunay(struct mesh *m, struct behavior *b)
11024 #else
11025 long delaunay(m, b)
11026 struct mesh *m;
11027 struct behavior *b;
11028 #endif
11029
11030 {
11031 long hulledges;
11032
11033 m->eextras = 0;
11034 initializetrisubpools(m, b);
11035
11036 #ifdef REDUCED
11037 if (!b->quiet) {
11038 printf(
11039 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11040 }
11041 hulledges = divconqdelaunay(m, b);
11042 #else
11043 if (!b->quiet) {
11044 printf("Constructing Delaunay triangulation ");
11045 if (b->incremental) {
11046 printf("by incremental method.\n");
11047 } else if (b->sweepline) {
11048 printf("by sweepline method.\n");
11049 } else {
11050 printf("by divide-and-conquer method.\n");
11051 }
11052 }
11053 if (b->incremental) {
11054 hulledges = incrementaldelaunay(m, b);
11055 } else if (b->sweepline) {
11056 hulledges = sweeplinedelaunay(m, b);
11057 } else {
11058 hulledges = divconqdelaunay(m, b);
11059 }
11060 #endif
11061
11062 if (m->triangles.items == 0) {
11063
11064 return 0l;
11065 } else {
11066 return hulledges;
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
11092
11093
11094
11095 #ifndef CDT_ONLY
11096
11097 #ifdef TRILIBRARY
11098
11099 #ifdef ANSI_DECLARATORS
11100 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11101 REAL *triangleattriblist, REAL *trianglearealist,
11102 int elements, int corners, int attribs,
11103 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11104 #else
11105 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11106 elements, corners, attribs, segmentlist, segmentmarkerlist,
11107 numberofsegments)
11108 struct mesh *m;
11109 struct behavior *b;
11110 int *trianglelist;
11111 REAL *triangleattriblist;
11112 REAL *trianglearealist;
11113 int elements;
11114 int corners;
11115 int attribs;
11116 int *segmentlist;
11117 int *segmentmarkerlist;
11118 int numberofsegments;
11119 #endif
11120
11121 #else
11122
11123 #ifdef ANSI_DECLARATORS
11124 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11125 char *areafilename, char *polyfilename, FILE *polyfile)
11126 #else
11127 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11128 struct mesh *m;
11129 struct behavior *b;
11130 char *elefilename;
11131 char *areafilename;
11132 char *polyfilename;
11133 FILE *polyfile;
11134 #endif
11135
11136 #endif
11137
11138 {
11139 #ifdef TRILIBRARY
11140 int vertexindex;
11141 int attribindex;
11142 #else
11143 FILE *elefile;
11144 FILE *areafile;
11145 char inputline[INPUTLINESIZE];
11146 char *stringptr;
11147 int areaelements;
11148 #endif
11149 struct otri triangleloop;
11150 struct otri triangleleft;
11151 struct otri checktri;
11152 struct otri checkleft;
11153 struct otri checkneighbor;
11154 struct osub subsegloop;
11155 triangle *vertexarray;
11156 triangle *prevlink;
11157 triangle nexttri;
11158 vertex tdest, tapex;
11159 vertex checkdest, checkapex;
11160 vertex shorg;
11161 vertex killvertex;
11162 vertex segmentorg, segmentdest;
11163 REAL area;
11164 int corner[3];
11165 int end[2];
11166 int killvertexindex;
11167 int incorners;
11168 int segmentmarkers;
11169 int boundmarker;
11170 int aroundvertex;
11171 long hullsize;
11172 int notfound;
11173 long elementnumber, segmentnumber;
11174 int i, j;
11175 triangle ptr;
11176
11177 #ifdef TRILIBRARY
11178 m->inelements = elements;
11179 incorners = corners;
11180 if (incorners < 3) {
11181 printf("Error: Triangles must have at least 3 vertices.\n");
11182 triexit(1);
11183 }
11184 m->eextras = attribs;
11185 #else
11186
11187 if (!b->quiet) {
11188 printf("Opening %s.\n", elefilename);
11189 }
11190 elefile = fopen(elefilename, "r");
11191 if (elefile == (FILE *) NULL) {
11192 printf(" Error: Cannot access file %s.\n", elefilename);
11193 triexit(1);
11194 }
11195
11196
11197 stringptr = readline(inputline, elefile, elefilename);
11198 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11199 stringptr = findfield(stringptr);
11200 if (*stringptr == '\0') {
11201 incorners = 3;
11202 } else {
11203 incorners = (int) strtol(stringptr, &stringptr, 0);
11204 if (incorners < 3) {
11205 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11206 elefilename);
11207 triexit(1);
11208 }
11209 }
11210 stringptr = findfield(stringptr);
11211 if (*stringptr == '\0') {
11212 m->eextras = 0;
11213 } else {
11214 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11215 }
11216 #endif
11217
11218 initializetrisubpools(m, b);
11219
11220
11221 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11222 maketriangle(m, b, &triangleloop);
11223
11224 triangleloop.tri[3] = (triangle) triangleloop.tri;
11225 }
11226
11227 segmentmarkers = 0;
11228 if (b->poly) {
11229 #ifdef TRILIBRARY
11230 m->insegments = numberofsegments;
11231 segmentmarkers = segmentmarkerlist != (int *) NULL;
11232 #else
11233
11234
11235 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11236 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11237 stringptr = findfield(stringptr);
11238 if (*stringptr != '\0') {
11239 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11240 }
11241 #endif
11242
11243
11244 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11245 makesubseg(m, &subsegloop);
11246
11247 subsegloop.ss[2] = (subseg) subsegloop.ss;
11248 }
11249 }
11250
11251 #ifdef TRILIBRARY
11252 vertexindex = 0;
11253 attribindex = 0;
11254 #else
11255 if (b->vararea) {
11256
11257 if (!b->quiet) {
11258 printf("Opening %s.\n", areafilename);
11259 }
11260 areafile = fopen(areafilename, "r");
11261 if (areafile == (FILE *) NULL) {
11262 printf(" Error: Cannot access file %s.\n", areafilename);
11263 triexit(1);
11264 }
11265 stringptr = readline(inputline, areafile, areafilename);
11266 areaelements = (int) strtol(stringptr, &stringptr, 0);
11267 if (areaelements != m->inelements) {
11268 printf("Error: %s and %s disagree on number of triangles.\n",
11269 elefilename, areafilename);
11270 triexit(1);
11271 }
11272 }
11273 #endif
11274
11275 if (!b->quiet) {
11276 printf("Reconstructing mesh.\n");
11277 }
11278
11279
11280
11281 vertexarray = (triangle *) trimalloc(m->vertices.items *
11282 (int) sizeof(triangle));
11283
11284 for (i = 0; i < m->vertices.items; i++) {
11285 vertexarray[i] = (triangle) m->dummytri;
11286 }
11287
11288 if (b->verbose) {
11289 printf(" Assembling triangles.\n");
11290 }
11291
11292
11293 traversalinit(&m->triangles);
11294 triangleloop.tri = triangletraverse(m);
11295 elementnumber = b->firstnumber;
11296 while (triangleloop.tri != (triangle *) NULL) {
11297 #ifdef TRILIBRARY
11298
11299 for (j = 0; j < 3; j++) {
11300 corner[j] = trianglelist[vertexindex++];
11301 if ((corner[j] < b->firstnumber) ||
11302 (corner[j] >= b->firstnumber + m->invertices)) {
11303 printf("Error: Triangle %ld has an invalid vertex index.\n",
11304 elementnumber);
11305 triexit(1);
11306 }
11307 }
11308 #else
11309
11310 stringptr = readline(inputline, elefile, elefilename);
11311 for (j = 0; j < 3; j++) {
11312 stringptr = findfield(stringptr);
11313 if (*stringptr == '\0') {
11314 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11315 elementnumber, j + 1, elefilename);
11316 triexit(1);
11317 } else {
11318 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11319 if ((corner[j] < b->firstnumber) ||
11320 (corner[j] >= b->firstnumber + m->invertices)) {
11321 printf("Error: Triangle %ld has an invalid vertex index.\n",
11322 elementnumber);
11323 triexit(1);
11324 }
11325 }
11326 }
11327 #endif
11328
11329
11330 for (j = 3; j < incorners; j++) {
11331 #ifdef TRILIBRARY
11332 killvertexindex = trianglelist[vertexindex++];
11333 #else
11334 stringptr = findfield(stringptr);
11335 if (*stringptr != '\0') {
11336 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11337 #endif
11338 if ((killvertexindex >= b->firstnumber) &&
11339 (killvertexindex < b->firstnumber + m->invertices)) {
11340
11341 killvertex = getvertex(m, b, killvertexindex);
11342 if (vertextype(killvertex) != DEADVERTEX) {
11343 vertexdealloc(m, killvertex);
11344 }
11345 }
11346 #ifndef TRILIBRARY
11347 }
11348 #endif
11349 }
11350
11351
11352 for (j = 0; j < m->eextras; j++) {
11353 #ifdef TRILIBRARY
11354 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11355 #else
11356 stringptr = findfield(stringptr);
11357 if (*stringptr == '\0') {
11358 setelemattribute(triangleloop, j, 0);
11359 } else {
11360 setelemattribute(triangleloop, j,
11361 (REAL) strtod(stringptr, &stringptr));
11362 }
11363 #endif
11364 }
11365
11366 if (b->vararea) {
11367 #ifdef TRILIBRARY
11368 area = trianglearealist[elementnumber - b->firstnumber];
11369 #else
11370
11371 stringptr = readline(inputline, areafile, areafilename);
11372 stringptr = findfield(stringptr);
11373 if (*stringptr == '\0') {
11374 area = -1.0;
11375 } else {
11376 area = (REAL) strtod(stringptr, &stringptr);
11377 }
11378 #endif
11379 setareabound(triangleloop, area);
11380 }
11381
11382
11383 triangleloop.orient = 0;
11384 setorg(triangleloop, getvertex(m, b, corner[0]));
11385 setdest(triangleloop, getvertex(m, b, corner[1]));
11386 setapex(triangleloop, getvertex(m, b, corner[2]));
11387
11388 for (triangleloop.orient = 0; triangleloop.orient < 3;
11389 triangleloop.orient++) {
11390
11391 aroundvertex = corner[triangleloop.orient];
11392
11393 nexttri = vertexarray[aroundvertex - b->firstnumber];
11394
11395 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11396
11397 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11398 decode(nexttri, checktri);
11399 if (checktri.tri != m->dummytri) {
11400 dest(triangleloop, tdest);
11401 apex(triangleloop, tapex);
11402
11403 do {
11404 dest(checktri, checkdest);
11405 apex(checktri, checkapex);
11406 if (tapex == checkdest) {
11407
11408 lprev(triangleloop, triangleleft);
11409 bond(triangleleft, checktri);
11410 }
11411 if (tdest == checkapex) {
11412
11413 lprev(checktri, checkleft);
11414 bond(triangleloop, checkleft);
11415 }
11416
11417 nexttri = checktri.tri[6 + checktri.orient];
11418 decode(nexttri, checktri);
11419 } while (checktri.tri != m->dummytri);
11420 }
11421 }
11422 triangleloop.tri = triangletraverse(m);
11423 elementnumber++;
11424 }
11425
11426 #ifdef TRILIBRARY
11427 vertexindex = 0;
11428 #else
11429 fclose(elefile);
11430 if (b->vararea) {
11431 fclose(areafile);
11432 }
11433 #endif
11434
11435 hullsize = 0;
11436 if (b->poly) {
11437 if (b->verbose) {
11438 printf(" Marking segments in triangulation.\n");
11439 }
11440
11441
11442 boundmarker = 0;
11443 traversalinit(&m->subsegs);
11444 subsegloop.ss = subsegtraverse(m);
11445 segmentnumber = b->firstnumber;
11446 while (subsegloop.ss != (subseg *) NULL) {
11447 #ifdef TRILIBRARY
11448 end[0] = segmentlist[vertexindex++];
11449 end[1] = segmentlist[vertexindex++];
11450 if (segmentmarkers) {
11451 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11452 }
11453 #else
11454
11455 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11456
11457 stringptr = findfield(stringptr);
11458 if (*stringptr == '\0') {
11459 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11460 polyfilename);
11461 triexit(1);
11462 } else {
11463 end[0] = (int) strtol(stringptr, &stringptr, 0);
11464 }
11465 stringptr = findfield(stringptr);
11466 if (*stringptr == '\0') {
11467 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11468 segmentnumber, polyfilename);
11469 triexit(1);
11470 } else {
11471 end[1] = (int) strtol(stringptr, &stringptr, 0);
11472 }
11473 if (segmentmarkers) {
11474 stringptr = findfield(stringptr);
11475 if (*stringptr == '\0') {
11476 boundmarker = 0;
11477 } else {
11478 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11479 }
11480 }
11481 #endif
11482 for (j = 0; j < 2; j++) {
11483 if ((end[j] < b->firstnumber) ||
11484 (end[j] >= b->firstnumber + m->invertices)) {
11485 printf("Error: Segment %ld has an invalid vertex index.\n",
11486 segmentnumber);
11487 triexit(1);
11488 }
11489 }
11490
11491
11492 subsegloop.ssorient = 0;
11493 segmentorg = getvertex(m, b, end[0]);
11494 segmentdest = getvertex(m, b, end[1]);
11495 setsorg(subsegloop, segmentorg);
11496 setsdest(subsegloop, segmentdest);
11497 setsegorg(subsegloop, segmentorg);
11498 setsegdest(subsegloop, segmentdest);
11499 setmark(subsegloop, boundmarker);
11500
11501 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11502 subsegloop.ssorient++) {
11503
11504 aroundvertex = end[1 - subsegloop.ssorient];
11505
11506 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11507 nexttri = vertexarray[aroundvertex - b->firstnumber];
11508 decode(nexttri, checktri);
11509 sorg(subsegloop, shorg);
11510 notfound = 1;
11511
11512
11513
11514
11515
11516
11517
11518 while (notfound && (checktri.tri != m->dummytri)) {
11519 dest(checktri, checkdest);
11520 if (shorg == checkdest) {
11521
11522 *prevlink = checktri.tri[6 + checktri.orient];
11523
11524 tsbond(checktri, subsegloop);
11525
11526 sym(checktri, checkneighbor);
11527 if (checkneighbor.tri == m->dummytri) {
11528
11529
11530
11531 insertsubseg(m, b, &checktri, 1);
11532 hullsize++;
11533 }
11534 notfound = 0;
11535 }
11536
11537 prevlink = &checktri.tri[6 + checktri.orient];
11538 nexttri = checktri.tri[6 + checktri.orient];
11539 decode(nexttri, checktri);
11540 }
11541 }
11542 subsegloop.ss = subsegtraverse(m);
11543 segmentnumber++;
11544 }
11545 }
11546
11547
11548
11549 for (i = 0; i < m->vertices.items; i++) {
11550
11551 nexttri = vertexarray[i];
11552 decode(nexttri, checktri);
11553 while (checktri.tri != m->dummytri) {
11554
11555
11556 nexttri = checktri.tri[6 + checktri.orient];
11557
11558 tsdissolve(checktri);
11559 sym(checktri, checkneighbor);
11560 if (checkneighbor.tri == m->dummytri) {
11561 insertsubseg(m, b, &checktri, 1);
11562 hullsize++;
11563 }
11564 decode(nexttri, checktri);
11565 }
11566 }
11567
11568 trifree((VOID *) vertexarray);
11569 return hullsize;
11570 }
11571
11572 #endif
11573
11576
11577
11578
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599 #ifdef ANSI_DECLARATORS
11600 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11601 struct otri *searchtri,
11602 vertex searchpoint)
11603 #else
11604 enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11605 struct mesh *m;
11606 struct behavior *b;
11607 struct otri *searchtri;
11608 vertex searchpoint;
11609 #endif
11610
11611 {
11612 struct otri checktri;
11613 vertex startvertex;
11614 vertex leftvertex, rightvertex;
11615 REAL leftccw, rightccw;
11616 int leftflag, rightflag;
11617 triangle ptr;
11618
11619 org(*searchtri, startvertex);
11620 dest(*searchtri, rightvertex);
11621 apex(*searchtri, leftvertex);
11622
11623 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11624 leftflag = leftccw > 0.0;
11625
11626 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11627 rightflag = rightccw > 0.0;
11628 if (leftflag && rightflag) {
11629
11630
11631 onext(*searchtri, checktri);
11632 if (checktri.tri == m->dummytri) {
11633 leftflag = 0;
11634 } else {
11635 rightflag = 0;
11636 }
11637 }
11638 while (leftflag) {
11639
11640 onextself(*searchtri);
11641 if (searchtri->tri == m->dummytri) {
11642 printf("Internal error in finddirection(): Unable to find a\n");
11643 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11644 startvertex[1]);
11645 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11646 internalerror();
11647 }
11648 apex(*searchtri, leftvertex);
11649 rightccw = leftccw;
11650 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11651 leftflag = leftccw > 0.0;
11652 }
11653 while (rightflag) {
11654
11655 oprevself(*searchtri);
11656 if (searchtri->tri == m->dummytri) {
11657 printf("Internal error in finddirection(): Unable to find a\n");
11658 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11659 startvertex[1]);
11660 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11661 internalerror();
11662 }
11663 dest(*searchtri, rightvertex);
11664 leftccw = rightccw;
11665 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11666 rightflag = rightccw > 0.0;
11667 }
11668 if (leftccw == 0.0) {
11669 return LEFTCOLLINEAR;
11670 } else if (rightccw == 0.0) {
11671 return RIGHTCOLLINEAR;
11672 } else {
11673 return WITHIN;
11674 }
11675 }
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694 #ifdef ANSI_DECLARATORS
11695 void segmentintersection(struct mesh *m, struct behavior *b,
11696 struct otri *splittri, struct osub *splitsubseg,
11697 vertex endpoint2)
11698 #else
11699 void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11700 struct mesh *m;
11701 struct behavior *b;
11702 struct otri *splittri;
11703 struct osub *splitsubseg;
11704 vertex endpoint2;
11705 #endif
11706
11707 {
11708 struct osub opposubseg;
11709 vertex endpoint1;
11710 vertex torg, tdest;
11711 vertex leftvertex, rightvertex;
11712 vertex newvertex;
11713 enum insertvertexresult success;
11714 enum finddirectionresult collinear;
11715 REAL ex, ey;
11716 REAL tx, ty;
11717 REAL etx, ety;
11718 REAL split, denom;
11719 int i;
11720 triangle ptr;
11721 subseg sptr;
11722
11723
11724 apex(*splittri, endpoint1);
11725 org(*splittri, torg);
11726 dest(*splittri, tdest);
11727
11728 tx = tdest[0] - torg[0];
11729 ty = tdest[1] - torg[1];
11730 ex = endpoint2[0] - endpoint1[0];
11731 ey = endpoint2[1] - endpoint1[1];
11732 etx = torg[0] - endpoint2[0];
11733 ety = torg[1] - endpoint2[1];
11734 denom = ty * ex - tx * ey;
11735 if (denom == 0.0) {
11736 printf("Internal error in segmentintersection():");
11737 printf(" Attempt to find intersection of parallel segments.\n");
11738 internalerror();
11739 }
11740 split = (ey * etx - ex * ety) / denom;
11741
11742 newvertex = (vertex) poolalloc(&m->vertices);
11743
11744 for (i = 0; i < 2 + m->nextras; i++) {
11745 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11746 }
11747 setvertexmark(newvertex, mark(*splitsubseg));
11748 setvertextype(newvertex, INPUTVERTEX);
11749 if (b->verbose > 1) {
11750 printf(
11751 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11752 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11753 }
11754
11755 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11756 if (success != SUCCESSFULVERTEX) {
11757 printf("Internal error in segmentintersection():\n");
11758 printf(" Failure to split a segment.\n");
11759 internalerror();
11760 }
11761
11762 setvertex2tri(newvertex, encode(*splittri));
11763 if (m->steinerleft > 0) {
11764 m->steinerleft--;
11765 }
11766
11767
11768 ssymself(*splitsubseg);
11769 spivot(*splitsubseg, opposubseg);
11770 sdissolve(*splitsubseg);
11771 sdissolve(opposubseg);
11772 do {
11773 setsegorg(*splitsubseg, newvertex);
11774 snextself(*splitsubseg);
11775 } while (splitsubseg->ss != m->dummysub);
11776 do {
11777 setsegorg(opposubseg, newvertex);
11778 snextself(opposubseg);
11779 } while (opposubseg.ss != m->dummysub);
11780
11781
11782
11783 collinear = finddirection(m, b, splittri, endpoint1);
11784 dest(*splittri, rightvertex);
11785 apex(*splittri, leftvertex);
11786 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11787 onextself(*splittri);
11788 } else if ((rightvertex[0] != endpoint1[0]) ||
11789 (rightvertex[1] != endpoint1[1])) {
11790 printf("Internal error in segmentintersection():\n");
11791 printf(" Topological inconsistency after splitting a segment.\n");
11792 internalerror();
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
11818
11819
11820
11821 #ifdef ANSI_DECLARATORS
11822 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11823 vertex endpoint2, int newmark)
11824 #else
11825 int scoutsegment(m, b, searchtri, endpoint2, newmark)
11826 struct mesh *m;
11827 struct behavior *b;
11828 struct otri *searchtri;
11829 vertex endpoint2;
11830 int newmark;
11831 #endif
11832
11833 {
11834 struct otri crosstri;
11835 struct osub crosssubseg;
11836 vertex leftvertex, rightvertex;
11837 enum finddirectionresult collinear;
11838 subseg sptr;
11839
11840 collinear = finddirection(m, b, searchtri, endpoint2);
11841 dest(*searchtri, rightvertex);
11842 apex(*searchtri, leftvertex);
11843 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11844 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11845
11846 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11847 lprevself(*searchtri);
11848 }
11849
11850 insertsubseg(m, b, searchtri, newmark);
11851 return 1;
11852 } else if (collinear == LEFTCOLLINEAR) {
11853
11854
11855 lprevself(*searchtri);
11856 insertsubseg(m, b, searchtri, newmark);
11857
11858 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11859 } else if (collinear == RIGHTCOLLINEAR) {
11860
11861 insertsubseg(m, b, searchtri, newmark);
11862
11863 lnextself(*searchtri);
11864
11865 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11866 } else {
11867 lnext(*searchtri, crosstri);
11868 tspivot(crosstri, crosssubseg);
11869
11870 if (crosssubseg.ss == m->dummysub) {
11871 return 0;
11872 } else {
11873
11874 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11875 otricopy(crosstri, *searchtri);
11876 insertsubseg(m, b, searchtri, newmark);
11877
11878 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11879 }
11880 }
11881 }
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902 #ifndef REDUCED
11903 #ifndef CDT_ONLY
11904
11905 #ifdef ANSI_DECLARATORS
11906 void conformingedge(struct mesh *m, struct behavior *b,
11907 vertex endpoint1, vertex endpoint2, int newmark)
11908 #else
11909 void conformingedge(m, b, endpoint1, endpoint2, newmark)
11910 struct mesh *m;
11911 struct behavior *b;
11912 vertex endpoint1;
11913 vertex endpoint2;
11914 int newmark;
11915 #endif
11916
11917 {
11918 struct otri searchtri1, searchtri2;
11919 struct osub brokensubseg;
11920 vertex newvertex;
11921 vertex midvertex1, midvertex2;
11922 enum insertvertexresult success;
11923 int i;
11924 subseg sptr;
11925
11926 if (b->verbose > 2) {
11927 printf("Forcing segment into triangulation by recursive splitting:\n");
11928 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11929 endpoint2[0], endpoint2[1]);
11930 }
11931
11932 newvertex = (vertex) poolalloc(&m->vertices);
11933
11934 for (i = 0; i < 2 + m->nextras; i++) {
11935 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11936 }
11937 setvertexmark(newvertex, newmark);
11938 setvertextype(newvertex, SEGMENTVERTEX);
11939
11940 searchtri1.tri = m->dummytri;
11941
11942 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11943 0, 0);
11944 if (success == DUPLICATEVERTEX) {
11945 if (b->verbose > 2) {
11946 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11947 newvertex[0], newvertex[1]);
11948 }
11949
11950 vertexdealloc(m, newvertex);
11951 org(searchtri1, newvertex);
11952 } else {
11953 if (success == VIOLATINGVERTEX) {
11954 if (b->verbose > 2) {
11955 printf(" Two segments intersect at (%.12g, %.12g).\n",
11956 newvertex[0], newvertex[1]);
11957 }
11958
11959 tspivot(searchtri1, brokensubseg);
11960 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11961 0, 0);
11962 if (success != SUCCESSFULVERTEX) {
11963 printf("Internal error in conformingedge():\n");
11964 printf(" Failure to split a segment.\n");
11965 internalerror();
11966 }
11967 }
11968
11969 if (m->steinerleft > 0) {
11970 m->steinerleft--;
11971 }
11972 }
11973 otricopy(searchtri1, searchtri2);
11974
11975
11976
11977
11978
11979 finddirection(m, b, &searchtri2, endpoint2);
11980 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11981
11982
11983 org(searchtri1, midvertex1);
11984 conformingedge(m, b, midvertex1, endpoint1, newmark);
11985 }
11986 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11987
11988
11989 org(searchtri2, midvertex2);
11990 conformingedge(m, b, midvertex2, endpoint2, newmark);
11991 }
11992 }
11993
11994 #endif
11995 #endif
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
12032
12033
12034
12035 #ifdef ANSI_DECLARATORS
12036 void delaunayfixup(struct mesh *m, struct behavior *b,
12037 struct otri *fixuptri, int leftside)
12038 #else
12039 void delaunayfixup(m, b, fixuptri, leftside)
12040 struct mesh *m;
12041 struct behavior *b;
12042 struct otri *fixuptri;
12043 int leftside;
12044 #endif
12045
12046 {
12047 struct otri neartri;
12048 struct otri fartri;
12049 struct osub faredge;
12050 vertex nearvertex, leftvertex, rightvertex, farvertex;
12051 triangle ptr;
12052 subseg sptr;
12053
12054 lnext(*fixuptri, neartri);
12055 sym(neartri, fartri);
12056
12057 if (fartri.tri == m->dummytri) {
12058 return;
12059 }
12060 tspivot(neartri, faredge);
12061 if (faredge.ss != m->dummysub) {
12062 return;
12063 }
12064
12065 apex(neartri, nearvertex);
12066 org(neartri, leftvertex);
12067 dest(neartri, rightvertex);
12068 apex(fartri, farvertex);
12069
12070 if (leftside) {
12071 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12072
12073
12074 return;
12075 }
12076 } else {
12077 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12078
12079
12080 return;
12081 }
12082 }
12083 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12084
12085
12086
12087
12088 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12089 0.0) {
12090 return;
12091 }
12092
12093 }
12094 flip(m, b, &neartri);
12095 lprevself(*fixuptri);
12096
12097 delaunayfixup(m, b, fixuptri, leftside);
12098 delaunayfixup(m, b, &fartri, leftside);
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
12152
12153
12154
12155 #ifdef ANSI_DECLARATORS
12156 void constrainededge(struct mesh *m, struct behavior *b,
12157 struct otri *starttri, vertex endpoint2, int newmark)
12158 #else
12159 void constrainededge(m, b, starttri, endpoint2, newmark)
12160 struct mesh *m;
12161 struct behavior *b;
12162 struct otri *starttri;
12163 vertex endpoint2;
12164 int newmark;
12165 #endif
12166
12167 {
12168 struct otri fixuptri, fixuptri2;
12169 struct osub crosssubseg;
12170 vertex endpoint1;
12171 vertex farvertex;
12172 REAL area;
12173 int collision;
12174 int done;
12175 triangle ptr;
12176 subseg sptr;
12177
12178 org(*starttri, endpoint1);
12179 lnext(*starttri, fixuptri);
12180 flip(m, b, &fixuptri);
12181
12182
12183 collision = 0;
12184 done = 0;
12185 do {
12186 org(fixuptri, farvertex);
12187
12188
12189 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12190 oprev(fixuptri, fixuptri2);
12191
12192 delaunayfixup(m, b, &fixuptri, 0);
12193 delaunayfixup(m, b, &fixuptri2, 1);
12194 done = 1;
12195 } else {
12196
12197
12198
12199 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12200 if (area == 0.0) {
12201
12202 collision = 1;
12203 oprev(fixuptri, fixuptri2);
12204
12205 delaunayfixup(m, b, &fixuptri, 0);
12206 delaunayfixup(m, b, &fixuptri2, 1);
12207 done = 1;
12208 } else {
12209 if (area > 0.0) {
12210 oprev(fixuptri, fixuptri2);
12211
12212
12213 delaunayfixup(m, b, &fixuptri2, 1);
12214
12215
12216
12217 lprevself(fixuptri);
12218 } else {
12219 delaunayfixup(m, b, &fixuptri, 0);
12220
12221
12222
12223 oprevself(fixuptri);
12224 }
12225
12226 tspivot(fixuptri, crosssubseg);
12227 if (crosssubseg.ss == m->dummysub) {
12228 flip(m, b, &fixuptri);
12229 } else {
12230
12231 collision = 1;
12232
12233 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12234 done = 1;
12235 }
12236 }
12237 }
12238 } while (!done);
12239
12240 insertsubseg(m, b, &fixuptri, newmark);
12241
12242
12243 if (collision) {
12244
12245 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12246 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12247 }
12248 }
12249 }
12250
12251
12252
12253
12254
12255
12256
12257 #ifdef ANSI_DECLARATORS
12258 void insertsegment(struct mesh *m, struct behavior *b,
12259 vertex endpoint1, vertex endpoint2, int newmark)
12260 #else
12261 void insertsegment(m, b, endpoint1, endpoint2, newmark)
12262 struct mesh *m;
12263 struct behavior *b;
12264 vertex endpoint1;
12265 vertex endpoint2;
12266 int newmark;
12267 #endif
12268
12269 {
12270 struct otri searchtri1, searchtri2;
12271 triangle encodedtri;
12272 vertex checkvertex;
12273 triangle ptr;
12274
12275 if (b->verbose > 1) {
12276 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12277 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12278 }
12279
12280
12281 checkvertex = (vertex) NULL;
12282 encodedtri = vertex2tri(endpoint1);
12283 if (encodedtri != (triangle) NULL) {
12284 decode(encodedtri, searchtri1);
12285 org(searchtri1, checkvertex);
12286 }
12287 if (checkvertex != endpoint1) {
12288
12289 searchtri1.tri = m->dummytri;
12290 searchtri1.orient = 0;
12291 symself(searchtri1);
12292
12293 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12294 printf(
12295 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12296 printf(" (%.12g, %.12g) in triangulation.\n",
12297 endpoint1[0], endpoint1[1]);
12298 internalerror();
12299 }
12300 }
12301
12302 otricopy(searchtri1, m->recenttri);
12303
12304
12305 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12306
12307 return;
12308 }
12309
12310
12311 org(searchtri1, endpoint1);
12312
12313
12314 checkvertex = (vertex) NULL;
12315 encodedtri = vertex2tri(endpoint2);
12316 if (encodedtri != (triangle) NULL) {
12317 decode(encodedtri, searchtri2);
12318 org(searchtri2, checkvertex);
12319 }
12320 if (checkvertex != endpoint2) {
12321
12322 searchtri2.tri = m->dummytri;
12323 searchtri2.orient = 0;
12324 symself(searchtri2);
12325
12326 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12327 printf(
12328 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12329 printf(" (%.12g, %.12g) in triangulation.\n",
12330 endpoint2[0], endpoint2[1]);
12331 internalerror();
12332 }
12333 }
12334
12335 otricopy(searchtri2, m->recenttri);
12336
12337
12338 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12339
12340 return;
12341 }
12342
12343
12344 org(searchtri2, endpoint2);
12345
12346 #ifndef REDUCED
12347 #ifndef CDT_ONLY
12348 if (b->splitseg) {
12349
12350 conformingedge(m, b, endpoint1, endpoint2, newmark);
12351 } else {
12352 #endif
12353 #endif
12354
12355 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12356 #ifndef REDUCED
12357 #ifndef CDT_ONLY
12358 }
12359 #endif
12360 #endif
12361 }
12362
12363
12364
12365
12366
12367
12368
12369 #ifdef ANSI_DECLARATORS
12370 void markhull(struct mesh *m, struct behavior *b)
12371 #else
12372 void markhull(m, b)
12373 struct mesh *m;
12374 struct behavior *b;
12375 #endif
12376
12377 {
12378 struct otri hulltri;
12379 struct otri nexttri;
12380 struct otri starttri;
12381 triangle ptr;
12382
12383
12384 hulltri.tri = m->dummytri;
12385 hulltri.orient = 0;
12386 symself(hulltri);
12387
12388 otricopy(hulltri, starttri);
12389
12390 do {
12391
12392 insertsubseg(m, b, &hulltri, 1);
12393
12394 lnextself(hulltri);
12395 oprev(hulltri, nexttri);
12396 while (nexttri.tri != m->dummytri) {
12397 otricopy(nexttri, hulltri);
12398 oprev(hulltri, nexttri);
12399 }
12400 } while (!otriequal(hulltri, starttri));
12401 }
12402
12403
12404
12405
12406
12407
12408
12409
12410
12411
12412
12413 #ifdef TRILIBRARY
12414
12415 #ifdef ANSI_DECLARATORS
12416 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12417 int *segmentmarkerlist, int numberofsegments)
12418 #else
12419 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12420 struct mesh *m;
12421 struct behavior *b;
12422 int *segmentlist;
12423 int *segmentmarkerlist;
12424 int numberofsegments;
12425 #endif
12426
12427 #else
12428
12429 #ifdef ANSI_DECLARATORS
12430 void formskeleton(struct mesh *m, struct behavior *b,
12431 FILE *polyfile, char *polyfilename)
12432 #else
12433 void formskeleton(m, b, polyfile, polyfilename)
12434 struct mesh *m;
12435 struct behavior *b;
12436 FILE *polyfile;
12437 char *polyfilename;
12438 #endif
12439
12440 #endif
12441
12442 {
12443 #ifdef TRILIBRARY
12444 char polyfilename[6];
12445 int index;
12446 #else
12447 char inputline[INPUTLINESIZE];
12448 char *stringptr;
12449 #endif
12450 vertex endpoint1, endpoint2;
12451 int segmentmarkers;
12452 int end1, end2;
12453 int boundmarker;
12454 int i;
12455
12456 if (b->poly) {
12457 if (!b->quiet) {
12458 printf("Recovering segments in Delaunay triangulation.\n");
12459 }
12460 #ifdef TRILIBRARY
12461 strcpy(polyfilename, "input");
12462 m->insegments = numberofsegments;
12463 segmentmarkers = segmentmarkerlist != (int *) NULL;
12464 index = 0;
12465 #else
12466
12467
12468 stringptr = readline(inputline, polyfile, polyfilename);
12469 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12470 stringptr = findfield(stringptr);
12471 if (*stringptr == '\0') {
12472 segmentmarkers = 0;
12473 } else {
12474 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12475 }
12476 #endif
12477
12478
12479 if (m->triangles.items == 0) {
12480 return;
12481 }
12482
12483
12484
12485 if (m->insegments > 0) {
12486 makevertexmap(m, b);
12487 if (b->verbose) {
12488 printf(" Recovering PSLG segments.\n");
12489 }
12490 }
12491
12492 boundmarker = 0;
12493
12494 for (i = 0; i < m->insegments; i++) {
12495 #ifdef TRILIBRARY
12496 end1 = segmentlist[index++];
12497 end2 = segmentlist[index++];
12498 if (segmentmarkers) {
12499 boundmarker = segmentmarkerlist[i];
12500 }
12501 #else
12502 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12503 stringptr = findfield(stringptr);
12504 if (*stringptr == '\0') {
12505 printf("Error: Segment %d has no endpoints in %s.\n",
12506 b->firstnumber + i, polyfilename);
12507 triexit(1);
12508 } else {
12509 end1 = (int) strtol(stringptr, &stringptr, 0);
12510 }
12511 stringptr = findfield(stringptr);
12512 if (*stringptr == '\0') {
12513 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12514 b->firstnumber + i, polyfilename);
12515 triexit(1);
12516 } else {
12517 end2 = (int) strtol(stringptr, &stringptr, 0);
12518 }
12519 if (segmentmarkers) {
12520 stringptr = findfield(stringptr);
12521 if (*stringptr == '\0') {
12522 boundmarker = 0;
12523 } else {
12524 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12525 }
12526 }
12527 #endif
12528 if ((end1 < b->firstnumber) ||
12529 (end1 >= b->firstnumber + m->invertices)) {
12530 if (!b->quiet) {
12531 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12532 b->firstnumber + i, polyfilename);
12533 }
12534 } else if ((end2 < b->firstnumber) ||
12535 (end2 >= b->firstnumber + m->invertices)) {
12536 if (!b->quiet) {
12537 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12538 b->firstnumber + i, polyfilename);
12539 }
12540 } else {
12541
12542 endpoint1 = getvertex(m, b, end1);
12543 endpoint2 = getvertex(m, b, end2);
12544 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12545 if (!b->quiet) {
12546 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12547 b->firstnumber + i, polyfilename);
12548 }
12549 } else {
12550 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12551 }
12552 }
12553 }
12554 } else {
12555 m->insegments = 0;
12556 }
12557 if (b->convex || !b->poly) {
12558
12559 if (b->verbose) {
12560 printf(" Enclosing convex hull with segments.\n");
12561 }
12562 markhull(m, b);
12563 }
12564 }
12565
12568
12569
12570
12574
12575
12576
12577
12578
12579
12580
12581
12582 #ifdef ANSI_DECLARATORS
12583 void infecthull(struct mesh *m, struct behavior *b)
12584 #else
12585 void infecthull(m, b)
12586 struct mesh *m;
12587 struct behavior *b;
12588 #endif
12589
12590 {
12591 struct otri hulltri;
12592 struct otri nexttri;
12593 struct otri starttri;
12594 struct osub hullsubseg;
12595 triangle **deadtriangle;
12596 vertex horg, hdest;
12597 triangle ptr;
12598 subseg sptr;
12599
12600 if (b->verbose) {
12601 printf(" Marking concavities (external triangles) for elimination.\n");
12602 }
12603
12604 hulltri.tri = m->dummytri;
12605 hulltri.orient = 0;
12606 symself(hulltri);
12607
12608 otricopy(hulltri, starttri);
12609
12610 do {
12611
12612 if (!infected(hulltri)) {
12613
12614 tspivot(hulltri, hullsubseg);
12615 if (hullsubseg.ss == m->dummysub) {
12616
12617 if (!infected(hulltri)) {
12618 infect(hulltri);
12619 deadtriangle = (triangle **) poolalloc(&m->viri);
12620 *deadtriangle = hulltri.tri;
12621 }
12622 } else {
12623
12624 if (mark(hullsubseg) == 0) {
12625 setmark(hullsubseg, 1);
12626 org(hulltri, horg);
12627 dest(hulltri, hdest);
12628 if (vertexmark(horg) == 0) {
12629 setvertexmark(horg, 1);
12630 }
12631 if (vertexmark(hdest) == 0) {
12632 setvertexmark(hdest, 1);
12633 }
12634 }
12635 }
12636 }
12637
12638 lnextself(hulltri);
12639 oprev(hulltri, nexttri);
12640 while (nexttri.tri != m->dummytri) {
12641 otricopy(nexttri, hulltri);
12642 oprev(hulltri, nexttri);
12643 }
12644 } while (!otriequal(hulltri, starttri));
12645 }
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663
12664 #ifdef ANSI_DECLARATORS
12665 void plague(struct mesh *m, struct behavior *b)
12666 #else
12667 void plague(m, b)
12668 struct mesh *m;
12669 struct behavior *b;
12670 #endif
12671
12672 {
12673 struct otri testtri;
12674 struct otri neighbor;
12675 triangle **virusloop;
12676 triangle **deadtriangle;
12677 struct osub neighborsubseg;
12678 vertex testvertex;
12679 vertex norg, ndest;
12680 vertex deadorg, deaddest, deadapex;
12681 int killorg;
12682 triangle ptr;
12683 subseg sptr;
12684
12685 if (b->verbose) {
12686 printf(" Marking neighbors of marked triangles.\n");
12687 }
12688
12689
12690 traversalinit(&m->viri);
12691 virusloop = (triangle **) traverse(&m->viri);
12692 while (virusloop != (triangle **) NULL) {
12693 testtri.tri = *virusloop;
12694
12695
12696
12697
12698 uninfect(testtri);
12699 if (b->verbose > 2) {
12700
12701
12702 testtri.orient = 0;
12703 org(testtri, deadorg);
12704 dest(testtri, deaddest);
12705 apex(testtri, deadapex);
12706 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12707 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12708 deadapex[0], deadapex[1]);
12709 }
12710
12711 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12712
12713 sym(testtri, neighbor);
12714
12715 tspivot(testtri, neighborsubseg);
12716
12717 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12718 if (neighborsubseg.ss != m->dummysub) {
12719
12720
12721
12722 subsegdealloc(m, neighborsubseg.ss);
12723 if (neighbor.tri != m->dummytri) {
12724
12725
12726 uninfect(neighbor);
12727 tsdissolve(neighbor);
12728 infect(neighbor);
12729 }
12730 }
12731 } else {
12732 if (neighborsubseg.ss == m->dummysub) {
12733
12734
12735 if (b->verbose > 2) {
12736 org(neighbor, deadorg);
12737 dest(neighbor, deaddest);
12738 apex(neighbor, deadapex);
12739 printf(
12740 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12741 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12742 deadapex[0], deadapex[1]);
12743 }
12744 infect(neighbor);
12745
12746 deadtriangle = (triangle **) poolalloc(&m->viri);
12747 *deadtriangle = neighbor.tri;
12748 } else {
12749
12750 stdissolve(neighborsubseg);
12751
12752 if (mark(neighborsubseg) == 0) {
12753 setmark(neighborsubseg, 1);
12754 }
12755 org(neighbor, norg);
12756 dest(neighbor, ndest);
12757 if (vertexmark(norg) == 0) {
12758 setvertexmark(norg, 1);
12759 }
12760 if (vertexmark(ndest) == 0) {
12761 setvertexmark(ndest, 1);
12762 }
12763 }
12764 }
12765 }
12766
12767
12768 infect(testtri);
12769 virusloop = (triangle **) traverse(&m->viri);
12770 }
12771
12772 if (b->verbose) {
12773 printf(" Deleting marked triangles.\n");
12774 }
12775
12776 traversalinit(&m->viri);
12777 virusloop = (triangle **) traverse(&m->viri);
12778 while (virusloop != (triangle **) NULL) {
12779 testtri.tri = *virusloop;
12780
12781
12782
12783
12784 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12785 org(testtri, testvertex);
12786
12787 if (testvertex != (vertex) NULL) {
12788 killorg = 1;
12789
12790 setorg(testtri, NULL);
12791
12792 onext(testtri, neighbor);
12793
12794 while ((neighbor.tri != m->dummytri) &&
12795 (!otriequal(neighbor, testtri))) {
12796 if (infected(neighbor)) {
12797
12798 setorg(neighbor, NULL);
12799 } else {
12800
12801 killorg = 0;
12802 }
12803
12804 onextself(neighbor);
12805 }
12806
12807 if (neighbor.tri == m->dummytri) {
12808
12809 oprev(testtri, neighbor);
12810
12811 while (neighbor.tri != m->dummytri) {
12812 if (infected(neighbor)) {
12813
12814 setorg(neighbor, NULL);
12815 } else {
12816
12817 killorg = 0;
12818 }
12819
12820 oprevself(neighbor);
12821 }
12822 }
12823 if (killorg) {
12824 if (b->verbose > 1) {
12825 printf(" Deleting vertex (%.12g, %.12g)\n",
12826 testvertex[0], testvertex[1]);
12827 }
12828 setvertextype(testvertex, UNDEADVERTEX);
12829 m->undeads++;
12830 }
12831 }
12832 }
12833
12834
12835
12836 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12837 sym(testtri, neighbor);
12838 if (neighbor.tri == m->dummytri) {
12839
12840
12841
12842 m->hullsize--;
12843 } else {
12844
12845 dissolve(neighbor);
12846
12847
12848 m->hullsize++;
12849 }
12850 }
12851
12852 triangledealloc(m, testtri.tri);
12853 virusloop = (triangle **) traverse(&m->viri);
12854 }
12855
12856 poolrestart(&m->viri);
12857 }
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870
12871
12872
12873
12874 #ifdef ANSI_DECLARATORS
12875 void regionplague(struct mesh *m, struct behavior *b,
12876 REAL attribute, REAL area)
12877 #else
12878 void regionplague(m, b, attribute, area)
12879 struct mesh *m;
12880 struct behavior *b;
12881 REAL attribute;
12882 REAL area;
12883 #endif
12884
12885 {
12886 struct otri testtri;
12887 struct otri neighbor;
12888 triangle **virusloop;
12889 triangle **regiontri;
12890 struct osub neighborsubseg;
12891 vertex regionorg, regiondest, regionapex;
12892 triangle ptr;
12893 subseg sptr;
12894
12895 if (b->verbose > 1) {
12896 printf(" Marking neighbors of marked triangles.\n");
12897 }
12898
12899
12900
12901 traversalinit(&m->viri);
12902 virusloop = (triangle **) traverse(&m->viri);
12903 while (virusloop != (triangle **) NULL) {
12904 testtri.tri = *virusloop;
12905
12906
12907
12908
12909 uninfect(testtri);
12910 if (b->regionattrib) {
12911
12912 setelemattribute(testtri, m->eextras, attribute);
12913 }
12914 if (b->vararea) {
12915
12916 setareabound(testtri, area);
12917 }
12918 if (b->verbose > 2) {
12919
12920
12921 testtri.orient = 0;
12922 org(testtri, regionorg);
12923 dest(testtri, regiondest);
12924 apex(testtri, regionapex);
12925 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12926 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12927 regionapex[0], regionapex[1]);
12928 }
12929
12930 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12931
12932 sym(testtri, neighbor);
12933
12934 tspivot(testtri, neighborsubseg);
12935
12936
12937 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12938 && (neighborsubseg.ss == m->dummysub)) {
12939 if (b->verbose > 2) {
12940 org(neighbor, regionorg);
12941 dest(neighbor, regiondest);
12942 apex(neighbor, regionapex);
12943 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12944 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12945 regionapex[0], regionapex[1]);
12946 }
12947
12948 infect(neighbor);
12949
12950 regiontri = (triangle **) poolalloc(&m->viri);
12951 *regiontri = neighbor.tri;
12952 }
12953 }
12954
12955
12956 infect(testtri);
12957 virusloop = (triangle **) traverse(&m->viri);
12958 }
12959
12960
12961 if (b->verbose > 1) {
12962 printf(" Unmarking marked triangles.\n");
12963 }
12964 traversalinit(&m->viri);
12965 virusloop = (triangle **) traverse(&m->viri);
12966 while (virusloop != (triangle **) NULL) {
12967 testtri.tri = *virusloop;
12968 uninfect(testtri);
12969 virusloop = (triangle **) traverse(&m->viri);
12970 }
12971
12972 poolrestart(&m->viri);
12973 }
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987 #ifdef ANSI_DECLARATORS
12988 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12989 REAL *regionlist, int regions)
12990 #else
12991 void carveholes(m, b, holelist, holes, regionlist, regions)
12992 struct mesh *m;
12993 struct behavior *b;
12994 REAL *holelist;
12995 int holes;
12996 REAL *regionlist;
12997 int regions;
12998 #endif
12999
13000 {
13001 struct otri searchtri;
13002 struct otri triangleloop;
13003 struct otri *regiontris;
13004 triangle **holetri;
13005 triangle **regiontri;
13006 vertex searchorg, searchdest;
13007 enum locateresult intersect;
13008 int i;
13009 triangle ptr;
13010
13011 if (!(b->quiet || (b->noholes && b->convex))) {
13012 printf("Removing unwanted triangles.\n");
13013 if (b->verbose && (holes > 0)) {
13014 printf(" Marking holes for elimination.\n");
13015 }
13016 }
13017
13018 if (regions > 0) {
13019
13020 regiontris = (struct otri *) trimalloc(regions *
13021 (int) sizeof(struct otri));
13022 } else {
13023 regiontris = (struct otri *) NULL;
13024 }
13025
13026 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13027
13028
13029 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13030 }
13031
13032 if (!b->convex) {
13033
13034
13035 infecthull(m, b);
13036 }
13037
13038 if ((holes > 0) && !b->noholes) {
13039
13040 for (i = 0; i < 2 * holes; i += 2) {
13041
13042 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13043 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13044
13045 searchtri.tri = m->dummytri;
13046 searchtri.orient = 0;
13047 symself(searchtri);
13048
13049
13050
13051 org(searchtri, searchorg);
13052 dest(searchtri, searchdest);
13053 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13054 0.0) {
13055
13056 intersect = locate(m, b, &holelist[i], &searchtri);
13057 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13058
13059
13060 infect(searchtri);
13061 holetri = (triangle **) poolalloc(&m->viri);
13062 *holetri = searchtri.tri;
13063 }
13064 }
13065 }
13066 }
13067 }
13068
13069
13070
13071
13072
13073
13074
13075 if (regions > 0) {
13076
13077 for (i = 0; i < regions; i++) {
13078 regiontris[i].tri = m->dummytri;
13079
13080 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13081 (regionlist[4 * i + 1] >= m->ymin) &&
13082 (regionlist[4 * i + 1] <= m->ymax)) {
13083
13084 searchtri.tri = m->dummytri;
13085 searchtri.orient = 0;
13086 symself(searchtri);
13087
13088
13089
13090 org(searchtri, searchorg);
13091 dest(searchtri, searchdest);
13092 if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) >
13093 0.0) {
13094
13095 intersect = locate(m, b, ®ionlist[4 * i], &searchtri);
13096 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13097
13098
13099 otricopy(searchtri, regiontris[i]);
13100 }
13101 }
13102 }
13103 }
13104 }
13105
13106 if (m->viri.items > 0) {
13107
13108 plague(m, b);
13109 }
13110
13111
13112 if (regions > 0) {
13113 if (!b->quiet) {
13114 if (b->regionattrib) {
13115 if (b->vararea) {
13116 printf("Spreading regional attributes and area constraints.\n");
13117 } else {
13118 printf("Spreading regional attributes.\n");
13119 }
13120 } else {
13121 printf("Spreading regional area constraints.\n");
13122 }
13123 }
13124 if (b->regionattrib && !b->refine) {
13125
13126 traversalinit(&m->triangles);
13127 triangleloop.orient = 0;
13128 triangleloop.tri = triangletraverse(m);
13129 while (triangleloop.tri != (triangle *) NULL) {
13130 setelemattribute(triangleloop, m->eextras, 0.0);
13131 triangleloop.tri = triangletraverse(m);
13132 }
13133 }
13134 for (i = 0; i < regions; i++) {
13135 if (regiontris[i].tri != m->dummytri) {
13136
13137
13138 if (!deadtri(regiontris[i].tri)) {
13139
13140 infect(regiontris[i]);
13141 regiontri = (triangle **) poolalloc(&m->viri);
13142 *regiontri = regiontris[i].tri;
13143
13144 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13145
13146 }
13147 }
13148 }
13149 if (b->regionattrib && !b->refine) {
13150
13151 m->eextras++;
13152 }
13153 }
13154
13155
13156 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13157 pooldeinit(&m->viri);
13158 }
13159 if (regions > 0) {
13160 trifree((VOID *) regiontris);
13161 }
13162 }
13163
13166
13167
13168
13172
13173
13174
13175
13176
13177
13178
13179 #ifndef CDT_ONLY
13180
13181 #ifdef ANSI_DECLARATORS
13182 void tallyencs(struct mesh *m, struct behavior *b)
13183 #else
13184 void tallyencs(m, b)
13185 struct mesh *m;
13186 struct behavior *b;
13187 #endif
13188
13189 {
13190 struct osub subsegloop;
13191 int dummy;
13192
13193 traversalinit(&m->subsegs);
13194 subsegloop.ssorient = 0;
13195 subsegloop.ss = subsegtraverse(m);
13196 while (subsegloop.ss != (subseg *) NULL) {
13197
13198 dummy = checkseg4encroach(m, b, &subsegloop);
13199 subsegloop.ss = subsegtraverse(m);
13200 }
13201 }
13202
13203 #endif
13204
13205
13206
13207
13208
13209
13210
13211 #ifndef CDT_ONLY
13212
13213 void precisionerror()
13214 {
13215 printf("Try increasing the area criterion and/or reducing the minimum\n");
13216 printf(" allowable angle so that tiny triangles are not created.\n");
13217 #ifdef SINGLE
13218 printf("Alternatively, try recompiling me with double precision\n");
13219 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13220 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13221 #endif
13222 }
13223
13224 #endif
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240 #ifndef CDT_ONLY
13241
13242 #ifdef ANSI_DECLARATORS
13243 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13244 #else
13245 void splitencsegs(m, b, triflaws)
13246 struct mesh *m;
13247 struct behavior *b;
13248 int triflaws;
13249 #endif
13250
13251 {
13252 struct otri enctri;
13253 struct otri testtri;
13254 struct osub testsh;
13255 struct osub currentenc;
13256 struct badsubseg *encloop;
13257 vertex eorg, edest, eapex;
13258 vertex newvertex;
13259 enum insertvertexresult success;
13260 REAL segmentlength, nearestpoweroftwo;
13261 REAL split;
13262 REAL multiplier, divisor;
13263 int acuteorg, acuteorg2, acutedest, acutedest2;
13264 int dummy;
13265 int i;
13266 triangle ptr;
13267 subseg sptr;
13268
13269
13270
13271 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13272 traversalinit(&m->badsubsegs);
13273 encloop = badsubsegtraverse(m);
13274 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13275 sdecode(encloop->encsubseg, currentenc);
13276 sorg(currentenc, eorg);
13277 sdest(currentenc, edest);
13278
13279
13280
13281
13282 if (!deadsubseg(currentenc.ss) &&
13283 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297
13298
13299
13300 stpivot(currentenc, enctri);
13301 lnext(enctri, testtri);
13302 tspivot(testtri, testsh);
13303 acuteorg = testsh.ss != m->dummysub;
13304
13305 lnextself(testtri);
13306 tspivot(testtri, testsh);
13307 acutedest = testsh.ss != m->dummysub;
13308
13309
13310
13311
13312 if (!b->conformdel && !acuteorg && !acutedest) {
13313 apex(enctri, eapex);
13314 while ((vertextype(eapex) == FREEVERTEX) &&
13315 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13316 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13317 deletevertex(m, b, &testtri);
13318 stpivot(currentenc, enctri);
13319 apex(enctri, eapex);
13320 lprev(enctri, testtri);
13321 }
13322 }
13323
13324
13325
13326 sym(enctri, testtri);
13327 if (testtri.tri != m->dummytri) {
13328
13329 lnextself(testtri);
13330 tspivot(testtri, testsh);
13331 acutedest2 = testsh.ss != m->dummysub;
13332 acutedest = acutedest || acutedest2;
13333
13334 lnextself(testtri);
13335 tspivot(testtri, testsh);
13336 acuteorg2 = testsh.ss != m->dummysub;
13337 acuteorg = acuteorg || acuteorg2;
13338
13339
13340 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13341 org(testtri, eapex);
13342 while ((vertextype(eapex) == FREEVERTEX) &&
13343 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13344 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13345 deletevertex(m, b, &testtri);
13346 sym(enctri, testtri);
13347 apex(testtri, eapex);
13348 lprevself(testtri);
13349 }
13350 }
13351 }
13352
13353
13354
13355 if (acuteorg || acutedest) {
13356 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13357 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13358
13359
13360 nearestpoweroftwo = 1.0;
13361 while (segmentlength > 3.0 * nearestpoweroftwo) {
13362 nearestpoweroftwo *= 2.0;
13363 }
13364 while (segmentlength < 1.5 * nearestpoweroftwo) {
13365 nearestpoweroftwo *= 0.5;
13366 }
13367
13368 split = nearestpoweroftwo / segmentlength;
13369 if (acutedest) {
13370 split = 1.0 - split;
13371 }
13372 } else {
13373
13374
13375 split = 0.5;
13376 }
13377
13378
13379 newvertex = (vertex) poolalloc(&m->vertices);
13380
13381 for (i = 0; i < 2 + m->nextras; i++) {
13382 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13383 }
13384
13385 if (!b->noexact) {
13386
13387
13388
13389 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13390 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13391 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13392 if ((multiplier != 0.0) && (divisor != 0.0)) {
13393 multiplier = multiplier / divisor;
13394
13395 if (multiplier == multiplier) {
13396 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13397 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13398 }
13399 }
13400 }
13401
13402 setvertexmark(newvertex, mark(currentenc));
13403 setvertextype(newvertex, SEGMENTVERTEX);
13404 if (b->verbose > 1) {
13405 printf(
13406 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13407 eorg[0], eorg[1], edest[0], edest[1],
13408 newvertex[0], newvertex[1]);
13409 }
13410
13411 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13412 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13413 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13414 newvertex[0], newvertex[1]);
13415 printf("I attempted to split a segment to a smaller size than\n");
13416 printf(" can be accommodated by the finite precision of\n");
13417 printf(" floating point arithmetic.\n");
13418 precisionerror();
13419 triexit(1);
13420 }
13421
13422 success = insertvertex(m, b, newvertex, &enctri, ¤tenc,
13423 1, triflaws);
13424 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13425 printf("Internal error in splitencsegs():\n");
13426 printf(" Failure to split a segment.\n");
13427 internalerror();
13428 }
13429 if (m->steinerleft > 0) {
13430 m->steinerleft--;
13431 }
13432
13433 dummy = checkseg4encroach(m, b, ¤tenc);
13434 snextself(currentenc);
13435 dummy = checkseg4encroach(m, b, ¤tenc);
13436 }
13437
13438 badsubsegdealloc(m, encloop);
13439 encloop = badsubsegtraverse(m);
13440 }
13441 }
13442 }
13443
13444 #endif
13445
13446
13447
13448
13449
13450
13451
13452 #ifndef CDT_ONLY
13453
13454 #ifdef ANSI_DECLARATORS
13455 void tallyfaces(struct mesh *m, struct behavior *b)
13456 #else
13457 void tallyfaces(m, b)
13458 struct mesh *m;
13459 struct behavior *b;
13460 #endif
13461
13462 {
13463 struct otri triangleloop;
13464
13465 if (b->verbose) {
13466 printf(" Making a list of bad triangles.\n");
13467 }
13468 traversalinit(&m->triangles);
13469 triangleloop.orient = 0;
13470 triangleloop.tri = triangletraverse(m);
13471 while (triangleloop.tri != (triangle *) NULL) {
13472
13473 testtriangle(m, b, &triangleloop);
13474 triangleloop.tri = triangletraverse(m);
13475 }
13476 }
13477
13478 #endif
13479
13480
13481
13482
13483
13484
13485
13486
13487
13488 #ifndef CDT_ONLY
13489
13490 #ifdef ANSI_DECLARATORS
13491 void splittriangle(struct mesh *m, struct behavior *b,
13492 struct badtriang *badtri)
13493 #else
13494 void splittriangle(m, b, badtri)
13495 struct mesh *m;
13496 struct behavior *b;
13497 struct badtriang *badtri;
13498 #endif
13499
13500 {
13501 struct otri badotri;
13502 vertex borg, bdest, bapex;
13503 vertex newvertex;
13504 REAL xi, eta;
13505 enum insertvertexresult success;
13506 int errorflag;
13507 int i;
13508
13509 decode(badtri->poortri, badotri);
13510 org(badotri, borg);
13511 dest(badotri, bdest);
13512 apex(badotri, bapex);
13513
13514
13515
13516 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13517 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13518 if (b->verbose > 1) {
13519 printf(" Splitting this triangle at its circumcenter:\n");
13520 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13521 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13522 }
13523
13524 errorflag = 0;
13525
13526 newvertex = (vertex) poolalloc(&m->vertices);
13527 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13528
13529
13530 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13531 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13532 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13533 if (!b->quiet) {
13534 printf(
13535 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13536 newvertex[0], newvertex[1]);
13537 errorflag = 1;
13538 }
13539 vertexdealloc(m, newvertex);
13540 } else {
13541 for (i = 2; i < 2 + m->nextras; i++) {
13542
13543 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13544 + eta * (bapex[i] - borg[i]);
13545 }
13546
13547
13548 setvertexmark(newvertex, 0);
13549 setvertextype(newvertex, FREEVERTEX);
13550
13551
13552
13553
13554
13555
13556
13557
13558 if (eta < xi) {
13559 lprevself(badotri);
13560 }
13561
13562
13563
13564 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13565 1, 1);
13566 if (success == SUCCESSFULVERTEX) {
13567 if (m->steinerleft > 0) {
13568 m->steinerleft--;
13569 }
13570 } else if (success == ENCROACHINGVERTEX) {
13571
13572
13573 undovertex(m, b);
13574 if (b->verbose > 1) {
13575 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13576 }
13577 vertexdealloc(m, newvertex);
13578 } else if (success == VIOLATINGVERTEX) {
13579
13580
13581 vertexdealloc(m, newvertex);
13582 } else {
13583
13584 if (!b->quiet) {
13585 printf(
13586 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13587 newvertex[0], newvertex[1]);
13588 errorflag = 1;
13589 }
13590 vertexdealloc(m, newvertex);
13591 }
13592 }
13593 if (errorflag) {
13594 if (b->verbose) {
13595 printf(" The new vertex is at the circumcenter of triangle\n");
13596 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13597 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13598 }
13599 printf("This probably means that I am trying to refine triangles\n");
13600 printf(" to a smaller size than can be accommodated by the finite\n");
13601 printf(" precision of floating point arithmetic. (You can be\n");
13602 printf(" sure of this if I fail to terminate.)\n");
13603 precisionerror();
13604 }
13605 }
13606 }
13607
13608 #endif
13609
13610
13611
13612
13613
13614
13615
13616
13617 #ifndef CDT_ONLY
13618
13619 #ifdef ANSI_DECLARATORS
13620 void enforcequality(struct mesh *m, struct behavior *b)
13621 #else
13622 void enforcequality(m, b)
13623 struct mesh *m;
13624 struct behavior *b;
13625 #endif
13626
13627 {
13628 struct badtriang *badtri;
13629 int i;
13630
13631 if (!b->quiet) {
13632 printf("Adding Steiner points to enforce quality.\n");
13633 }
13634
13635 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13636 BADSUBSEGPERBLOCK, 0);
13637 if (b->verbose) {
13638 printf(" Looking for encroached subsegments.\n");
13639 }
13640
13641 tallyencs(m, b);
13642 if (b->verbose && (m->badsubsegs.items > 0)) {
13643 printf(" Splitting encroached subsegments.\n");
13644 }
13645
13646 splitencsegs(m, b, 0);
13647
13648
13649
13650
13651 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13652
13653 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13654 BADTRIPERBLOCK, 0);
13655
13656 for (i = 0; i < 4096; i++) {
13657 m->queuefront[i] = (struct badtriang *) NULL;
13658 }
13659 m->firstnonemptyq = -1;
13660
13661 tallyfaces(m, b);
13662
13663 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13664 FLIPSTACKERPERBLOCK, 0);
13665 m->checkquality = 1;
13666 if (b->verbose) {
13667 printf(" Splitting bad triangles.\n");
13668 }
13669 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13670
13671 badtri = dequeuebadtriang(m);
13672 splittriangle(m, b, badtri);
13673 if (m->badsubsegs.items > 0) {
13674
13675 enqueuebadtriang(m, b, badtri);
13676
13677
13678 splitencsegs(m, b, 1);
13679 } else {
13680
13681 pooldealloc(&m->badtriangles, (VOID *) badtri);
13682 }
13683 }
13684 }
13685
13686
13687
13688
13689
13690 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13691 (m->steinerleft == 0)) {
13692 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13693 if (m->badsubsegs.items == 1) {
13694 printf(" one encroached subsegment, and therefore might not be truly\n"
13695 );
13696 } else {
13697 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13698 , m->badsubsegs.items);
13699 }
13700 printf(" Delaunay. If the Delaunay property is important to you,\n");
13701 printf(" try increasing the number of Steiner points (controlled by\n");
13702 printf(" the -S switch) slightly and try again.\n\n");
13703 }
13704 }
13705
13706 #endif
13707
13710
13711
13712
13713
13714
13715
13716
13717
13718 #ifdef ANSI_DECLARATORS
13719 void highorder(struct mesh *m, struct behavior *b)
13720 #else
13721 void highorder(m, b)
13722 struct mesh *m;
13723 struct behavior *b;
13724 #endif
13725
13726 {
13727 struct otri triangleloop, trisym;
13728 struct osub checkmark;
13729 vertex newvertex;
13730 vertex torg, tdest;
13731 int i;
13732 triangle ptr;
13733 subseg sptr;
13734
13735 if (!b->quiet) {
13736 printf("Adding vertices for second-order triangles.\n");
13737 }
13738
13739
13740
13741
13742
13743 m->vertices.deaditemstack = (VOID *) NULL;
13744
13745 traversalinit(&m->triangles);
13746 triangleloop.tri = triangletraverse(m);
13747
13748
13749
13750
13751
13752
13753 while (triangleloop.tri != (triangle *) NULL) {
13754 for (triangleloop.orient = 0; triangleloop.orient < 3;
13755 triangleloop.orient++) {
13756 sym(triangleloop, trisym);
13757 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13758 org(triangleloop, torg);
13759 dest(triangleloop, tdest);
13760
13761
13762 newvertex = (vertex) poolalloc(&m->vertices);
13763 for (i = 0; i < 2 + m->nextras; i++) {
13764 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13765 }
13766
13767
13768 setvertexmark(newvertex, trisym.tri == m->dummytri);
13769 setvertextype(newvertex,
13770 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13771 if (b->usesegments) {
13772 tspivot(triangleloop, checkmark);
13773
13774 if (checkmark.ss != m->dummysub) {
13775 setvertexmark(newvertex, mark(checkmark));
13776 setvertextype(newvertex, SEGMENTVERTEX);
13777 }
13778 }
13779 if (b->verbose > 1) {
13780 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13781 }
13782
13783 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13784 (triangle) newvertex;
13785 if (trisym.tri != m->dummytri) {
13786 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13787 }
13788 }
13789 }
13790 triangleloop.tri = triangletraverse(m);
13791 }
13792 }
13793
13794
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807 #ifndef TRILIBRARY
13808
13809 #ifdef ANSI_DECLARATORS
13810 char *readline(char *string, FILE *infile, char *infilename)
13811 #else
13812 char *readline(string, infile, infilename)
13813 char *string;
13814 FILE *infile;
13815 char *infilename;
13816 #endif
13817
13818 {
13819 char *result;
13820
13821
13822 do {
13823 result = fgets(string, INPUTLINESIZE, infile);
13824 if (result == (char *) NULL) {
13825 printf(" Error: Unexpected end of file in %s.\n", infilename);
13826 triexit(1);
13827 }
13828
13829
13830 while ((*result != '\0') && (*result != '#')
13831 && (*result != '.') && (*result != '+') && (*result != '-')
13832 && ((*result < '0') || (*result > '9'))) {
13833 result++;
13834 }
13835
13836 } while ((*result == '#') || (*result == '\0'));
13837 return result;
13838 }
13839
13840 #endif
13841
13842
13843
13844
13845
13846
13847
13848
13849
13850
13851 #ifndef TRILIBRARY
13852
13853 #ifdef ANSI_DECLARATORS
13854 char *findfield(char *string)
13855 #else
13856 char *findfield(string)
13857 char *string;
13858 #endif
13859
13860 {
13861 char *result;
13862
13863 result = string;
13864
13865 while ((*result != '\0') && (*result != '#')
13866 && (*result != ' ') && (*result != '\t')) {
13867 result++;
13868 }
13869
13870
13871 while ((*result != '\0') && (*result != '#')
13872 && (*result != '.') && (*result != '+') && (*result != '-')
13873 && ((*result < '0') || (*result > '9'))) {
13874 result++;
13875 }
13876
13877 if (*result == '#') {
13878 *result = '\0';
13879 }
13880 return result;
13881 }
13882
13883 #endif
13884
13885
13886
13887
13888
13889
13890
13891
13892 #ifndef TRILIBRARY
13893
13894 #ifdef ANSI_DECLARATORS
13895 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13896 char *polyfilename, FILE **polyfile)
13897 #else
13898 void readnodes(m, b, nodefilename, polyfilename, polyfile)
13899 struct mesh *m;
13900 struct behavior *b;
13901 char *nodefilename;
13902 char *polyfilename;
13903 FILE **polyfile;
13904 #endif
13905
13906 {
13907 FILE *infile;
13908 vertex vertexloop;
13909 char inputline[INPUTLINESIZE];
13910 char *stringptr;
13911 char *infilename;
13912 REAL x, y;
13913 int firstnode;
13914 int nodemarkers;
13915 int currentmarker;
13916 int i, j;
13917
13918 if (b->poly) {
13919
13920 if (!b->quiet) {
13921 printf("Opening %s.\n", polyfilename);
13922 }
13923 *polyfile = fopen(polyfilename, "r");
13924 if (*polyfile == (FILE *) NULL) {
13925 printf(" Error: Cannot access file %s.\n", polyfilename);
13926 triexit(1);
13927 }
13928
13929
13930 stringptr = readline(inputline, *polyfile, polyfilename);
13931 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13932 stringptr = findfield(stringptr);
13933 if (*stringptr == '\0') {
13934 m->mesh_dim = 2;
13935 } else {
13936 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13937 }
13938 stringptr = findfield(stringptr);
13939 if (*stringptr == '\0') {
13940 m->nextras = 0;
13941 } else {
13942 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13943 }
13944 stringptr = findfield(stringptr);
13945 if (*stringptr == '\0') {
13946 nodemarkers = 0;
13947 } else {
13948 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13949 }
13950 if (m->invertices > 0) {
13951 infile = *polyfile;
13952 infilename = polyfilename;
13953 m->readnodefile = 0;
13954 } else {
13955
13956
13957 m->readnodefile = 1;
13958 infilename = nodefilename;
13959 }
13960 } else {
13961 m->readnodefile = 1;
13962 infilename = nodefilename;
13963 *polyfile = (FILE *) NULL;
13964 }
13965
13966 if (m->readnodefile) {
13967
13968 if (!b->quiet) {
13969 printf("Opening %s.\n", nodefilename);
13970 }
13971 infile = fopen(nodefilename, "r");
13972 if (infile == (FILE *) NULL) {
13973 printf(" Error: Cannot access file %s.\n", nodefilename);
13974 triexit(1);
13975 }
13976
13977
13978 stringptr = readline(inputline, infile, nodefilename);
13979 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13980 stringptr = findfield(stringptr);
13981 if (*stringptr == '\0') {
13982 m->mesh_dim = 2;
13983 } else {
13984 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13985 }
13986 stringptr = findfield(stringptr);
13987 if (*stringptr == '\0') {
13988 m->nextras = 0;
13989 } else {
13990 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13991 }
13992 stringptr = findfield(stringptr);
13993 if (*stringptr == '\0') {
13994 nodemarkers = 0;
13995 } else {
13996 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13997 }
13998 }
13999
14000 if (m->invertices < 3) {
14001 printf("Error: Input must have at least three input vertices.\n");
14002 triexit(1);
14003 }
14004 if (m->mesh_dim != 2) {
14005 printf("Error: Triangle only works with two-dimensional meshes.\n");
14006 triexit(1);
14007 }
14008 if (m->nextras == 0) {
14009 b->weighted = 0;
14010 }
14011
14012 initializevertexpool(m, b);
14013
14014
14015 for (i = 0; i < m->invertices; i++) {
14016 vertexloop = (vertex) poolalloc(&m->vertices);
14017 stringptr = readline(inputline, infile, infilename);
14018 if (i == 0) {
14019 firstnode = (int) strtol(stringptr, &stringptr, 0);
14020 if ((firstnode == 0) || (firstnode == 1)) {
14021 b->firstnumber = firstnode;
14022 }
14023 }
14024 stringptr = findfield(stringptr);
14025 if (*stringptr == '\0') {
14026 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14027 triexit(1);
14028 }
14029 x = (REAL) strtod(stringptr, &stringptr);
14030 stringptr = findfield(stringptr);
14031 if (*stringptr == '\0') {
14032 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14033 triexit(1);
14034 }
14035 y = (REAL) strtod(stringptr, &stringptr);
14036 vertexloop[0] = x;
14037 vertexloop[1] = y;
14038
14039 for (j = 2; j < 2 + m->nextras; j++) {
14040 stringptr = findfield(stringptr);
14041 if (*stringptr == '\0') {
14042 vertexloop[j] = 0.0;
14043 } else {
14044 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14045 }
14046 }
14047 if (nodemarkers) {
14048
14049 stringptr = findfield(stringptr);
14050 if (*stringptr == '\0') {
14051 setvertexmark(vertexloop, 0);
14052 } else {
14053 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14054 setvertexmark(vertexloop, currentmarker);
14055 }
14056 } else {
14057
14058 setvertexmark(vertexloop, 0);
14059 }
14060 setvertextype(vertexloop, INPUTVERTEX);
14061
14062 if (i == 0) {
14063 m->xmin = m->xmax = x;
14064 m->ymin = m->ymax = y;
14065 } else {
14066 m->xmin = (x < m->xmin) ? x : m->xmin;
14067 m->xmax = (x > m->xmax) ? x : m->xmax;
14068 m->ymin = (y < m->ymin) ? y : m->ymin;
14069 m->ymax = (y > m->ymax) ? y : m->ymax;
14070 }
14071 }
14072 if (m->readnodefile) {
14073 fclose(infile);
14074 }
14075
14076
14077
14078 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14079 }
14080
14081 #endif
14082
14083
14084
14085
14086
14087
14088
14089 #ifdef TRILIBRARY
14090
14091 #ifdef ANSI_DECLARATORS
14092 void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14093 REAL *pointattriblist, int *pointmarkerlist,
14094 int numberofpoints, int numberofpointattribs)
14095 #else
14096 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14097 numberofpoints, numberofpointattribs)
14098 struct mesh *m;
14099 struct behavior *b;
14100 REAL *pointlist;
14101 REAL *pointattriblist;
14102 int *pointmarkerlist;
14103 int numberofpoints;
14104 int numberofpointattribs;
14105 #endif
14106
14107 {
14108 vertex vertexloop;
14109 REAL x, y;
14110 int i, j;
14111 int coordindex;
14112 int attribindex;
14113
14114 m->invertices = numberofpoints;
14115 m->mesh_dim = 2;
14116 m->nextras = numberofpointattribs;
14117 m->readnodefile = 0;
14118 if (m->invertices < 3) {
14119 printf("Error: Input must have at least three input vertices.\n");
14120 triexit(1);
14121 }
14122 if (m->nextras == 0) {
14123 b->weighted = 0;
14124 }
14125
14126 initializevertexpool(m, b);
14127
14128
14129 coordindex = 0;
14130 attribindex = 0;
14131 for (i = 0; i < m->invertices; i++) {
14132 vertexloop = (vertex) poolalloc(&m->vertices);
14133
14134 x = vertexloop[0] = pointlist[coordindex++];
14135 y = vertexloop[1] = pointlist[coordindex++];
14136
14137 for (j = 0; j < numberofpointattribs; j++) {
14138 vertexloop[2 + j] = pointattriblist[attribindex++];
14139 }
14140 if (pointmarkerlist != (int *) NULL) {
14141
14142 setvertexmark(vertexloop, pointmarkerlist[i]);
14143 } else {
14144
14145 setvertexmark(vertexloop, 0);
14146 }
14147 setvertextype(vertexloop, INPUTVERTEX);
14148
14149 if (i == 0) {
14150 m->xmin = m->xmax = x;
14151 m->ymin = m->ymax = y;
14152 } else {
14153 m->xmin = (x < m->xmin) ? x : m->xmin;
14154 m->xmax = (x > m->xmax) ? x : m->xmax;
14155 m->ymin = (y < m->ymin) ? y : m->ymin;
14156 m->ymax = (y > m->ymax) ? y : m->ymax;
14157 }
14158 }
14159
14160
14161
14162 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14163 }
14164
14165 #endif
14166
14167
14168
14169
14170
14171
14172
14173
14174 #ifndef TRILIBRARY
14175
14176 #ifdef ANSI_DECLARATORS
14177 void readholes(struct mesh *m, struct behavior *b,
14178 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14179 REAL **rlist, int *regions)
14180 #else
14181 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14182 struct mesh *m;
14183 struct behavior *b;
14184 FILE *polyfile;
14185 char *polyfilename;
14186 REAL **hlist;
14187 int *holes;
14188 REAL **rlist;
14189 int *regions;
14190 #endif
14191
14192 {
14193 REAL *holelist;
14194 REAL *regionlist;
14195 char inputline[INPUTLINESIZE];
14196 char *stringptr;
14197 int index;
14198 int i;
14199
14200
14201 stringptr = readline(inputline, polyfile, polyfilename);
14202 *holes = (int) strtol(stringptr, &stringptr, 0);
14203 if (*holes > 0) {
14204 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14205 *hlist = holelist;
14206 for (i = 0; i < 2 * *holes; i += 2) {
14207 stringptr = readline(inputline, polyfile, polyfilename);
14208 stringptr = findfield(stringptr);
14209 if (*stringptr == '\0') {
14210 printf("Error: Hole %d has no x coordinate.\n",
14211 b->firstnumber + (i >> 1));
14212 triexit(1);
14213 } else {
14214 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14215 }
14216 stringptr = findfield(stringptr);
14217 if (*stringptr == '\0') {
14218 printf("Error: Hole %d has no y coordinate.\n",
14219 b->firstnumber + (i >> 1));
14220 triexit(1);
14221 } else {
14222 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14223 }
14224 }
14225 } else {
14226 *hlist = (REAL *) NULL;
14227 }
14228
14229 #ifndef CDT_ONLY
14230 if ((b->regionattrib || b->vararea) && !b->refine) {
14231
14232 stringptr = readline(inputline, polyfile, polyfilename);
14233 *regions = (int) strtol(stringptr, &stringptr, 0);
14234 if (*regions > 0) {
14235 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14236 *rlist = regionlist;
14237 index = 0;
14238 for (i = 0; i < *regions; i++) {
14239 stringptr = readline(inputline, polyfile, polyfilename);
14240 stringptr = findfield(stringptr);
14241 if (*stringptr == '\0') {
14242 printf("Error: Region %d has no x coordinate.\n",
14243 b->firstnumber + i);
14244 triexit(1);
14245 } else {
14246 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14247 }
14248 stringptr = findfield(stringptr);
14249 if (*stringptr == '\0') {
14250 printf("Error: Region %d has no y coordinate.\n",
14251 b->firstnumber + i);
14252 triexit(1);
14253 } else {
14254 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14255 }
14256 stringptr = findfield(stringptr);
14257 if (*stringptr == '\0') {
14258 printf(
14259 "Error: Region %d has no region attribute or area constraint.\n",
14260 b->firstnumber + i);
14261 triexit(1);
14262 } else {
14263 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14264 }
14265 stringptr = findfield(stringptr);
14266 if (*stringptr == '\0') {
14267 regionlist[index] = regionlist[index - 1];
14268 } else {
14269 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14270 }
14271 index++;
14272 }
14273 }
14274 } else {
14275
14276 *regions = 0;
14277 *rlist = (REAL *) NULL;
14278 }
14279 #endif
14280
14281 fclose(polyfile);
14282 }
14283
14284 #endif
14285
14286
14287
14288
14289
14290
14291
14292
14293 #ifndef TRILIBRARY
14294
14295 #ifdef ANSI_DECLARATORS
14296 void finishfile(FILE *outfile, int argc, char **argv)
14297 #else
14298 void finishfile(outfile, argc, argv)
14299 FILE *outfile;
14300 int argc;
14301 char **argv;
14302 #endif
14303
14304 {
14305 int i;
14306
14307 fprintf(outfile, "# Generated by");
14308 for (i = 0; i < argc; i++) {
14309 fprintf(outfile, " ");
14310 fputs(argv[i], outfile);
14311 }
14312 fprintf(outfile, "\n");
14313 fclose(outfile);
14314 }
14315
14316 #endif
14317
14318
14319
14320
14321
14322
14323
14324
14325
14326
14327 #ifdef TRILIBRARY
14328
14329 #ifdef ANSI_DECLARATORS
14330 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14331 REAL **pointattriblist, int **pointmarkerlist)
14332 #else
14333 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14334 struct mesh *m;
14335 struct behavior *b;
14336 REAL **pointlist;
14337 REAL **pointattriblist;
14338 int **pointmarkerlist;
14339 #endif
14340
14341 #else
14342
14343 #ifdef ANSI_DECLARATORS
14344 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14345 int argc, char **argv)
14346 #else
14347 void writenodes(m, b, nodefilename, argc, argv)
14348 struct mesh *m;
14349 struct behavior *b;
14350 char *nodefilename;
14351 int argc;
14352 char **argv;
14353 #endif
14354
14355 #endif
14356
14357 {
14358 #ifdef TRILIBRARY
14359 REAL *plist;
14360 REAL *palist;
14361 int *pmlist;
14362 int coordindex;
14363 int attribindex;
14364 #else
14365 FILE *outfile;
14366 #endif
14367 vertex vertexloop;
14368 long outvertices;
14369 int vertexnumber;
14370 int i;
14371
14372 if (b->jettison) {
14373 outvertices = m->vertices.items - m->undeads;
14374 } else {
14375 outvertices = m->vertices.items;
14376 }
14377
14378 #ifdef TRILIBRARY
14379 if (!b->quiet) {
14380 printf("Writing vertices.\n");
14381 }
14382
14383 if (*pointlist == (REAL *) NULL) {
14384 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14385 }
14386
14387 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14388 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14389 sizeof(REAL)));
14390 }
14391
14392 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14393 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14394 }
14395 plist = *pointlist;
14396 palist = *pointattriblist;
14397 pmlist = *pointmarkerlist;
14398 coordindex = 0;
14399 attribindex = 0;
14400 #else
14401 if (!b->quiet) {
14402 printf("Writing %s.\n", nodefilename);
14403 }
14404 outfile = fopen(nodefilename, "w");
14405 if (outfile == (FILE *) NULL) {
14406 printf(" Error: Cannot create file %s.\n", nodefilename);
14407 triexit(1);
14408 }
14409
14410
14411 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14412 m->nextras, 1 - b->nobound);
14413 #endif
14414
14415 traversalinit(&m->vertices);
14416 vertexnumber = b->firstnumber;
14417 vertexloop = vertextraverse(m);
14418 while (vertexloop != (vertex) NULL) {
14419 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14420 #ifdef TRILIBRARY
14421
14422 plist[coordindex++] = vertexloop[0];
14423 plist[coordindex++] = vertexloop[1];
14424
14425 for (i = 0; i < m->nextras; i++) {
14426 palist[attribindex++] = vertexloop[2 + i];
14427 }
14428 if (!b->nobound) {
14429
14430 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14431 }
14432 #else
14433
14434 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14435 vertexloop[1]);
14436 for (i = 0; i < m->nextras; i++) {
14437
14438 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14439 }
14440 if (b->nobound) {
14441 fprintf(outfile, "\n");
14442 } else {
14443
14444 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14445 }
14446 #endif
14447
14448 setvertexmark(vertexloop, vertexnumber);
14449 vertexnumber++;
14450 }
14451 vertexloop = vertextraverse(m);
14452 }
14453
14454 #ifndef TRILIBRARY
14455 finishfile(outfile, argc, argv);
14456 #endif
14457 }
14458
14459
14460
14461
14462
14463
14464
14465
14466
14467
14468
14469 #ifdef ANSI_DECLARATORS
14470 void numbernodes(struct mesh *m, struct behavior *b)
14471 #else
14472 void numbernodes(m, b)
14473 struct mesh *m;
14474 struct behavior *b;
14475 #endif
14476
14477 {
14478 vertex vertexloop;
14479 int vertexnumber;
14480
14481 traversalinit(&m->vertices);
14482 vertexnumber = b->firstnumber;
14483 vertexloop = vertextraverse(m);
14484 while (vertexloop != (vertex) NULL) {
14485 setvertexmark(vertexloop, vertexnumber);
14486 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14487 vertexnumber++;
14488 }
14489 vertexloop = vertextraverse(m);
14490 }
14491 }
14492
14493
14494
14495
14496
14497
14498
14499 #ifdef TRILIBRARY
14500
14501 #ifdef ANSI_DECLARATORS
14502 void writeelements(struct mesh *m, struct behavior *b,
14503 int **trianglelist, REAL **triangleattriblist)
14504 #else
14505 void writeelements(m, b, trianglelist, triangleattriblist)
14506 struct mesh *m;
14507 struct behavior *b;
14508 int **trianglelist;
14509 REAL **triangleattriblist;
14510 #endif
14511
14512 #else
14513
14514 #ifdef ANSI_DECLARATORS
14515 void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14516 int argc, char **argv)
14517 #else
14518 void writeelements(m, b, elefilename, argc, argv)
14519 struct mesh *m;
14520 struct behavior *b;
14521 char *elefilename;
14522 int argc;
14523 char **argv;
14524 #endif
14525
14526 #endif
14527
14528 {
14529 #ifdef TRILIBRARY
14530 int *tlist;
14531 REAL *talist;
14532 int vertexindex;
14533 int attribindex;
14534 #else
14535 FILE *outfile;
14536 #endif
14537 struct otri triangleloop;
14538 vertex p1, p2, p3;
14539 vertex mid1, mid2, mid3;
14540 long elementnumber;
14541 int i;
14542
14543 #ifdef TRILIBRARY
14544 if (!b->quiet) {
14545 printf("Writing triangles.\n");
14546 }
14547
14548 if (*trianglelist == (int *) NULL) {
14549 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14550 ((b->order + 1) * (b->order + 2) /
14551 2) * sizeof(int)));
14552 }
14553
14554 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14555 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14556 m->eextras *
14557 sizeof(REAL)));
14558 }
14559 tlist = *trianglelist;
14560 talist = *triangleattriblist;
14561 vertexindex = 0;
14562 attribindex = 0;
14563 #else
14564 if (!b->quiet) {
14565 printf("Writing %s.\n", elefilename);
14566 }
14567 outfile = fopen(elefilename, "w");
14568 if (outfile == (FILE *) NULL) {
14569 printf(" Error: Cannot create file %s.\n", elefilename);
14570 triexit(1);
14571 }
14572
14573 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14574 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14575 #endif
14576
14577 traversalinit(&m->triangles);
14578 triangleloop.tri = triangletraverse(m);
14579 triangleloop.orient = 0;
14580 elementnumber = b->firstnumber;
14581 while (triangleloop.tri != (triangle *) NULL) {
14582 org(triangleloop, p1);
14583 dest(triangleloop, p2);
14584 apex(triangleloop, p3);
14585 if (b->order == 1) {
14586 #ifdef TRILIBRARY
14587 tlist[vertexindex++] = vertexmark(p1);
14588 tlist[vertexindex++] = vertexmark(p2);
14589 tlist[vertexindex++] = vertexmark(p3);
14590 #else
14591
14592 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14593 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14594 #endif
14595 } else {
14596 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14597 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14598 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14599 #ifdef TRILIBRARY
14600 tlist[vertexindex++] = vertexmark(p1);
14601 tlist[vertexindex++] = vertexmark(p2);
14602 tlist[vertexindex++] = vertexmark(p3);
14603 tlist[vertexindex++] = vertexmark(mid1);
14604 tlist[vertexindex++] = vertexmark(mid2);
14605 tlist[vertexindex++] = vertexmark(mid3);
14606 #else
14607
14608 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14609 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14610 vertexmark(mid2), vertexmark(mid3));
14611 #endif
14612 }
14613
14614 #ifdef TRILIBRARY
14615 for (i = 0; i < m->eextras; i++) {
14616 talist[attribindex++] = elemattribute(triangleloop, i);
14617 }
14618 #else
14619 for (i = 0; i < m->eextras; i++) {
14620 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14621 }
14622 fprintf(outfile, "\n");
14623 #endif
14624
14625 triangleloop.tri = triangletraverse(m);
14626 elementnumber++;
14627 }
14628
14629 #ifndef TRILIBRARY
14630 finishfile(outfile, argc, argv);
14631 #endif
14632 }
14633
14634
14635
14636
14637
14638
14639
14640 #ifdef TRILIBRARY
14641
14642 #ifdef ANSI_DECLARATORS
14643 void writepoly(struct mesh *m, struct behavior *b,
14644 int **segmentlist, int **segmentmarkerlist)
14645 #else
14646 void writepoly(m, b, segmentlist, segmentmarkerlist)
14647 struct mesh *m;
14648 struct behavior *b;
14649 int **segmentlist;
14650 int **segmentmarkerlist;
14651 #endif
14652
14653 #else
14654
14655 #ifdef ANSI_DECLARATORS
14656 void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14657 REAL *holelist, int holes, REAL *regionlist, int regions,
14658 int argc, char **argv)
14659 #else
14660 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14661 argc, argv)
14662 struct mesh *m;
14663 struct behavior *b;
14664 char *polyfilename;
14665 REAL *holelist;
14666 int holes;
14667 REAL *regionlist;
14668 int regions;
14669 int argc;
14670 char **argv;
14671 #endif
14672
14673 #endif
14674
14675 {
14676 #ifdef TRILIBRARY
14677 int *slist;
14678 int *smlist;
14679 int index;
14680 #else
14681 FILE *outfile;
14682 long holenumber, regionnumber;
14683 #endif
14684 struct osub subsegloop;
14685 vertex endpoint1, endpoint2;
14686 long subsegnumber;
14687
14688 #ifdef TRILIBRARY
14689 if (!b->quiet) {
14690 printf("Writing segments.\n");
14691 }
14692
14693 if (*segmentlist == (int *) NULL) {
14694 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14695 sizeof(int)));
14696 }
14697
14698 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14699 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14700 sizeof(int)));
14701 }
14702 slist = *segmentlist;
14703 smlist = *segmentmarkerlist;
14704 index = 0;
14705 #else
14706 if (!b->quiet) {
14707 printf("Writing %s.\n", polyfilename);
14708 }
14709 outfile = fopen(polyfilename, "w");
14710 if (outfile == (FILE *) NULL) {
14711 printf(" Error: Cannot create file %s.\n", polyfilename);
14712 triexit(1);
14713 }
14714
14715
14716
14717 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14718 1 - b->nobound);
14719
14720 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14721 #endif
14722
14723 traversalinit(&m->subsegs);
14724 subsegloop.ss = subsegtraverse(m);
14725 subsegloop.ssorient = 0;
14726 subsegnumber = b->firstnumber;
14727 while (subsegloop.ss != (subseg *) NULL) {
14728 sorg(subsegloop, endpoint1);
14729 sdest(subsegloop, endpoint2);
14730 #ifdef TRILIBRARY
14731
14732 slist[index++] = vertexmark(endpoint1);
14733 slist[index++] = vertexmark(endpoint2);
14734 if (!b->nobound) {
14735
14736 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14737 }
14738 #else
14739
14740 if (b->nobound) {
14741 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14742 vertexmark(endpoint1), vertexmark(endpoint2));
14743 } else {
14744 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14745 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14746 }
14747 #endif
14748
14749 subsegloop.ss = subsegtraverse(m);
14750 subsegnumber++;
14751 }
14752
14753 #ifndef TRILIBRARY
14754 #ifndef CDT_ONLY
14755 fprintf(outfile, "%d\n", holes);
14756 if (holes > 0) {
14757 for (holenumber = 0; holenumber < holes; holenumber++) {
14758
14759 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14760 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14761 }
14762 }
14763 if (regions > 0) {
14764 fprintf(outfile, "%d\n", regions);
14765 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14766
14767 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14768 b->firstnumber + regionnumber,
14769 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14770 regionlist[4 * regionnumber + 2],
14771 regionlist[4 * regionnumber + 3]);
14772 }
14773 }
14774 #endif
14775
14776 finishfile(outfile, argc, argv);
14777 #endif
14778 }
14779
14780
14781
14782
14783
14784
14785
14786 #ifdef TRILIBRARY
14787
14788 #ifdef ANSI_DECLARATORS
14789 void writeedges(struct mesh *m, struct behavior *b,
14790 int **edgelist, int **edgemarkerlist)
14791 #else
14792 void writeedges(m, b, edgelist, edgemarkerlist)
14793 struct mesh *m;
14794 struct behavior *b;
14795 int **edgelist;
14796 int **edgemarkerlist;
14797 #endif
14798
14799 #else
14800
14801 #ifdef ANSI_DECLARATORS
14802 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14803 int argc, char **argv)
14804 #else
14805 void writeedges(m, b, edgefilename, argc, argv)
14806 struct mesh *m;
14807 struct behavior *b;
14808 char *edgefilename;
14809 int argc;
14810 char **argv;
14811 #endif
14812
14813 #endif
14814
14815 {
14816 #ifdef TRILIBRARY
14817 int *elist;
14818 int *emlist;
14819 int index;
14820 #else
14821 FILE *outfile;
14822 #endif
14823 struct otri triangleloop, trisym;
14824 struct osub checkmark;
14825 vertex p1, p2;
14826 long edgenumber;
14827 triangle ptr;
14828 subseg sptr;
14829
14830 #ifdef TRILIBRARY
14831 if (!b->quiet) {
14832 printf("Writing edges.\n");
14833 }
14834
14835 if (*edgelist == (int *) NULL) {
14836 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14837 }
14838
14839 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14840 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14841 }
14842 elist = *edgelist;
14843 emlist = *edgemarkerlist;
14844 index = 0;
14845 #else
14846 if (!b->quiet) {
14847 printf("Writing %s.\n", edgefilename);
14848 }
14849 outfile = fopen(edgefilename, "w");
14850 if (outfile == (FILE *) NULL) {
14851 printf(" Error: Cannot create file %s.\n", edgefilename);
14852 triexit(1);
14853 }
14854
14855 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14856 #endif
14857
14858 traversalinit(&m->triangles);
14859 triangleloop.tri = triangletraverse(m);
14860 edgenumber = b->firstnumber;
14861
14862
14863
14864
14865
14866
14867 while (triangleloop.tri != (triangle *) NULL) {
14868 for (triangleloop.orient = 0; triangleloop.orient < 3;
14869 triangleloop.orient++) {
14870 sym(triangleloop, trisym);
14871 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14872 org(triangleloop, p1);
14873 dest(triangleloop, p2);
14874 #ifdef TRILIBRARY
14875 elist[index++] = vertexmark(p1);
14876 elist[index++] = vertexmark(p2);
14877 #endif
14878 if (b->nobound) {
14879 #ifndef TRILIBRARY
14880
14881 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14882 vertexmark(p1), vertexmark(p2));
14883 #endif
14884 } else {
14885
14886
14887 if (b->usesegments) {
14888 tspivot(triangleloop, checkmark);
14889 if (checkmark.ss == m->dummysub) {
14890 #ifdef TRILIBRARY
14891 emlist[edgenumber - b->firstnumber] = 0;
14892 #else
14893 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14894 vertexmark(p1), vertexmark(p2), 0);
14895 #endif
14896 } else {
14897 #ifdef TRILIBRARY
14898 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14899 #else
14900 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14901 vertexmark(p1), vertexmark(p2), mark(checkmark));
14902 #endif
14903 }
14904 } else {
14905 #ifdef TRILIBRARY
14906 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14907 #else
14908 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14909 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14910 #endif
14911 }
14912 }
14913 edgenumber++;
14914 }
14915 }
14916 triangleloop.tri = triangletraverse(m);
14917 }
14918
14919 #ifndef TRILIBRARY
14920 finishfile(outfile, argc, argv);
14921 #endif
14922 }
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936
14937
14938
14939
14940 #ifdef TRILIBRARY
14941
14942 #ifdef ANSI_DECLARATORS
14943 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14944 REAL **vpointattriblist, int **vpointmarkerlist,
14945 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14946 #else
14947 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14948 vedgelist, vedgemarkerlist, vnormlist)
14949 struct mesh *m;
14950 struct behavior *b;
14951 REAL **vpointlist;
14952 REAL **vpointattriblist;
14953 int **vpointmarkerlist;
14954 int **vedgelist;
14955 int **vedgemarkerlist;
14956 REAL **vnormlist;
14957 #endif
14958
14959 #else
14960
14961 #ifdef ANSI_DECLARATORS
14962 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14963 char *vedgefilename, int argc, char **argv)
14964 #else
14965 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14966 struct mesh *m;
14967 struct behavior *b;
14968 char *vnodefilename;
14969 char *vedgefilename;
14970 int argc;
14971 char **argv;
14972 #endif
14973
14974 #endif
14975
14976 {
14977 #ifdef TRILIBRARY
14978 REAL *plist;
14979 REAL *palist;
14980 int *elist;
14981 REAL *normlist;
14982 int coordindex;
14983 int attribindex;
14984 #else
14985 FILE *outfile;
14986 #endif
14987 struct otri triangleloop, trisym;
14988 vertex torg, tdest, tapex;
14989 REAL circumcenter[2];
14990 REAL xi, eta;
14991 long vnodenumber, vedgenumber;
14992 int p1, p2;
14993 int i;
14994 triangle ptr;
14995
14996 #ifdef TRILIBRARY
14997 if (!b->quiet) {
14998 printf("Writing Voronoi vertices.\n");
14999 }
15000
15001 if (*vpointlist == (REAL *) NULL) {
15002 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
15003 sizeof(REAL)));
15004 }
15005
15006 if (*vpointattriblist == (REAL *) NULL) {
15007 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15008 m->nextras * sizeof(REAL)));
15009 }
15010 *vpointmarkerlist = (int *) NULL;
15011 plist = *vpointlist;
15012 palist = *vpointattriblist;
15013 coordindex = 0;
15014 attribindex = 0;
15015 #else
15016 if (!b->quiet) {
15017 printf("Writing %s.\n", vnodefilename);
15018 }
15019 outfile = fopen(vnodefilename, "w");
15020 if (outfile == (FILE *) NULL) {
15021 printf(" Error: Cannot create file %s.\n", vnodefilename);
15022 triexit(1);
15023 }
15024
15025
15026 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15027 #endif
15028
15029 traversalinit(&m->triangles);
15030 triangleloop.tri = triangletraverse(m);
15031 triangleloop.orient = 0;
15032 vnodenumber = b->firstnumber;
15033 while (triangleloop.tri != (triangle *) NULL) {
15034 org(triangleloop, torg);
15035 dest(triangleloop, tdest);
15036 apex(triangleloop, tapex);
15037 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15038 #ifdef TRILIBRARY
15039
15040 plist[coordindex++] = circumcenter[0];
15041 plist[coordindex++] = circumcenter[1];
15042 for (i = 2; i < 2 + m->nextras; i++) {
15043
15044 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15045 + eta * (tapex[i] - torg[i]);
15046 }
15047 #else
15048
15049 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15050 circumcenter[1]);
15051 for (i = 2; i < 2 + m->nextras; i++) {
15052
15053 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15054 + eta * (tapex[i] - torg[i]));
15055 }
15056 fprintf(outfile, "\n");
15057 #endif
15058
15059 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15060 triangleloop.tri = triangletraverse(m);
15061 vnodenumber++;
15062 }
15063
15064 #ifndef TRILIBRARY
15065 finishfile(outfile, argc, argv);
15066 #endif
15067
15068 #ifdef TRILIBRARY
15069 if (!b->quiet) {
15070 printf("Writing Voronoi edges.\n");
15071 }
15072
15073 if (*vedgelist == (int *) NULL) {
15074 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15075 }
15076 *vedgemarkerlist = (int *) NULL;
15077
15078 if (*vnormlist == (REAL *) NULL) {
15079 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15080 }
15081 elist = *vedgelist;
15082 normlist = *vnormlist;
15083 coordindex = 0;
15084 #else
15085 if (!b->quiet) {
15086 printf("Writing %s.\n", vedgefilename);
15087 }
15088 outfile = fopen(vedgefilename, "w");
15089 if (outfile == (FILE *) NULL) {
15090 printf(" Error: Cannot create file %s.\n", vedgefilename);
15091 triexit(1);
15092 }
15093
15094 fprintf(outfile, "%ld %d\n", m->edges, 0);
15095 #endif
15096
15097 traversalinit(&m->triangles);
15098 triangleloop.tri = triangletraverse(m);
15099 vedgenumber = b->firstnumber;
15100
15101
15102
15103
15104
15105
15106 while (triangleloop.tri != (triangle *) NULL) {
15107 for (triangleloop.orient = 0; triangleloop.orient < 3;
15108 triangleloop.orient++) {
15109 sym(triangleloop, trisym);
15110 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15111
15112 p1 = * (int *) (triangleloop.tri + 6);
15113 if (trisym.tri == m->dummytri) {
15114 org(triangleloop, torg);
15115 dest(triangleloop, tdest);
15116 #ifdef TRILIBRARY
15117
15118 elist[coordindex] = p1;
15119 normlist[coordindex++] = tdest[1] - torg[1];
15120 elist[coordindex] = -1;
15121 normlist[coordindex++] = torg[0] - tdest[0];
15122 #else
15123
15124
15125
15126 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15127 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15128 #endif
15129 } else {
15130
15131 p2 = * (int *) (trisym.tri + 6);
15132
15133 #ifdef TRILIBRARY
15134 elist[coordindex] = p1;
15135 normlist[coordindex++] = 0.0;
15136 elist[coordindex] = p2;
15137 normlist[coordindex++] = 0.0;
15138 #else
15139 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15140 #endif
15141 }
15142 vedgenumber++;
15143 }
15144 }
15145 triangleloop.tri = triangletraverse(m);
15146 }
15147
15148 #ifndef TRILIBRARY
15149 finishfile(outfile, argc, argv);
15150 #endif
15151 }
15152
15153 #ifdef TRILIBRARY
15154
15155 #ifdef ANSI_DECLARATORS
15156 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15157 #else
15158 void writeneighbors(m, b, neighborlist)
15159 struct mesh *m;
15160 struct behavior *b;
15161 int **neighborlist;
15162 #endif
15163
15164 #else
15165
15166 #ifdef ANSI_DECLARATORS
15167 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15168 int argc, char **argv)
15169 #else
15170 void writeneighbors(m, b, neighborfilename, argc, argv)
15171 struct mesh *m;
15172 struct behavior *b;
15173 char *neighborfilename;
15174 int argc;
15175 char **argv;
15176 #endif
15177
15178 #endif
15179
15180 {
15181 #ifdef TRILIBRARY
15182 int *nlist;
15183 int index;
15184 #else
15185 FILE *outfile;
15186 #endif
15187 struct otri triangleloop, trisym;
15188 long elementnumber;
15189 int neighbor1, neighbor2, neighbor3;
15190 triangle ptr;
15191
15192 #ifdef TRILIBRARY
15193 if (!b->quiet) {
15194 printf("Writing neighbors.\n");
15195 }
15196
15197 if (*neighborlist == (int *) NULL) {
15198 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15199 sizeof(int)));
15200 }
15201 nlist = *neighborlist;
15202 index = 0;
15203 #else
15204 if (!b->quiet) {
15205 printf("Writing %s.\n", neighborfilename);
15206 }
15207 outfile = fopen(neighborfilename, "w");
15208 if (outfile == (FILE *) NULL) {
15209 printf(" Error: Cannot create file %s.\n", neighborfilename);
15210 triexit(1);
15211 }
15212
15213 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15214 #endif
15215
15216 traversalinit(&m->triangles);
15217 triangleloop.tri = triangletraverse(m);
15218 triangleloop.orient = 0;
15219 elementnumber = b->firstnumber;
15220 while (triangleloop.tri != (triangle *) NULL) {
15221 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15222 triangleloop.tri = triangletraverse(m);
15223 elementnumber++;
15224 }
15225 * (int *) (m->dummytri + 6) = -1;
15226
15227 traversalinit(&m->triangles);
15228 triangleloop.tri = triangletraverse(m);
15229 elementnumber = b->firstnumber;
15230 while (triangleloop.tri != (triangle *) NULL) {
15231 triangleloop.orient = 1;
15232 sym(triangleloop, trisym);
15233 neighbor1 = * (int *) (trisym.tri + 6);
15234 triangleloop.orient = 2;
15235 sym(triangleloop, trisym);
15236 neighbor2 = * (int *) (trisym.tri + 6);
15237 triangleloop.orient = 0;
15238 sym(triangleloop, trisym);
15239 neighbor3 = * (int *) (trisym.tri + 6);
15240 #ifdef TRILIBRARY
15241 nlist[index++] = neighbor1;
15242 nlist[index++] = neighbor2;
15243 nlist[index++] = neighbor3;
15244 #else
15245
15246 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15247 neighbor1, neighbor2, neighbor3);
15248 #endif
15249
15250 triangleloop.tri = triangletraverse(m);
15251 elementnumber++;
15252 }
15253
15254 #ifndef TRILIBRARY
15255 finishfile(outfile, argc, argv);
15256 #endif
15257 }
15258
15259
15260
15261
15262
15263
15264
15265
15266
15267
15268 #ifndef TRILIBRARY
15269
15270 #ifdef ANSI_DECLARATORS
15271 void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15272 int argc, char **argv)
15273 #else
15274 void writeoff(m, b, offfilename, argc, argv)
15275 struct mesh *m;
15276 struct behavior *b;
15277 char *offfilename;
15278 int argc;
15279 char **argv;
15280 #endif
15281
15282 {
15283 FILE *outfile;
15284 struct otri triangleloop;
15285 vertex vertexloop;
15286 vertex p1, p2, p3;
15287 long outvertices;
15288
15289 if (!b->quiet) {
15290 printf("Writing %s.\n", offfilename);
15291 }
15292
15293 if (b->jettison) {
15294 outvertices = m->vertices.items - m->undeads;
15295 } else {
15296 outvertices = m->vertices.items;
15297 }
15298
15299 outfile = fopen(offfilename, "w");
15300 if (outfile == (FILE *) NULL) {
15301 printf(" Error: Cannot create file %s.\n", offfilename);
15302 triexit(1);
15303 }
15304
15305 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15306 m->edges);
15307
15308
15309 traversalinit(&m->vertices);
15310 vertexloop = vertextraverse(m);
15311 while (vertexloop != (vertex) NULL) {
15312 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15313
15314 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15315 0.0);
15316 }
15317 vertexloop = vertextraverse(m);
15318 }
15319
15320
15321 traversalinit(&m->triangles);
15322 triangleloop.tri = triangletraverse(m);
15323 triangleloop.orient = 0;
15324 while (triangleloop.tri != (triangle *) NULL) {
15325 org(triangleloop, p1);
15326 dest(triangleloop, p2);
15327 apex(triangleloop, p3);
15328
15329 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15330 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15331 triangleloop.tri = triangletraverse(m);
15332 }
15333 finishfile(outfile, argc, argv);
15334 }
15335
15336 #endif
15337
15340
15341
15342
15343
15344
15345
15346
15347
15348 #ifdef ANSI_DECLARATORS
15349 void quality_statistics(struct mesh *m, struct behavior *b)
15350 #else
15351 void quality_statistics(m, b)
15352 struct mesh *m;
15353 struct behavior *b;
15354 #endif
15355
15356 {
15357 struct otri triangleloop;
15358 vertex p[3];
15359 REAL cossquaretable[8];
15360 REAL ratiotable[16];
15361 REAL dx[3], dy[3];
15362 REAL edgelength[3];
15363 REAL dotproduct;
15364 REAL cossquare;
15365 REAL triarea;
15366 REAL shortest, longest;
15367 REAL trilongest2;
15368 REAL smallestarea, biggestarea;
15369 REAL triminaltitude2;
15370 REAL minaltitude;
15371 REAL triaspect2;
15372 REAL worstaspect;
15373 REAL smallestangle, biggestangle;
15374 REAL radconst, degconst;
15375 int angletable[18];
15376 int aspecttable[16];
15377 int aspectindex;
15378 int tendegree;
15379 int acutebiggest;
15380 int i, ii, j, k;
15381
15382 printf("Mesh quality statistics:\n\n");
15383 radconst = PI / 18.0;
15384 degconst = 180.0 / PI;
15385 for (i = 0; i < 8; i++) {
15386 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15387 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15388 }
15389 for (i = 0; i < 18; i++) {
15390 angletable[i] = 0;
15391 }
15392
15393 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15394 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15395 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15396 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15397 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15398 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15399 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15400 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15401 for (i = 0; i < 16; i++) {
15402 aspecttable[i] = 0;
15403 }
15404
15405 worstaspect = 0.0;
15406 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15407 minaltitude = minaltitude * minaltitude;
15408 shortest = minaltitude;
15409 longest = 0.0;
15410 smallestarea = minaltitude;
15411 biggestarea = 0.0;
15412 worstaspect = 0.0;
15413 smallestangle = 0.0;
15414 biggestangle = 2.0;
15415 acutebiggest = 1;
15416
15417 traversalinit(&m->triangles);
15418 triangleloop.tri = triangletraverse(m);
15419 triangleloop.orient = 0;
15420 while (triangleloop.tri != (triangle *) NULL) {
15421 org(triangleloop, p[0]);
15422 dest(triangleloop, p[1]);
15423 apex(triangleloop, p[2]);
15424 trilongest2 = 0.0;
15425
15426 for (i = 0; i < 3; i++) {
15427 j = plus1mod3[i];
15428 k = minus1mod3[i];
15429 dx[i] = p[j][0] - p[k][0];
15430 dy[i] = p[j][1] - p[k][1];
15431 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15432 if (edgelength[i] > trilongest2) {
15433 trilongest2 = edgelength[i];
15434 }
15435 if (edgelength[i] > longest) {
15436 longest = edgelength[i];
15437 }
15438 if (edgelength[i] < shortest) {
15439 shortest = edgelength[i];
15440 }
15441 }
15442
15443 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15444 if (triarea < smallestarea) {
15445 smallestarea = triarea;
15446 }
15447 if (triarea > biggestarea) {
15448 biggestarea = triarea;
15449 }
15450 triminaltitude2 = triarea * triarea / trilongest2;
15451 if (triminaltitude2 < minaltitude) {
15452 minaltitude = triminaltitude2;
15453 }
15454 triaspect2 = trilongest2 / triminaltitude2;
15455 if (triaspect2 > worstaspect) {
15456 worstaspect = triaspect2;
15457 }
15458 aspectindex = 0;
15459 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15460 && (aspectindex < 15)) {
15461 aspectindex++;
15462 }
15463 aspecttable[aspectindex]++;
15464
15465 for (i = 0; i < 3; i++) {
15466 j = plus1mod3[i];
15467 k = minus1mod3[i];
15468 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15469 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15470 tendegree = 8;
15471 for (ii = 7; ii >= 0; ii--) {
15472 if (cossquare > cossquaretable[ii]) {
15473 tendegree = ii;
15474 }
15475 }
15476 if (dotproduct <= 0.0) {
15477 angletable[tendegree]++;
15478 if (cossquare > smallestangle) {
15479 smallestangle = cossquare;
15480 }
15481 if (acutebiggest && (cossquare < biggestangle)) {
15482 biggestangle = cossquare;
15483 }
15484 } else {
15485 angletable[17 - tendegree]++;
15486 if (acutebiggest || (cossquare > biggestangle)) {
15487 biggestangle = cossquare;
15488 acutebiggest = 0;
15489 }
15490 }
15491 }
15492 triangleloop.tri = triangletraverse(m);
15493 }
15494
15495 shortest = sqrt(shortest);
15496 longest = sqrt(longest);
15497 minaltitude = sqrt(minaltitude);
15498 worstaspect = sqrt(worstaspect);
15499 smallestarea *= 0.5;
15500 biggestarea *= 0.5;
15501 if (smallestangle >= 1.0) {
15502 smallestangle = 0.0;
15503 } else {
15504 smallestangle = degconst * acos(sqrt(smallestangle));
15505 }
15506 if (biggestangle >= 1.0) {
15507 biggestangle = 180.0;
15508 } else {
15509 if (acutebiggest) {
15510 biggestangle = degconst * acos(sqrt(biggestangle));
15511 } else {
15512 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15513 }
15514 }
15515
15516 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15517 smallestarea, biggestarea);
15518 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15519 shortest, longest);
15520 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15521 minaltitude, worstaspect);
15522
15523 printf(" Triangle aspect ratio histogram:\n");
15524 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15525 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15526 aspecttable[8]);
15527 for (i = 1; i < 7; i++) {
15528 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15529 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15530 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15531 }
15532 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15533 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15534 aspecttable[15]);
15535 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15536
15537 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15538 smallestangle, biggestangle);
15539
15540 printf(" Angle histogram:\n");
15541 for (i = 0; i < 9; i++) {
15542 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15543 i * 10, i * 10 + 10, angletable[i],
15544 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15545 }
15546 printf("\n");
15547 }
15548
15549
15550
15551
15552
15553
15554
15555 #ifdef ANSI_DECLARATORS
15556 void statistics(struct mesh *m, struct behavior *b)
15557 #else
15558 void statistics(m, b)
15559 struct mesh *m;
15560 struct behavior *b;
15561 #endif
15562
15563 {
15564 printf("\nStatistics:\n\n");
15565 printf(" Input vertices: %d\n", m->invertices);
15566 if (b->refine) {
15567 printf(" Input triangles: %d\n", m->inelements);
15568 }
15569 if (b->poly) {
15570 printf(" Input segments: %d\n", m->insegments);
15571 if (!b->refine) {
15572 printf(" Input holes: %d\n", m->holes);
15573 }
15574 }
15575
15576 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15577 printf(" Mesh triangles: %ld\n", m->triangles.items);
15578 printf(" Mesh edges: %ld\n", m->edges);
15579 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15580 if (b->poly || b->refine) {
15581 printf(" Mesh interior boundary edges: %ld\n",
15582 m->subsegs.items - m->hullsize);
15583 printf(" Mesh subsegments (constrained edges): %ld\n",
15584 m->subsegs.items);
15585 }
15586 printf("\n");
15587
15588 if (b->verbose) {
15589 quality_statistics(m, b);
15590 printf("Memory allocation statistics:\n\n");
15591 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15592 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15593 if (m->subsegs.maxitems > 0) {
15594 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15595 }
15596 if (m->viri.maxitems > 0) {
15597 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15598 }
15599 if (m->badsubsegs.maxitems > 0) {
15600 printf(" Maximum number of encroached subsegments: %ld\n",
15601 m->badsubsegs.maxitems);
15602 }
15603 if (m->badtriangles.maxitems > 0) {
15604 printf(" Maximum number of bad triangles: %ld\n",
15605 m->badtriangles.maxitems);
15606 }
15607 if (m->flipstackers.maxitems > 0) {
15608 printf(" Maximum number of stacked triangle flips: %ld\n",
15609 m->flipstackers.maxitems);
15610 }
15611 if (m->splaynodes.maxitems > 0) {
15612 printf(" Maximum number of splay tree nodes: %ld\n",
15613 m->splaynodes.maxitems);
15614 }
15615 printf(" Approximate heap memory use (bytes): %ld\n\n",
15616 m->vertices.maxitems * m->vertices.itembytes +
15617 m->triangles.maxitems * m->triangles.itembytes +
15618 m->subsegs.maxitems * m->subsegs.itembytes +
15619 m->viri.maxitems * m->viri.itembytes +
15620 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15621 m->badtriangles.maxitems * m->badtriangles.itembytes +
15622 m->flipstackers.maxitems * m->flipstackers.itembytes +
15623 m->splaynodes.maxitems * m->splaynodes.itembytes);
15624
15625 printf("Algorithmic statistics:\n\n");
15626 if (!b->weighted) {
15627 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15628 } else {
15629 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15630 }
15631 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15632 if (m->hyperbolacount > 0) {
15633 printf(" Number of right-of-hyperbola tests: %ld\n",
15634 m->hyperbolacount);
15635 }
15636 if (m->circletopcount > 0) {
15637 printf(" Number of circle top computations: %ld\n",
15638 m->circletopcount);
15639 }
15640 if (m->circumcentercount > 0) {
15641 printf(" Number of triangle circumcenter computations: %ld\n",
15642 m->circumcentercount);
15643 }
15644 printf("\n");
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
15671
15672
15673 #ifdef TRILIBRARY
15674
15675 #ifdef ANSI_DECLARATORS
15676 void triangulate(char *triswitches, struct triangulateio *in,
15677 struct triangulateio *out, struct triangulateio *vorout)
15678 #else
15679 void triangulate(triswitches, in, out, vorout)
15680 char *triswitches;
15681 struct triangulateio *in;
15682 struct triangulateio *out;
15683 struct triangulateio *vorout;
15684 #endif
15685
15686 #else
15687
15688 #ifdef ANSI_DECLARATORS
15689 int main(int argc, char **argv)
15690 #else
15691 int main(argc, argv)
15692 int argc;
15693 char **argv;
15694 #endif
15695
15696 #endif
15697
15698 {
15699 struct mesh m;
15700 struct behavior b;
15701 REAL *holearray;
15702 REAL *regionarray;
15703 #ifndef TRILIBRARY
15704 FILE *polyfile;
15705 #endif
15706 #ifndef NO_TIMER
15707
15708
15709 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15710 struct timezone tz;
15711 #endif
15712
15713 #ifndef NO_TIMER
15714 gettimeofday(&tv0, &tz);
15715 #endif
15716
15717 triangleinit(&m);
15718 #ifdef TRILIBRARY
15719 parsecommandline(1, &triswitches, &b);
15720 #else
15721 parsecommandline(argc, argv, &b);
15722 #endif
15723 m.steinerleft = b.steiner;
15724
15725 #ifdef TRILIBRARY
15726 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15727 in->pointmarkerlist, in->numberofpoints,
15728 in->numberofpointattributes);
15729 #else
15730 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15731 #endif
15732
15733 #ifndef NO_TIMER
15734 if (!b.quiet) {
15735 gettimeofday(&tv1, &tz);
15736 }
15737 #endif
15738
15739 #ifdef CDT_ONLY
15740 m.hullsize = delaunay(&m, &b);
15741 #else
15742 if (b.refine) {
15743
15744 #ifdef TRILIBRARY
15745 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15746 in->triangleattributelist, in->trianglearealist,
15747 in->numberoftriangles, in->numberofcorners,
15748 in->numberoftriangleattributes,
15749 in->segmentlist, in->segmentmarkerlist,
15750 in->numberofsegments);
15751 #else
15752 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15753 b.inpolyfilename, polyfile);
15754 #endif
15755 } else {
15756 m.hullsize = delaunay(&m, &b);
15757 }
15758 #endif
15759
15760 #ifndef NO_TIMER
15761 if (!b.quiet) {
15762 gettimeofday(&tv2, &tz);
15763 if (b.refine) {
15764 printf("Mesh reconstruction");
15765 } else {
15766 printf("Delaunay");
15767 }
15768 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15769 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15770 }
15771 #endif
15772
15773
15774
15775 m.infvertex1 = (vertex) NULL;
15776 m.infvertex2 = (vertex) NULL;
15777 m.infvertex3 = (vertex) NULL;
15778
15779 if (b.usesegments) {
15780 m.checksegments = 1;
15781 if (!b.refine) {
15782
15783 #ifdef TRILIBRARY
15784 formskeleton(&m, &b, in->segmentlist,
15785 in->segmentmarkerlist, in->numberofsegments);
15786 #else
15787 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15788 #endif
15789 }
15790 }
15791
15792 #ifndef NO_TIMER
15793 if (!b.quiet) {
15794 gettimeofday(&tv3, &tz);
15795 if (b.usesegments && !b.refine) {
15796 printf("Segment milliseconds: %ld\n",
15797 1000l * (tv3.tv_sec - tv2.tv_sec) +
15798 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15799 }
15800 }
15801 #endif
15802
15803 if (b.poly && (m.triangles.items > 0)) {
15804 #ifdef TRILIBRARY
15805 holearray = in->holelist;
15806 m.holes = in->numberofholes;
15807 regionarray = in->regionlist;
15808 m.regions = in->numberofregions;
15809 #else
15810 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15811 ®ionarray, &m.regions);
15812 #endif
15813 if (!b.refine) {
15814
15815 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15816 }
15817 } else {
15818
15819
15820
15821 m.holes = 0;
15822 m.regions = 0;
15823 }
15824
15825 #ifndef NO_TIMER
15826 if (!b.quiet) {
15827 gettimeofday(&tv4, &tz);
15828 if (b.poly && !b.refine) {
15829 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15830 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15831 }
15832 }
15833 #endif
15834
15835 #ifndef CDT_ONLY
15836 if (b.quality && (m.triangles.items > 0)) {
15837 enforcequality(&m, &b);
15838 }
15839 #endif
15840
15841 #ifndef NO_TIMER
15842 if (!b.quiet) {
15843 gettimeofday(&tv5, &tz);
15844 #ifndef CDT_ONLY
15845 if (b.quality) {
15846 printf("Quality milliseconds: %ld\n",
15847 1000l * (tv5.tv_sec - tv4.tv_sec) +
15848 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15849 }
15850 #endif
15851 }
15852 #endif
15853
15854
15855 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15856
15857 if (b.order > 1) {
15858 highorder(&m, &b);
15859 }
15860 if (!b.quiet) {
15861 printf("\n");
15862 }
15863
15864 #ifdef TRILIBRARY
15865 if (b.jettison) {
15866 out->numberofpoints = m.vertices.items - m.undeads;
15867 } else {
15868 out->numberofpoints = m.vertices.items;
15869 }
15870 out->numberofpointattributes = m.nextras;
15871 out->numberoftriangles = m.triangles.items;
15872 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15873 out->numberoftriangleattributes = m.eextras;
15874 out->numberofedges = m.edges;
15875 if (b.usesegments) {
15876 out->numberofsegments = m.subsegs.items;
15877 } else {
15878 out->numberofsegments = m.hullsize;
15879 }
15880 if (vorout != (struct triangulateio *) NULL) {
15881 vorout->numberofpoints = m.triangles.items;
15882 vorout->numberofpointattributes = m.nextras;
15883 vorout->numberofedges = m.edges;
15884 }
15885 #endif
15886
15887
15888 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15889 if (!b.quiet) {
15890 #ifdef TRILIBRARY
15891 printf("NOT writing vertices.\n");
15892 #else
15893 printf("NOT writing a .node file.\n");
15894 #endif
15895 }
15896 numbernodes(&m, &b);
15897 } else {
15898
15899 #ifdef TRILIBRARY
15900 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15901 &out->pointmarkerlist);
15902 #else
15903 writenodes(&m, &b, b.outnodefilename, argc, argv);
15904 #endif
15905 }
15906 if (b.noelewritten) {
15907 if (!b.quiet) {
15908 #ifdef TRILIBRARY
15909 printf("NOT writing triangles.\n");
15910 #else
15911 printf("NOT writing an .ele file.\n");
15912 #endif
15913 }
15914 } else {
15915 #ifdef TRILIBRARY
15916 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15917 #else
15918 writeelements(&m, &b, b.outelefilename, argc, argv);
15919 #endif
15920 }
15921
15922
15923 if (b.poly || b.convex) {
15924
15925 if (b.nopolywritten || b.noiterationnum) {
15926 if (!b.quiet) {
15927 #ifdef TRILIBRARY
15928 printf("NOT writing segments.\n");
15929 #else
15930 printf("NOT writing a .poly file.\n");
15931 #endif
15932 }
15933 } else {
15934 #ifdef TRILIBRARY
15935 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15936 out->numberofholes = m.holes;
15937 out->numberofregions = m.regions;
15938 if (b.poly) {
15939 out->holelist = in->holelist;
15940 out->regionlist = in->regionlist;
15941 } else {
15942 out->holelist = (REAL *) NULL;
15943 out->regionlist = (REAL *) NULL;
15944 }
15945 #else
15946 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15947 m.regions, argc, argv);
15948 #endif
15949 }
15950 }
15951 #ifndef TRILIBRARY
15952 #ifndef CDT_ONLY
15953 if (m.regions > 0) {
15954 trifree((VOID *) regionarray);
15955 }
15956 #endif
15957 if (m.holes > 0) {
15958 trifree((VOID *) holearray);
15959 }
15960 if (b.geomview) {
15961 writeoff(&m, &b, b.offfilename, argc, argv);
15962 }
15963 #endif
15964 if (b.edgesout) {
15965 #ifdef TRILIBRARY
15966 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15967 #else
15968 writeedges(&m, &b, b.edgefilename, argc, argv);
15969 #endif
15970 }
15971 if (b.voronoi) {
15972 #ifdef TRILIBRARY
15973 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15974 &vorout->pointmarkerlist, &vorout->edgelist,
15975 &vorout->edgemarkerlist, &vorout->normlist);
15976 #else
15977 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15978 #endif
15979 }
15980 if (b.neighbors) {
15981 #ifdef TRILIBRARY
15982 writeneighbors(&m, &b, &out->neighborlist);
15983 #else
15984 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15985 #endif
15986 }
15987
15988 if (!b.quiet) {
15989 #ifndef NO_TIMER
15990 gettimeofday(&tv6, &tz);
15991 printf("\nOutput milliseconds: %ld\n",
15992 1000l * (tv6.tv_sec - tv5.tv_sec) +
15993 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15994 printf("Total running milliseconds: %ld\n",
15995 1000l * (tv6.tv_sec - tv0.tv_sec) +
15996 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15997 #endif
15998
15999 statistics(&m, &b);
16000 }
16001
16002 #ifndef REDUCED
16003 if (b.docheck) {
16004 checkmesh(&m, &b);
16005 checkdelaunay(&m, &b);
16006 }
16007 #endif
16008
16009 triangledeinit(&m, &b);
16010 #ifndef TRILIBRARY
16011 return 0;
16012 #endif
16013 }