00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 #ifdef SINGLE
00214 #define REAL float
00215 #else
00216 #define REAL double
00217 #endif
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 #define INEXACT
00273
00274
00275
00276
00277 #define FILENAMESIZE 2048
00278
00279
00280
00281
00282 #define INPUTLINESIZE 1024
00283
00284
00285
00286
00287
00288 #define TRIPERBLOCK 4092
00289 #define SUBSEGPERBLOCK 508
00290 #define VERTEXPERBLOCK 4092
00291 #define VIRUSPERBLOCK 1020
00292
00293 #define BADSUBSEGPERBLOCK 252
00294
00295 #define BADTRIPERBLOCK 4092
00296
00297 #define FLIPSTACKERPERBLOCK 252
00298
00299 #define SPLAYNODEPERBLOCK 508
00300
00301
00302
00303
00304
00305 #define INPUTVERTEX 0
00306 #define SEGMENTVERTEX 1
00307 #define FREEVERTEX 2
00308 #define DEADVERTEX -32768
00309 #define UNDEADVERTEX -32767
00310
00311
00312
00313
00314
00315 #define VOID int
00316
00317
00318
00319
00320
00321
00322
00323 #define SAMPLEFACTOR 11
00324
00325
00326
00327
00328
00329 #define SAMPLERATE 10
00330
00331
00332
00333 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
00334
00335
00336
00337 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
00338
00339
00340
00341 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
00342
00343 #include <stdio.h>
00344 #include <stdlib.h>
00345 #include <string.h>
00346 #include <math.h>
00347 #ifndef NO_TIMER
00348 #include <sys/time.h>
00349 #endif
00350 #ifdef CPU86
00351 #include <float.h>
00352 #endif
00353 #ifdef LINUX
00354 #include <fpu_control.h>
00355 #endif
00356 #ifdef TRILIBRARY
00357 #include "triangle.h"
00358 #endif
00359
00360
00361
00362 #ifndef TRILIBRARY
00363 char *readline();
00364 char *findfield();
00365 #endif
00366
00367
00368
00369
00370
00371 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
00372
00373
00374
00375
00376
00377
00378
00379 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
00380 DUPLICATEVERTEX};
00381
00382
00383
00384
00385
00386
00387 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 typedef REAL **triangle;
00507
00508
00509
00510
00511
00512
00513 struct otri {
00514 triangle *tri;
00515 int orient;
00516 };
00517
00518
00519
00520
00521
00522
00523 typedef REAL **subseg;
00524
00525
00526
00527
00528
00529
00530 struct osub {
00531 subseg *ss;
00532 int ssorient;
00533 };
00534
00535
00536
00537
00538
00539
00540 typedef REAL *vertex;
00541
00542
00543
00544
00545 struct badsubseg {
00546 subseg encsubseg;
00547 vertex subsegorg, subsegdest;
00548 };
00549
00550
00551
00552
00553
00554 struct badtriang {
00555 triangle poortri;
00556 REAL key;
00557 vertex triangorg, triangdest, triangapex;
00558 struct badtriang *nexttriang;
00559 };
00560
00561
00562
00563
00564
00565 struct flipstacker {
00566 triangle flippedtri;
00567 struct flipstacker *prevflip;
00568 };
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 struct event {
00581 REAL xkey, ykey;
00582 VOID *eventptr;
00583 int heapposition;
00584 };
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 struct splaynode {
00598 struct otri keyedge;
00599 vertex keydest;
00600 struct splaynode *lchild, *rchild;
00601 };
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 struct memorypool {
00627 VOID **firstblock, **nowblock;
00628 VOID *nextitem;
00629 VOID *deaditemstack;
00630 VOID **pathblock;
00631 VOID *pathitem;
00632 int alignbytes;
00633 int itembytes;
00634 int itemsperblock;
00635 int itemsfirstblock;
00636 long items, maxitems;
00637 int unallocateditems;
00638 int pathitemsleft;
00639 };
00640
00641
00642
00643
00644 REAL splitter;
00645 REAL epsilon;
00646 REAL resulterrbound;
00647 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00648 REAL iccerrboundA, iccerrboundB, iccerrboundC;
00649 REAL o3derrboundA, o3derrboundB, o3derrboundC;
00650
00651
00652
00653 unsigned long randomseed;
00654
00655
00656
00657
00658
00659 struct mesh {
00660
00661
00662
00663
00664
00665 struct memorypool triangles;
00666 struct memorypool subsegs;
00667 struct memorypool vertices;
00668 struct memorypool viri;
00669 struct memorypool badsubsegs;
00670 struct memorypool badtriangles;
00671 struct memorypool flipstackers;
00672 struct memorypool splaynodes;
00673
00674
00675
00676
00677 struct badtriang *queuefront[4096];
00678 struct badtriang *queuetail[4096];
00679 int nextnonemptyq[4096];
00680 int firstnonemptyq;
00681
00682
00683
00684 struct flipstacker *lastflip;
00685
00686
00687
00688 REAL xmin, xmax, ymin, ymax;
00689 REAL xminextreme;
00690 int invertices;
00691 int inelements;
00692 int insegments;
00693 int holes;
00694 int regions;
00695 int undeads;
00696 long edges;
00697 int mesh_dim;
00698 int nextras;
00699 int eextras;
00700 long hullsize;
00701 int steinerleft;
00702 int vertexmarkindex;
00703 int vertex2triindex;
00704 int highorderindex;
00705 int elemattribindex;
00706 int areaboundindex;
00707 int checksegments;
00708 int checkquality;
00709 int readnodefile;
00710 long samples;
00711
00712 long incirclecount;
00713 long counterclockcount;
00714 long orient3dcount;
00715 long hyperbolacount;
00716 long circumcentercount;
00717 long circletopcount;
00718
00719
00720
00721 vertex infvertex1, infvertex2, infvertex3;
00722
00723
00724
00725 triangle *dummytri;
00726 triangle *dummytribase;
00727
00728
00729
00730
00731
00732 subseg *dummysub;
00733 subseg *dummysubbase;
00734
00735
00736
00737
00738 struct otri recenttri;
00739
00740 };
00741
00742
00743
00744
00745
00746 struct behavior {
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 int poly, refine, quality, vararea, fixedarea, usertest;
00782 int regionattrib, convex, weighted, jettison;
00783 int firstnumber;
00784 int edgesout, voronoi, neighbors, geomview;
00785 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
00786 int noholes, noexact, conformdel;
00787 int incremental, sweepline, dwyer;
00788 int splitseg;
00789 int docheck;
00790 int quiet, verbose;
00791 int usesegments;
00792 int order;
00793 int nobisect;
00794 int steiner;
00795 REAL minangle, goodangle, offconstant;
00796 REAL maxarea;
00797
00798
00799
00800 #ifndef TRILIBRARY
00801 char innodefilename[FILENAMESIZE];
00802 char inelefilename[FILENAMESIZE];
00803 char inpolyfilename[FILENAMESIZE];
00804 char areafilename[FILENAMESIZE];
00805 char outnodefilename[FILENAMESIZE];
00806 char outelefilename[FILENAMESIZE];
00807 char outpolyfilename[FILENAMESIZE];
00808 char edgefilename[FILENAMESIZE];
00809 char vnodefilename[FILENAMESIZE];
00810 char vedgefilename[FILENAMESIZE];
00811 char neighborfilename[FILENAMESIZE];
00812 char offfilename[FILENAMESIZE];
00813 #endif
00814
00815 };
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00928
00929
00930 int plus1mod3[3] = {1, 2, 0};
00931 int minus1mod3[3] = {2, 0, 1};
00932
00933
00934
00935
00936
00937
00938
00939
00940 #define decode(ptr, otri) \
00941 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
00942 (otri).tri = (triangle *) \
00943 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
00944
00945
00946
00947
00948
00949 #define encode(otri) \
00950 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960 #define sym(otri1, otri2) \
00961 ptr = (otri1).tri[(otri1).orient]; \
00962 decode(ptr, otri2);
00963
00964 #define symself(otri) \
00965 ptr = (otri).tri[(otri).orient]; \
00966 decode(ptr, otri);
00967
00968
00969
00970 #define lnext(otri1, otri2) \
00971 (otri2).tri = (otri1).tri; \
00972 (otri2).orient = plus1mod3[(otri1).orient]
00973
00974 #define lnextself(otri) \
00975 (otri).orient = plus1mod3[(otri).orient]
00976
00977
00978
00979 #define lprev(otri1, otri2) \
00980 (otri2).tri = (otri1).tri; \
00981 (otri2).orient = minus1mod3[(otri1).orient]
00982
00983 #define lprevself(otri) \
00984 (otri).orient = minus1mod3[(otri).orient]
00985
00986
00987
00988
00989
00990 #define onext(otri1, otri2) \
00991 lprev(otri1, otri2); \
00992 symself(otri2);
00993
00994 #define onextself(otri) \
00995 lprevself(otri); \
00996 symself(otri);
00997
00998
00999
01000
01001
01002 #define oprev(otri1, otri2) \
01003 sym(otri1, otri2); \
01004 lnextself(otri2);
01005
01006 #define oprevself(otri) \
01007 symself(otri); \
01008 lnextself(otri);
01009
01010
01011
01012
01013
01014 #define dnext(otri1, otri2) \
01015 sym(otri1, otri2); \
01016 lprevself(otri2);
01017
01018 #define dnextself(otri) \
01019 symself(otri); \
01020 lprevself(otri);
01021
01022
01023
01024
01025
01026 #define dprev(otri1, otri2) \
01027 lnext(otri1, otri2); \
01028 symself(otri2);
01029
01030 #define dprevself(otri) \
01031 lnextself(otri); \
01032 symself(otri);
01033
01034
01035
01036
01037
01038 #define rnext(otri1, otri2) \
01039 sym(otri1, otri2); \
01040 lnextself(otri2); \
01041 symself(otri2);
01042
01043 #define rnextself(otri) \
01044 symself(otri); \
01045 lnextself(otri); \
01046 symself(otri);
01047
01048
01049
01050
01051
01052 #define rprev(otri1, otri2) \
01053 sym(otri1, otri2); \
01054 lprevself(otri2); \
01055 symself(otri2);
01056
01057 #define rprevself(otri) \
01058 symself(otri); \
01059 lprevself(otri); \
01060 symself(otri);
01061
01062
01063
01064
01065 #define org(otri, vertexptr) \
01066 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
01067
01068 #define dest(otri, vertexptr) \
01069 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
01070
01071 #define apex(otri, vertexptr) \
01072 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
01073
01074 #define setorg(otri, vertexptr) \
01075 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01076
01077 #define setdest(otri, vertexptr) \
01078 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01079
01080 #define setapex(otri, vertexptr) \
01081 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
01082
01083
01084
01085 #define bond(otri1, otri2) \
01086 (otri1).tri[(otri1).orient] = encode(otri2); \
01087 (otri2).tri[(otri2).orient] = encode(otri1)
01088
01089
01090
01091
01092
01093
01094 #define dissolve(otri) \
01095 (otri).tri[(otri).orient] = (triangle) m->dummytri
01096
01097
01098
01099 #define otricopy(otri1, otri2) \
01100 (otri2).tri = (otri1).tri; \
01101 (otri2).orient = (otri1).orient
01102
01103
01104
01105 #define otriequal(otri1, otri2) \
01106 (((otri1).tri == (otri2).tri) && \
01107 ((otri1).orient == (otri2).orient))
01108
01109
01110
01111
01112 #define infect(otri) \
01113 (otri).tri[6] = (triangle) \
01114 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
01115
01116 #define uninfect(otri) \
01117 (otri).tri[6] = (triangle) \
01118 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
01119
01120
01121
01122 #define infected(otri) \
01123 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
01124
01125
01126
01127 #define elemattribute(otri, attnum) \
01128 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
01129
01130 #define setelemattribute(otri, attnum, value) \
01131 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
01132
01133
01134
01135 #define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
01136
01137 #define setareabound(otri, value) \
01138 ((REAL *) (otri).tri)[m->areaboundindex] = value
01139
01140
01141
01142
01143
01144
01145 #define deadtri(tria) ((tria)[1] == (triangle) NULL)
01146
01147 #define killtri(tria) \
01148 (tria)[1] = (triangle) NULL; \
01149 (tria)[3] = (triangle) NULL
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 #define sdecode(sptr, osub) \
01161 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
01162 (osub).ss = (subseg *) \
01163 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
01164
01165
01166
01167
01168
01169 #define sencode(osub) \
01170 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
01171
01172
01173
01174 #define ssym(osub1, osub2) \
01175 (osub2).ss = (osub1).ss; \
01176 (osub2).ssorient = 1 - (osub1).ssorient
01177
01178 #define ssymself(osub) \
01179 (osub).ssorient = 1 - (osub).ssorient
01180
01181
01182
01183
01184 #define spivot(osub1, osub2) \
01185 sptr = (osub1).ss[(osub1).ssorient]; \
01186 sdecode(sptr, osub2)
01187
01188 #define spivotself(osub) \
01189 sptr = (osub).ss[(osub).ssorient]; \
01190 sdecode(sptr, osub)
01191
01192
01193
01194
01195 #define snext(osub1, osub2) \
01196 sptr = (osub1).ss[1 - (osub1).ssorient]; \
01197 sdecode(sptr, osub2)
01198
01199 #define snextself(osub) \
01200 sptr = (osub).ss[1 - (osub).ssorient]; \
01201 sdecode(sptr, osub)
01202
01203
01204
01205
01206 #define sorg(osub, vertexptr) \
01207 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
01208
01209 #define sdest(osub, vertexptr) \
01210 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
01211
01212 #define setsorg(osub, vertexptr) \
01213 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
01214
01215 #define setsdest(osub, vertexptr) \
01216 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
01217
01218 #define segorg(osub, vertexptr) \
01219 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
01220
01221 #define segdest(osub, vertexptr) \
01222 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
01223
01224 #define setsegorg(osub, vertexptr) \
01225 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
01226
01227 #define setsegdest(osub, vertexptr) \
01228 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
01229
01230
01231
01232
01233
01234 #define mark(osub) (* (int *) ((osub).ss + 8))
01235
01236 #define setmark(osub, value) \
01237 * (int *) ((osub).ss + 8) = value
01238
01239
01240
01241 #define sbond(osub1, osub2) \
01242 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
01243 (osub2).ss[(osub2).ssorient] = sencode(osub1)
01244
01245
01246
01247
01248 #define sdissolve(osub) \
01249 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
01250
01251
01252
01253 #define subsegcopy(osub1, osub2) \
01254 (osub2).ss = (osub1).ss; \
01255 (osub2).ssorient = (osub1).ssorient
01256
01257
01258
01259 #define subsegequal(osub1, osub2) \
01260 (((osub1).ss == (osub2).ss) && \
01261 ((osub1).ssorient == (osub2).ssorient))
01262
01263
01264
01265
01266
01267
01268 #define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
01269
01270 #define killsubseg(sub) \
01271 (sub)[1] = (subseg) NULL; \
01272 (sub)[2] = (subseg) NULL
01273
01274
01275
01276
01277
01278
01279
01280 #define tspivot(otri, osub) \
01281 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
01282 sdecode(sptr, osub)
01283
01284
01285
01286
01287 #define stpivot(osub, otri) \
01288 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
01289 decode(ptr, otri)
01290
01291
01292
01293 #define tsbond(otri, osub) \
01294 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
01295 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
01296
01297
01298
01299 #define tsdissolve(otri) \
01300 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
01301
01302
01303
01304 #define stdissolve(osub) \
01305 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
01306
01307
01308
01309
01310
01311 #define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
01312
01313 #define setvertexmark(vx, value) \
01314 ((int *) (vx))[m->vertexmarkindex] = value
01315
01316 #define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
01317
01318 #define setvertextype(vx, value) \
01319 ((int *) (vx))[m->vertexmarkindex + 1] = value
01320
01321 #define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
01322
01323 #define setvertex2tri(vx, value) \
01324 ((triangle *) (vx))[m->vertex2triindex] = value
01325
01328
01329
01330
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357 #ifdef EXTERNAL_TEST
01358
01359 int triunsuitable();
01360
01361 #else
01362
01363 #ifdef ANSI_DECLARATORS
01364 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
01365 #else
01366 int triunsuitable(triorg, tridest, triapex, area)
01367 vertex triorg;
01368 vertex tridest;
01369 vertex triapex;
01370 REAL area;
01371 #endif
01372
01373 {
01374 REAL dxoa, dxda, dxod;
01375 REAL dyoa, dyda, dyod;
01376 REAL oalen, dalen, odlen;
01377 REAL maxlen;
01378
01379 dxoa = triorg[0] - triapex[0];
01380 dyoa = triorg[1] - triapex[1];
01381 dxda = tridest[0] - triapex[0];
01382 dyda = tridest[1] - triapex[1];
01383 dxod = triorg[0] - tridest[0];
01384 dyod = triorg[1] - tridest[1];
01385
01386 oalen = dxoa * dxoa + dyoa * dyoa;
01387 dalen = dxda * dxda + dyda * dyda;
01388 odlen = dxod * dxod + dyod * dyod;
01389
01390 maxlen = (dalen > oalen) ? dalen : oalen;
01391 maxlen = (odlen > maxlen) ? odlen : maxlen;
01392
01393 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
01394 return 1;
01395 } else {
01396 return 0;
01397 }
01398 }
01399
01400 #endif
01401
01404
01405
01406
01410 #ifdef ANSI_DECLARATORS
01411 void triexit(int status)
01412 #else
01413 void triexit(status)
01414 int status;
01415 #endif
01416
01417 {
01418 exit(status);
01419 }
01420
01421 #ifdef ANSI_DECLARATORS
01422 VOID *trimalloc(int size)
01423 #else
01424 VOID *trimalloc(size)
01425 int size;
01426 #endif
01427
01428 {
01429 VOID *memptr;
01430
01431 memptr = (VOID *) malloc((unsigned int) size);
01432 if (memptr == (VOID *) NULL) {
01433 printf("Error: Out of memory.\n");
01434 triexit(1);
01435 }
01436 return(memptr);
01437 }
01438
01439 #ifdef ANSI_DECLARATORS
01440 void trifree(VOID *memptr)
01441 #else
01442 void trifree(memptr)
01443 VOID *memptr;
01444 #endif
01445
01446 {
01447 free(memptr);
01448 }
01449
01452
01453
01454
01458
01459
01460
01461
01462
01463
01464 #ifndef TRILIBRARY
01465
01466 void syntax()
01467 {
01468 #ifdef CDT_ONLY
01469 #ifdef REDUCED
01470 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
01471 #else
01472 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
01473 #endif
01474 #else
01475 #ifdef REDUCED
01476 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
01477 #else
01478 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
01479 #endif
01480 #endif
01481
01482 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
01483 #ifndef CDT_ONLY
01484 printf(" -r Refines a previously generated mesh.\n");
01485 printf(
01486 " -q Quality mesh generation. A minimum angle may be specified.\n");
01487 printf(" -a Applies a maximum triangle area constraint.\n");
01488 printf(" -u Applies a user-defined triangle constraint.\n");
01489 #endif
01490 printf(
01491 " -A Applies attributes to identify triangles in certain regions.\n");
01492 printf(" -c Encloses the convex hull with segments.\n");
01493 #ifndef CDT_ONLY
01494 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
01495 #endif
01496
01497
01498
01499
01500 printf(" -j Jettison unused vertices from output .node file.\n");
01501 printf(" -e Generates an edge list.\n");
01502 printf(" -v Generates a Voronoi diagram.\n");
01503 printf(" -n Generates a list of triangle neighbors.\n");
01504 printf(" -g Generates an .off file for Geomview.\n");
01505 printf(" -B Suppresses output of boundary information.\n");
01506 printf(" -P Suppresses output of .poly file.\n");
01507 printf(" -N Suppresses output of .node file.\n");
01508 printf(" -E Suppresses output of .ele file.\n");
01509 printf(" -I Suppresses mesh iteration numbers.\n");
01510 printf(" -O Ignores holes in .poly file.\n");
01511 printf(" -X Suppresses use of exact arithmetic.\n");
01512 printf(" -z Numbers all items starting from zero (rather than one).\n");
01513 printf(" -o2 Generates second-order subparametric elements.\n");
01514 #ifndef CDT_ONLY
01515 printf(" -Y Suppresses boundary segment splitting.\n");
01516 printf(" -S Specifies maximum number of added Steiner points.\n");
01517 #endif
01518 #ifndef REDUCED
01519 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
01520 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
01521 #endif
01522 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
01523 #ifndef REDUCED
01524 #ifndef CDT_ONLY
01525 printf(
01526 " -s Force segments into mesh by splitting (instead of using CDT).\n");
01527 #endif
01528 printf(" -C Check consistency of final mesh.\n");
01529 #endif
01530 printf(" -Q Quiet: No terminal output except errors.\n");
01531 printf(" -V Verbose: Detailed information on what I'm doing.\n");
01532 printf(" -h Help: Detailed instructions for Triangle.\n");
01533 triexit(0);
01534 }
01535
01536 #endif
01537
01538
01539
01540
01541
01542
01543
01544 #ifndef TRILIBRARY
01545
01546 void info()
01547 {
01548 printf("Triangle\n");
01549 printf(
01550 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
01551 printf("Version 1.6\n\n");
01552 printf(
01553 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
01554 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
01555 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
01556 printf(
01557 "Created as part of the Quake project (tools for earthquake simulation).\n");
01558 printf(
01559 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
01560 printf("There is no warranty whatsoever. Use at your own risk.\n");
01561 #ifdef SINGLE
01562 printf("This executable is compiled for single precision arithmetic.\n\n\n");
01563 #else
01564 printf("This executable is compiled for double precision arithmetic.\n\n\n");
01565 #endif
01566 printf(
01567 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
01568 printf(
01569 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
01570 printf(
01571 "high-quality triangular meshes. The latter can be generated with no small\n"
01572 );
01573 printf(
01574 "or large angles, and are thus suitable for finite element analysis. If no\n"
01575 );
01576 printf(
01577 "command line switch is specified, your .node input file is read, and the\n");
01578 printf(
01579 "Delaunay triangulation is returned in .node and .ele output files. The\n");
01580 printf("command syntax is:\n\n");
01581 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
01582 printf(
01583 "Underscores indicate that numbers may optionally follow certain switches.\n");
01584 printf(
01585 "Do not leave any space between a switch and its numeric parameter.\n");
01586 printf(
01587 "input_file must be a file with extension .node, or extension .poly if the\n");
01588 printf(
01589 "-p switch is used. If -r is used, you must supply .node and .ele files,\n");
01590 printf(
01591 "and possibly a .poly file and an .area file as well. The formats of these\n"
01592 );
01593 printf("files are described below.\n\n");
01594 printf("Command Line Switches:\n\n");
01595 printf(
01596 " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
01597 );
01598 printf(
01599 " vertices, segments, holes, regional attributes, and regional area\n");
01600 printf(
01601 " constraints. Generates a constrained Delaunay triangulation (CDT)\n"
01602 );
01603 printf(
01604 " fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
01605 printf(
01606 " constrained Delaunay triangulation (CCDT). If you want a truly\n");
01607 printf(
01608 " Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
01609 printf(
01610 " well. When -p is not used, Triangle reads a .node file by default.\n"
01611 );
01612 printf(
01613 " -r Refines a previously generated mesh. The mesh is read from a .node\n"
01614 );
01615 printf(
01616 " file and an .ele file. If -p is also used, a .poly file is read\n");
01617 printf(
01618 " and used to constrain segments in the mesh. If -a is also used\n");
01619 printf(
01620 " (with no number following), an .area file is read and used to\n");
01621 printf(
01622 " impose area constraints on the mesh. Further details on refinement\n"
01623 );
01624 printf(" appear below.\n");
01625 printf(
01626 " -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
01627 printf(
01628 " Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
01629 );
01630 printf(
01631 " ensure that all angles are between 20 and 140 degrees. An\n");
01632 printf(
01633 " alternative bound on the minimum angle, replacing 20 degrees, may\n");
01634 printf(
01635 " be specified after the `q'. The specified angle may include a\n");
01636 printf(
01637 " decimal point, but not exponential notation. Note that a bound of\n"
01638 );
01639 printf(
01640 " theta degrees on the smallest angle also implies a bound of\n");
01641 printf(
01642 " (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
01643 );
01644 printf(
01645 " degrees or smaller, Triangle is mathematically guaranteed to\n");
01646 printf(
01647 " terminate (assuming infinite precision arithmetic--Triangle may\n");
01648 printf(
01649 " fail to terminate if you run out of precision). In practice,\n");
01650 printf(
01651 " Triangle often succeeds for minimum angles up to 34 degrees. For\n");
01652 printf(
01653 " some meshes, however, you might need to reduce the minimum angle to\n"
01654 );
01655 printf(
01656 " avoid problems associated with insufficient floating-point\n");
01657 printf(" precision.\n");
01658 printf(
01659 " -a Imposes a maximum triangle area. If a number follows the `a', no\n");
01660 printf(
01661 " triangle is generated whose area is larger than that number. If no\n"
01662 );
01663 printf(
01664 " number is specified, an .area file (if -r is used) or .poly file\n");
01665 printf(
01666 " (if -r is not used) specifies a set of maximum area constraints.\n");
01667 printf(
01668 " An .area file contains a separate area constraint for each\n");
01669 printf(
01670 " triangle, and is useful for refining a finite element mesh based on\n"
01671 );
01672 printf(
01673 " a posteriori error estimates. A .poly file can optionally contain\n"
01674 );
01675 printf(
01676 " an area constraint for each segment-bounded region, thereby\n");
01677 printf(
01678 " controlling triangle densities in a first triangulation of a PSLG.\n"
01679 );
01680 printf(
01681 " You can impose both a fixed area constraint and a varying area\n");
01682 printf(
01683 " constraint by invoking the -a switch twice, once with and once\n");
01684 printf(
01685 " without a number following. Each area specified may include a\n");
01686 printf(" decimal point.\n");
01687 printf(
01688 " -u Imposes a user-defined constraint on triangle size. There are two\n"
01689 );
01690 printf(
01691 " ways to use this feature. One is to edit the triunsuitable()\n");
01692 printf(
01693 " procedure in triangle.c to encode any constraint you like, then\n");
01694 printf(
01695 " recompile Triangle. The other is to compile triangle.c with the\n");
01696 printf(
01697 " EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
01698 printf(
01699 " link Triangle with a separate object file that implements\n");
01700 printf(
01701 " triunsuitable(). In either case, the -u switch causes the user-\n");
01702 printf(" defined test to be applied to every triangle.\n");
01703 printf(
01704 " -A Assigns an additional floating-point attribute to each triangle\n");
01705 printf(
01706 " that identifies what segment-bounded region each triangle belongs\n");
01707 printf(
01708 " to. Attributes are assigned to regions by the .poly file. If a\n");
01709 printf(
01710 " region is not explicitly marked by the .poly file, triangles in\n");
01711 printf(
01712 " that region are assigned an attribute of zero. The -A switch has\n");
01713 printf(
01714 " an effect only when the -p switch is used and the -r switch is not.\n"
01715 );
01716 printf(
01717 " -c Creates segments on the convex hull of the triangulation. If you\n");
01718 printf(
01719 " are triangulating a vertex set, this switch causes a .poly file to\n"
01720 );
01721 printf(
01722 " be written, containing all edges of the convex hull. If you are\n");
01723 printf(
01724 " triangulating a PSLG, this switch specifies that the whole convex\n");
01725 printf(
01726 " hull of the PSLG should be triangulated, regardless of what\n");
01727 printf(
01728 " segments the PSLG has. If you do not use this switch when\n");
01729 printf(
01730 " triangulating a PSLG, Triangle assumes that you have identified the\n"
01731 );
01732 printf(
01733 " region to be triangulated by surrounding it with segments of the\n");
01734 printf(
01735 " input PSLG. Beware: if you are not careful, this switch can cause\n"
01736 );
01737 printf(
01738 " the introduction of an extremely thin angle between a PSLG segment\n"
01739 );
01740 printf(
01741 " and a convex hull segment, which can cause overrefinement (and\n");
01742 printf(
01743 " possibly failure if Triangle runs out of precision). If you are\n");
01744 printf(
01745 " refining a mesh, the -c switch works differently: it causes a\n");
01746 printf(
01747 " .poly file to be written containing the boundary edges of the mesh\n"
01748 );
01749 printf(" (useful if no .poly file was read).\n");
01750 printf(
01751 " -D Conforming Delaunay triangulation: use this switch if you want to\n"
01752 );
01753 printf(
01754 " ensure that all the triangles in the mesh are Delaunay, and not\n");
01755 printf(
01756 " merely constrained Delaunay; or if you want to ensure that all the\n"
01757 );
01758 printf(
01759 " Voronoi vertices lie within the triangulation. (Some finite volume\n"
01760 );
01761 printf(
01762 " methods have this requirement.) This switch invokes Ruppert's\n");
01763 printf(
01764 " original algorithm, which splits every subsegment whose diametral\n");
01765 printf(
01766 " circle is encroached. It usually increases the number of vertices\n"
01767 );
01768 printf(" and triangles.\n");
01769 printf(
01770 " -j Jettisons vertices that are not part of the final triangulation\n");
01771 printf(
01772 " from the output .node file. By default, Triangle copies all\n");
01773 printf(
01774 " vertices in the input .node file to the output .node file, in the\n");
01775 printf(
01776 " same order, so their indices do not change. The -j switch prevents\n"
01777 );
01778 printf(
01779 " duplicated input vertices, or vertices `eaten' by holes, from\n");
01780 printf(
01781 " appearing in the output .node file. Thus, if two input vertices\n");
01782 printf(
01783 " have exactly the same coordinates, only the first appears in the\n");
01784 printf(
01785 " output. If any vertices are jettisoned, the vertex numbering in\n");
01786 printf(
01787 " the output .node file differs from that of the input .node file.\n");
01788 printf(
01789 " -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
01790 printf(
01791 " -v Outputs the Voronoi diagram associated with the triangulation.\n");
01792 printf(
01793 " Does not attempt to detect degeneracies, so some Voronoi vertices\n");
01794 printf(
01795 " may be duplicated. See the discussion of Voronoi diagrams below.\n");
01796 printf(
01797 " -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
01798 printf(" triangle.\n");
01799 printf(
01800 " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
01801 );
01802 printf(" viewing with the Geometry Center's Geomview package.\n");
01803 printf(
01804 " -B No boundary markers in the output .node, .poly, and .edge output\n");
01805 printf(
01806 " files. See the detailed discussion of boundary markers below.\n");
01807 printf(
01808 " -P No output .poly file. Saves disk space, but you lose the ability\n");
01809 printf(
01810 " to maintain constraining segments on later refinements of the mesh.\n"
01811 );
01812 printf(" -N No output .node file.\n");
01813 printf(" -E No output .ele file.\n");
01814 printf(
01815 " -I No iteration numbers. Suppresses the output of .node and .poly\n");
01816 printf(
01817 " files, so your input files won't be overwritten. (If your input is\n"
01818 );
01819 printf(
01820 " a .poly file only, a .node file is written.) Cannot be used with\n");
01821 printf(
01822 " the -r switch, because that would overwrite your input .ele file.\n");
01823 printf(
01824 " Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
01825 printf(
01826 " using a .node file for input, because no .node file is written, so\n"
01827 );
01828 printf(" there is no record of any added Steiner points.\n");
01829 printf(" -O No holes. Ignores the holes in the .poly file.\n");
01830 printf(
01831 " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
01832 );
01833 printf(
01834 " arithmetic for certain tests if it thinks the inexact tests are not\n"
01835 );
01836 printf(
01837 " accurate enough. Exact arithmetic ensures the robustness of the\n");
01838 printf(
01839 " triangulation algorithms, despite floating-point roundoff error.\n");
01840 printf(
01841 " Disabling exact arithmetic with the -X switch causes a small\n");
01842 printf(
01843 " improvement in speed and creates the possibility that Triangle will\n"
01844 );
01845 printf(" fail to produce a valid mesh. Not recommended.\n");
01846 printf(
01847 " -z Numbers all items starting from zero (rather than one). Note that\n"
01848 );
01849 printf(
01850 " this switch is normally overridden by the value used to number the\n"
01851 );
01852 printf(
01853 " first vertex of the input .node or .poly file. However, this\n");
01854 printf(
01855 " switch is useful when calling Triangle from another program.\n");
01856 printf(
01857 " -o2 Generates second-order subparametric elements with six nodes each.\n"
01858 );
01859 printf(
01860 " -Y No new vertices on the boundary. This switch is useful when the\n");
01861 printf(
01862 " mesh boundary must be preserved so that it conforms to some\n");
01863 printf(
01864 " adjacent mesh. Be forewarned that you will probably sacrifice much\n"
01865 );
01866 printf(
01867 " of the quality of the mesh; Triangle will try, but the resulting\n");
01868 printf(
01869 " mesh may contain poorly shaped triangles. Works well if all the\n");
01870 printf(
01871 " boundary vertices are closely spaced. Specify this switch twice\n");
01872 printf(
01873 " (`-YY') to prevent all segment splitting, including internal\n");
01874 printf(" boundaries.\n");
01875 printf(
01876 " -S Specifies the maximum number of Steiner points (vertices that are\n");
01877 printf(
01878 " not in the input, but are added to meet the constraints on minimum\n"
01879 );
01880 printf(
01881 " angle and maximum area). The default is to allow an unlimited\n");
01882 printf(
01883 " number. If you specify this switch with no number after it,\n");
01884 printf(
01885 " the limit is set to zero. Triangle always adds vertices at segment\n"
01886 );
01887 printf(
01888 " intersections, even if it needs to use more vertices than the limit\n"
01889 );
01890 printf(
01891 " you set. When Triangle inserts segments by splitting (-s), it\n");
01892 printf(
01893 " always adds enough vertices to ensure that all the segments of the\n"
01894 );
01895 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
01896 printf(
01897 " -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
01898 printf(
01899 " construct a Delaunay triangulation. Try it if the divide-and-\n");
01900 printf(" conquer algorithm fails.\n");
01901 printf(
01902 " -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
01903 printf(
01904 " triangulation. Warning: does not use exact arithmetic for all\n");
01905 printf(" calculations. An exact result is not guaranteed.\n");
01906 printf(
01907 " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
01908 printf(
01909 " default, Triangle alternates between vertical and horizontal cuts,\n"
01910 );
01911 printf(
01912 " which usually improve the speed except with vertex sets that are\n");
01913 printf(
01914 " small or short and wide. This switch is primarily of theoretical\n");
01915 printf(" interest.\n");
01916 printf(
01917 " -s Specifies that segments should be forced into the triangulation by\n"
01918 );
01919 printf(
01920 " recursively splitting them at their midpoints, rather than by\n");
01921 printf(
01922 " generating a constrained Delaunay triangulation. Segment splitting\n"
01923 );
01924 printf(
01925 " is true to Ruppert's original algorithm, but can create needlessly\n"
01926 );
01927 printf(
01928 " small triangles. This switch is primarily of theoretical interest.\n"
01929 );
01930 printf(
01931 " -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
01932 );
01933 printf(
01934 " checking, even if the -X switch is used. Useful if you suspect\n");
01935 printf(" Triangle is buggy.\n");
01936 printf(
01937 " -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
01938 printf(" unless an error occurs.\n");
01939 printf(
01940 " -V Verbose: Gives detailed information about what Triangle is doing.\n"
01941 );
01942 printf(
01943 " Add more `V's for increasing amount of detail. `-V' is most\n");
01944 printf(
01945 " useful; itgives information on algorithmic progress and much more\n");
01946 printf(
01947 " detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
01948 printf(
01949 " prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
01950 );
01951 printf(" information only a debugger could love.\n");
01952 printf(" -h Help: Displays these instructions.\n");
01953 printf("\n");
01954 printf("Definitions:\n");
01955 printf("\n");
01956 printf(
01957 " A Delaunay triangulation of a vertex set is a triangulation whose\n");
01958 printf(
01959 " vertices are the vertex set, that covers the convex hull of the vertex\n");
01960 printf(
01961 " set. A Delaunay triangulation has the property that no vertex lies\n");
01962 printf(
01963 " inside the circumscribing circle (circle that passes through all three\n");
01964 printf(" vertices) of any triangle in the triangulation.\n\n");
01965 printf(
01966 " A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
01967 printf(
01968 " polygonal cells (some of which may be unbounded, meaning infinitely\n");
01969 printf(
01970 " large), where each cell is the set of points in the plane that are closer\n"
01971 );
01972 printf(
01973 " to some input vertex than to any other input vertex. The Voronoi diagram\n"
01974 );
01975 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
01976 printf(
01977 " A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
01978 printf(
01979 " Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
01980 );
01981 printf(
01982 " Segments may intersect each other only at their endpoints. The file\n");
01983 printf(" format for PSLGs (.poly files) is described below.\n\n");
01984 printf(
01985 " A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
01986 printf(
01987 " Delaunay triangulation, but each PSLG segment is present as a single edge\n"
01988 );
01989 printf(
01990 " of the CDT. (A constrained Delaunay triangulation is not truly a\n");
01991 printf(
01992 " Delaunay triangulation, because some of its triangles might not be\n");
01993 printf(
01994 " Delaunay.) By definition, a CDT does not have any vertices other than\n");
01995 printf(
01996 " those specified in the input PSLG. Depending on context, a CDT might\n");
01997 printf(
01998 " cover the convex hull of the PSLG, or it might cover only a segment-\n");
01999 printf(" bounded region (e.g. a polygon).\n\n");
02000 printf(
02001 " A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
02002 );
02003 printf(
02004 " each triangle is truly Delaunay, and each PSLG segment is represented by\n"
02005 );
02006 printf(
02007 " a linear contiguous sequence of edges of the triangulation. New vertices\n"
02008 );
02009 printf(
02010 " (not part of the PSLG) may appear, and each input segment may have been\n");
02011 printf(
02012 " subdivided into shorter edges (subsegments) by these additional vertices.\n"
02013 );
02014 printf(
02015 " The new vertices are frequently necessary to maintain the Delaunay\n");
02016 printf(" property while ensuring that every segment is represented.\n\n");
02017 printf(
02018 " A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
02019 printf(
02020 " triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
02021 printf(" vertices may appear, and input segments may be subdivided into\n");
02022 printf(
02023 " subsegments, but not to guarantee that segments are respected; rather, to\n"
02024 );
02025 printf(
02026 " improve the quality of the triangles. The high-quality meshes produced\n");
02027 printf(
02028 " by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
02029 printf(" with the -D switch.\n\n");
02030 printf("File Formats:\n\n");
02031 printf(
02032 " All files may contain comments prefixed by the character '#'. Vertices,\n"
02033 );
02034 printf(
02035 " triangles, edges, holes, and maximum area constraints must be numbered\n");
02036 printf(
02037 " consecutively, starting from either 1 or 0. Whichever you choose, all\n");
02038 printf(
02039 " input files must be consistent; if the vertices are numbered from 1, so\n");
02040 printf(
02041 " must be all other objects. Triangle automatically detects your choice\n");
02042 printf(
02043 " while reading the .node (or .poly) file. (When calling Triangle from\n");
02044 printf(
02045 " another program, use the -z switch if you wish to number objects from\n");
02046 printf(" zero.) Examples of these file formats are given below.\n\n");
02047 printf(" .node files:\n");
02048 printf(
02049 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02050 );
02051 printf(
02052 " <# of boundary markers (0 or 1)>\n"
02053 );
02054 printf(
02055 " Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02056 printf("\n");
02057 printf(
02058 " The attributes, which are typically floating-point values of physical\n");
02059 printf(
02060 " quantities (such as mass or conductivity) associated with the nodes of\n"
02061 );
02062 printf(
02063 " a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
02064 );
02065 printf(
02066 " -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
02067 );
02068 printf(" has attributes assigned to it by linear interpolation.\n\n");
02069 printf(
02070 " If the fourth entry of the first line is `1', the last column of the\n");
02071 printf(
02072 " remainder of the file is assumed to contain boundary markers. Boundary\n"
02073 );
02074 printf(
02075 " markers are used to identify boundary vertices and vertices resting on\n"
02076 );
02077 printf(
02078 " PSLG segments; a complete description appears in a section below. The\n"
02079 );
02080 printf(
02081 " .node file produced by Triangle contains boundary markers in the last\n");
02082 printf(" column unless they are suppressed by the -B switch.\n\n");
02083 printf(" .ele files:\n");
02084 printf(
02085 " First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
02086 printf(
02087 " Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
02088 printf("\n");
02089 printf(
02090 " Nodes are indices into the corresponding .node file. The first three\n");
02091 printf(
02092 " nodes are the corner vertices, and are listed in counterclockwise order\n"
02093 );
02094 printf(
02095 " around each triangle. (The remaining nodes, if any, depend on the type\n"
02096 );
02097 printf(" of finite element used.)\n\n");
02098 printf(
02099 " The attributes are just like those of .node files. Because there is no\n"
02100 );
02101 printf(
02102 " simple mapping from input to output triangles, Triangle attempts to\n");
02103 printf(
02104 " interpolate attributes, and may cause a lot of diffusion of attributes\n"
02105 );
02106 printf(
02107 " among nearby triangles as the triangulation is refined. Attributes do\n"
02108 );
02109 printf(" not diffuse across segments, so attributes used to identify\n");
02110 printf(" segment-bounded regions remain intact.\n\n");
02111 printf(
02112 " In .ele files produced by Triangle, each triangular element has three\n");
02113 printf(
02114 " nodes (vertices) unless the -o2 switch is used, in which case\n");
02115 printf(
02116 " subparametric quadratic elements with six nodes each are generated.\n");
02117 printf(
02118 " The first three nodes are the corners in counterclockwise order, and\n");
02119 printf(
02120 " the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
02121 printf(
02122 " opposite the first, second, and third vertices, respectively.\n");
02123 printf("\n");
02124 printf(" .poly files:\n");
02125 printf(
02126 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02127 );
02128 printf(
02129 " <# of boundary markers (0 or 1)>\n"
02130 );
02131 printf(
02132 " Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02133 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
02134 printf(
02135 " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
02136 printf(" One line: <# of holes>\n");
02137 printf(" Following lines: <hole #> <x> <y>\n");
02138 printf(
02139 " Optional line: <# of regional attributes and/or area constraints>\n");
02140 printf(
02141 " Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
02142 printf("\n");
02143 printf(
02144 " A .poly file represents a PSLG, as well as some additional information.\n"
02145 );
02146 printf(
02147 " The first section lists all the vertices, and is identical to the\n");
02148 printf(
02149 " format of .node files. <# of vertices> may be set to zero to indicate\n"
02150 );
02151 printf(
02152 " that the vertices are listed in a separate .node file; .poly files\n");
02153 printf(
02154 " produced by Triangle always have this format. A vertex set represented\n"
02155 );
02156 printf(
02157 " this way has the advantage that it may easily be triangulated with or\n");
02158 printf(
02159 " without segments (depending on whether the -p switch is invoked).\n");
02160 printf("\n");
02161 printf(
02162 " The second section lists the segments. Segments are edges whose\n");
02163 printf(
02164 " presence in the triangulation is enforced. (Depending on the choice of\n"
02165 );
02166 printf(
02167 " switches, segment might be subdivided into smaller edges). Each\n");
02168 printf(
02169 " segment is specified by listing the indices of its two endpoints. This\n"
02170 );
02171 printf(
02172 " means that you must include its endpoints in the vertex list. Each\n");
02173 printf(" segment, like each point, may have a boundary marker.\n\n");
02174 printf(
02175 " If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
02176 );
02177 printf(
02178 " Delaunay triangulation (CDT), in which each segment appears as a single\n"
02179 );
02180 printf(
02181 " edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
02182 );
02183 printf(
02184 " produces a conforming constrained Delaunay triangulation (CCDT), in\n");
02185 printf(
02186 " which segments may be subdivided into smaller edges. If -D is\n");
02187 printf(
02188 " selected, Triangle produces a conforming Delaunay triangulation, so\n");
02189 printf(
02190 " that every triangle is Delaunay, and not just constrained Delaunay.\n");
02191 printf("\n");
02192 printf(
02193 " The third section lists holes (and concavities, if -c is selected) in\n");
02194 printf(
02195 " the triangulation. Holes are specified by identifying a point inside\n");
02196 printf(
02197 " each hole. After the triangulation is formed, Triangle creates holes\n");
02198 printf(
02199 " by eating triangles, spreading out from each hole point until its\n");
02200 printf(
02201 " progress is blocked by segments in the PSLG. You must be careful to\n");
02202 printf(
02203 " enclose each hole in segments, or your whole triangulation might be\n");
02204 printf(
02205 " eaten away. If the two triangles abutting a segment are eaten, the\n");
02206 printf(
02207 " segment itself is also eaten. Do not place a hole directly on a\n");
02208 printf(" segment; if you do, Triangle chooses one side of the segment\n");
02209 printf(" arbitrarily.\n\n");
02210 printf(
02211 " The optional fourth section lists regional attributes (to be assigned\n");
02212 printf(
02213 " to all triangles in a region) and regional constraints on the maximum\n");
02214 printf(
02215 " triangle area. Triangle reads this section only if the -A switch is\n");
02216 printf(
02217 " used or the -a switch is used without a number following it, and the -r\n"
02218 );
02219 printf(
02220 " switch is not used. Regional attributes and area constraints are\n");
02221 printf(
02222 " propagated in the same manner as holes: you specify a point for each\n");
02223 printf(
02224 " attribute and/or constraint, and the attribute and/or constraint\n");
02225 printf(
02226 " affects the whole region (bounded by segments) containing the point.\n");
02227 printf(
02228 " If two values are written on a line after the x and y coordinate, the\n");
02229 printf(
02230 " first such value is assumed to be a regional attribute (but is only\n");
02231 printf(
02232 " applied if the -A switch is selected), and the second value is assumed\n"
02233 );
02234 printf(
02235 " to be a regional area constraint (but is only applied if the -a switch\n"
02236 );
02237 printf(
02238 " is selected). You may specify just one value after the coordinates,\n");
02239 printf(
02240 " which can serve as both an attribute and an area constraint, depending\n"
02241 );
02242 printf(
02243 " on the choice of switches. If you are using the -A and -a switches\n");
02244 printf(
02245 " simultaneously and wish to assign an attribute to some region without\n");
02246 printf(" imposing an area constraint, use a negative maximum area.\n\n");
02247 printf(
02248 " When a triangulation is created from a .poly file, you must either\n");
02249 printf(
02250 " enclose the entire region to be triangulated in PSLG segments, or\n");
02251 printf(
02252 " use the -c switch, which automatically creates extra segments that\n");
02253 printf(
02254 " enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
02255 );
02256 printf(
02257 " Triangle eats all triangles that are not enclosed by segments; if you\n");
02258 printf(
02259 " are not careful, your whole triangulation may be eaten away. If you do\n"
02260 );
02261 printf(
02262 " use the -c switch, you can still produce concavities by the appropriate\n"
02263 );
02264 printf(
02265 " placement of holes just inside the boundary of the convex hull.\n");
02266 printf("\n");
02267 printf(
02268 " An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
02269 printf(
02270 " upon segments (except, of course, the endpoints of each segment). You\n"
02271 );
02272 printf(
02273 " aren't required to make your .poly files ideal, but you should be aware\n"
02274 );
02275 printf(
02276 " of what can go wrong. Segment intersections are relatively safe--\n");
02277 printf(
02278 " Triangle calculates the intersection points for you and adds them to\n");
02279 printf(
02280 " the triangulation--as long as your machine's floating-point precision\n");
02281 printf(
02282 " doesn't become a problem. You are tempting the fates if you have three\n"
02283 );
02284 printf(
02285 " segments that cross at the same location, and expect Triangle to figure\n"
02286 );
02287 printf(
02288 " out where the intersection point is. Thanks to floating-point roundoff\n"
02289 );
02290 printf(
02291 " error, Triangle will probably decide that the three segments intersect\n"
02292 );
02293 printf(
02294 " at three different points, and you will find a minuscule triangle in\n");
02295 printf(
02296 " your output--unless Triangle tries to refine the tiny triangle, uses\n");
02297 printf(
02298 " up the last bit of machine precision, and fails to terminate at all.\n");
02299 printf(
02300 " You're better off putting the intersection point in the input files,\n");
02301 printf(
02302 " and manually breaking up each segment into two. Similarly, if you\n");
02303 printf(
02304 " place a vertex at the middle of a segment, and hope that Triangle will\n"
02305 );
02306 printf(
02307 " break up the segment at that vertex, you might get lucky. On the other\n"
02308 );
02309 printf(
02310 " hand, Triangle might decide that the vertex doesn't lie precisely on\n");
02311 printf(
02312 " the segment, and you'll have a needle-sharp triangle in your output--or\n"
02313 );
02314 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
02315 printf("\n");
02316 printf(
02317 " When Triangle reads a .poly file, it also writes a .poly file, which\n");
02318 printf(
02319 " includes all the subsegments--the edges that are parts of input\n");
02320 printf(
02321 " segments. If the -c switch is used, the output .poly file also\n");
02322 printf(
02323 " includes all of the edges on the convex hull. Hence, the output .poly\n"
02324 );
02325 printf(
02326 " file is useful for finding edges associated with input segments and for\n"
02327 );
02328 printf(
02329 " setting boundary conditions in finite element simulations. Moreover,\n");
02330 printf(
02331 " you will need the output .poly file if you plan to refine the output\n");
02332 printf(
02333 " mesh, and don't want segments to be missing in later triangulations.\n");
02334 printf("\n");
02335 printf(" .area files:\n");
02336 printf(" First line: <# of triangles>\n");
02337 printf(" Following lines: <triangle #> <maximum area>\n");
02338 printf("\n");
02339 printf(
02340 " An .area file associates with each triangle a maximum area that is used\n"
02341 );
02342 printf(
02343 " for mesh refinement. As with other file formats, every triangle must\n");
02344 printf(
02345 " be represented, and the triangles must be numbered consecutively. A\n");
02346 printf(
02347 " triangle may be left unconstrained by assigning it a negative maximum\n");
02348 printf(" area.\n\n");
02349 printf(" .edge files:\n");
02350 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
02351 printf(
02352 " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
02353 printf("\n");
02354 printf(
02355 " Endpoints are indices into the corresponding .node file. Triangle can\n"
02356 );
02357 printf(
02358 " produce .edge files (use the -e switch), but cannot read them. The\n");
02359 printf(
02360 " optional column of boundary markers is suppressed by the -B switch.\n");
02361 printf("\n");
02362 printf(
02363 " In Voronoi diagrams, one also finds a special kind of edge that is an\n");
02364 printf(
02365 " infinite ray with only one endpoint. For these edges, a different\n");
02366 printf(" format is used:\n\n");
02367 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
02368 printf(
02369 " The `direction' is a floating-point vector that indicates the direction\n"
02370 );
02371 printf(" of the infinite ray.\n\n");
02372 printf(" .neigh files:\n");
02373 printf(
02374 " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
02375 );
02376 printf(
02377 " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
02378 printf("\n");
02379 printf(
02380 " Neighbors are indices into the corresponding .ele file. An index of -1\n"
02381 );
02382 printf(
02383 " indicates no neighbor (because the triangle is on an exterior\n");
02384 printf(
02385 " boundary). The first neighbor of triangle i is opposite the first\n");
02386 printf(" corner of triangle i, and so on.\n\n");
02387 printf(
02388 " Triangle can produce .neigh files (use the -n switch), but cannot read\n"
02389 );
02390 printf(" them.\n\n");
02391 printf("Boundary Markers:\n\n");
02392 printf(
02393 " Boundary markers are tags used mainly to identify which output vertices\n");
02394 printf(
02395 " and edges are associated with which PSLG segment, and to identify which\n");
02396 printf(
02397 " vertices and edges occur on a boundary of the triangulation. A common\n");
02398 printf(
02399 " use is to determine where boundary conditions should be applied to a\n");
02400 printf(
02401 " finite element mesh. You can prevent boundary markers from being written\n"
02402 );
02403 printf(" into files produced by Triangle by using the -B switch.\n\n");
02404 printf(
02405 " The boundary marker associated with each segment in an output .poly file\n"
02406 );
02407 printf(" and each edge in an output .edge file is chosen as follows:\n");
02408 printf(
02409 " - If an output edge is part or all of a PSLG segment with a nonzero\n");
02410 printf(
02411 " boundary marker, then the edge is assigned the same marker.\n");
02412 printf(
02413 " - Otherwise, if the edge lies on a boundary of the triangulation\n");
02414 printf(
02415 " (even the boundary of a hole), then the edge is assigned the marker\n");
02416 printf(" one (1).\n");
02417 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
02418 printf(
02419 " The boundary marker associated with each vertex in an output .node file\n");
02420 printf(" is chosen as follows:\n");
02421 printf(
02422 " - If a vertex is assigned a nonzero boundary marker in the input file,\n"
02423 );
02424 printf(
02425 " then it is assigned the same marker in the output .node file.\n");
02426 printf(
02427 " - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
02428 printf(
02429 " endpoint of the segment) with a nonzero boundary marker, then the\n");
02430 printf(
02431 " vertex is assigned the same marker. If the vertex lies on several\n");
02432 printf(" such segments, one of the markers is chosen arbitrarily.\n");
02433 printf(
02434 " - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
02435 printf(" then the vertex is assigned the marker one (1).\n");
02436 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
02437 printf("\n");
02438 printf(
02439 " If you want Triangle to determine for you which vertices and edges are on\n"
02440 );
02441 printf(
02442 " the boundary, assign them the boundary marker zero (or use no markers at\n"
02443 );
02444 printf(
02445 " all) in your input files. In the output files, all boundary vertices,\n");
02446 printf(" edges, and segments will be assigned the value one.\n\n");
02447 printf("Triangulation Iteration Numbers:\n\n");
02448 printf(
02449 " Because Triangle can read and refine its own triangulations, input\n");
02450 printf(
02451 " and output files have iteration numbers. For instance, Triangle might\n");
02452 printf(
02453 " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
02454 printf(
02455 " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
02456 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
02457 printf(
02458 " their iteration number is zero; hence, Triangle might read the file\n");
02459 printf(
02460 " points.node, triangulate it, and produce the files points.1.node and\n");
02461 printf(" points.1.ele.\n\n");
02462 printf(
02463 " Iteration numbers allow you to create a sequence of successively finer\n");
02464 printf(
02465 " meshes suitable for multigrid methods. They also allow you to produce a\n"
02466 );
02467 printf(
02468 " sequence of meshes using error estimate-driven mesh refinement.\n");
02469 printf("\n");
02470 printf(
02471 " If you're not using refinement or quality meshing, and you don't like\n");
02472 printf(
02473 " iteration numbers, use the -I switch to disable them. This switch also\n");
02474 printf(
02475 " disables output of .node and .poly files to prevent your input files from\n"
02476 );
02477 printf(
02478 " being overwritten. (If the input is a .poly file that contains its own\n");
02479 printf(
02480 " points, a .node file is written. This can be quite convenient for\n");
02481 printf(" computing CDTs or quality meshes.)\n\n");
02482 printf("Examples of How to Use Triangle:\n\n");
02483 printf(
02484 " `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
02485 );
02486 printf(
02487 " triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
02488 printf(
02489 " to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
02490 printf(
02491 " instead. (No additional .node file is needed, so none is written.)\n");
02492 printf("\n");
02493 printf(
02494 " `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
02495 printf(
02496 " object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
02497 );
02498 printf(
02499 " its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
02500 );
02501 printf(
02502 " The segments are copied to object.2.poly, and all edges are written to\n");
02503 printf(" object.2.edge.\n\n");
02504 printf(
02505 " `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
02506 );
02507 printf(
02508 " object.node), generates a mesh whose angles are all between 31.5 and 117\n"
02509 );
02510 printf(
02511 " degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
02512 );
02513 printf(
02514 " mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
02515 printf(" into multiple subsegments; these are written to object.1.poly.\n");
02516 printf("\n");
02517 printf(
02518 " Here is a sample file `box.poly' describing a square with a square hole:\n"
02519 );
02520 printf("\n");
02521 printf(
02522 " # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
02523 );
02524 printf(" 8 2 0 1\n");
02525 printf(" # Outer box has these vertices:\n");
02526 printf(" 1 0 0 0\n");
02527 printf(" 2 0 3 0\n");
02528 printf(" 3 3 0 0\n");
02529 printf(" 4 3 3 33 # A special marker for this vertex.\n");
02530 printf(" # Inner square has these vertices:\n");
02531 printf(" 5 1 1 0\n");
02532 printf(" 6 1 2 0\n");
02533 printf(" 7 2 1 0\n");
02534 printf(" 8 2 2 0\n");
02535 printf(" # Five segments with boundary markers.\n");
02536 printf(" 5 1\n");
02537 printf(" 1 1 2 5 # Left side of outer box.\n");
02538 printf(" # Square hole has these segments:\n");
02539 printf(" 2 5 7 0\n");
02540 printf(" 3 7 8 0\n");
02541 printf(" 4 8 6 10\n");
02542 printf(" 5 6 5 0\n");
02543 printf(" # One hole in the middle of the inner square.\n");
02544 printf(" 1\n");
02545 printf(" 1 1.5 1.5\n");
02546 printf("\n");
02547 printf(
02548 " Note that some segments are missing from the outer square, so you must\n");
02549 printf(
02550 " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
02551 );
02552 printf(
02553 " file `box.1.node', with twelve vertices. The last four vertices were\n");
02554 printf(
02555 " added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
02556 printf(
02557 " from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
02558 printf(
02559 " other vertices but 4 have been marked to indicate that they lie on a\n");
02560 printf(" boundary.\n\n");
02561 printf(" 12 2 0 1\n");
02562 printf(" 1 0 0 5\n");
02563 printf(" 2 0 3 5\n");
02564 printf(" 3 3 0 1\n");
02565 printf(" 4 3 3 33\n");
02566 printf(" 5 1 1 1\n");
02567 printf(" 6 1 2 10\n");
02568 printf(" 7 2 1 1\n");
02569 printf(" 8 2 2 10\n");
02570 printf(" 9 0 1.5 5\n");
02571 printf(" 10 1.5 0 1\n");
02572 printf(" 11 3 1.5 1\n");
02573 printf(" 12 1.5 3 1\n");
02574 printf(" # Generated by triangle -pqc box.poly\n");
02575 printf("\n");
02576 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
02577 printf("\n");
02578 printf(" 12 3 0\n");
02579 printf(" 1 5 6 9\n");
02580 printf(" 2 10 3 7\n");
02581 printf(" 3 6 8 12\n");
02582 printf(" 4 9 1 5\n");
02583 printf(" 5 6 2 9\n");
02584 printf(" 6 7 3 11\n");
02585 printf(" 7 11 4 8\n");
02586 printf(" 8 7 5 10\n");
02587 printf(" 9 12 2 6\n");
02588 printf(" 10 8 7 11\n");
02589 printf(" 11 5 1 10\n");
02590 printf(" 12 8 4 12\n");
02591 printf(" # Generated by triangle -pqc box.poly\n\n");
02592 printf(
02593 " Here is the output file `box.1.poly'. Note that segments have been added\n"
02594 );
02595 printf(
02596 " to represent the convex hull, and some segments have been subdivided by\n");
02597 printf(
02598 " newly added vertices. Note also that <# of vertices> is set to zero to\n");
02599 printf(" indicate that the vertices should be read from the .node file.\n");
02600 printf("\n");
02601 printf(" 0 2 0 1\n");
02602 printf(" 12 1\n");
02603 printf(" 1 1 9 5\n");
02604 printf(" 2 5 7 1\n");
02605 printf(" 3 8 7 1\n");
02606 printf(" 4 6 8 10\n");
02607 printf(" 5 5 6 1\n");
02608 printf(" 6 3 10 1\n");
02609 printf(" 7 4 11 1\n");
02610 printf(" 8 2 12 1\n");
02611 printf(" 9 9 2 5\n");
02612 printf(" 10 10 1 1\n");
02613 printf(" 11 11 3 1\n");
02614 printf(" 12 12 4 1\n");
02615 printf(" 1\n");
02616 printf(" 1 1.5 1.5\n");
02617 printf(" # Generated by triangle -pqc box.poly\n");
02618 printf("\n");
02619 printf("Refinement and Area Constraints:\n");
02620 printf("\n");
02621 printf(
02622 " The -r switch causes a mesh (.node and .ele files) to be read and\n");
02623 printf(
02624 " refined. If the -p switch is also used, a .poly file is read and used to\n"
02625 );
02626 printf(
02627 " specify edges that are constrained and cannot be eliminated (although\n");
02628 printf(
02629 " they can be subdivided into smaller edges) by the refinement process.\n");
02630 printf("\n");
02631 printf(
02632 " When you refine a mesh, you generally want to impose tighter constraints.\n"
02633 );
02634 printf(
02635 " One way to accomplish this is to use -q with a larger angle, or -a\n");
02636 printf(
02637 " followed by a smaller area than you used to generate the mesh you are\n");
02638 printf(
02639 " refining. Another way to do this is to create an .area file, which\n");
02640 printf(
02641 " specifies a maximum area for each triangle, and use the -a switch\n");
02642 printf(
02643 " (without a number following). Each triangle's area constraint is applied\n"
02644 );
02645 printf(
02646 " to that triangle. Area constraints tend to diffuse as the mesh is\n");
02647 printf(
02648 " refined, so if there are large variations in area constraint between\n");
02649 printf(
02650 " adjacent triangles, you may not get the results you want. In that case,\n"
02651 );
02652 printf(
02653 " consider instead using the -u switch and writing a C procedure that\n");
02654 printf(" determines which triangles are too large.\n\n");
02655 printf(
02656 " If you are refining a mesh composed of linear (three-node) elements, the\n"
02657 );
02658 printf(
02659 " output mesh contains all the nodes present in the input mesh, in the same\n"
02660 );
02661 printf(
02662 " order, with new nodes added at the end of the .node file. However, the\n");
02663 printf(
02664 " refinement is not hierarchical: there is no guarantee that each output\n");
02665 printf(
02666 " element is contained in a single input element. Often, an output element\n"
02667 );
02668 printf(
02669 " can overlap two or three input elements, and some input edges are not\n");
02670 printf(
02671 " present in the output mesh. Hence, a sequence of refined meshes forms a\n"
02672 );
02673 printf(
02674 " hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
02675 printf(
02676 " mesh of higher-order elements, the hierarchical property applies only to\n"
02677 );
02678 printf(
02679 " the nodes at the corners of an element; the midpoint nodes on each edge\n");
02680 printf(" are discarded before the mesh is refined.\n\n");
02681 printf(
02682 " Maximum area constraints in .poly files operate differently from those in\n"
02683 );
02684 printf(
02685 " .area files. A maximum area in a .poly file applies to the whole\n");
02686 printf(
02687 " (segment-bounded) region in which a point falls, whereas a maximum area\n");
02688 printf(
02689 " in an .area file applies to only one triangle. Area constraints in .poly\n"
02690 );
02691 printf(
02692 " files are used only when a mesh is first generated, whereas area\n");
02693 printf(
02694 " constraints in .area files are used only to refine an existing mesh, and\n"
02695 );
02696 printf(
02697 " are typically based on a posteriori error estimates resulting from a\n");
02698 printf(" finite element simulation on that mesh.\n\n");
02699 printf(
02700 " `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
02701 printf(
02702 " refines the triangulation to enforce a 25 degree minimum angle, and then\n"
02703 );
02704 printf(
02705 " writes the refined triangulation to object.2.node and object.2.ele.\n");
02706 printf("\n");
02707 printf(
02708 " `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
02709 );
02710 printf(
02711 " After reconstructing the mesh and its subsegments, Triangle refines the\n");
02712 printf(
02713 " mesh so that no triangle has area greater than 6.2, and furthermore the\n");
02714 printf(
02715 " triangles satisfy the maximum area constraints in z.3.area. No angle\n");
02716 printf(
02717 " bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
02718 );
02719 printf(" z.4.poly.\n\n");
02720 printf(
02721 " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
02722 printf(
02723 " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
02724 printf(" suitable for multigrid.\n\n");
02725 printf("Convex Hulls and Mesh Boundaries:\n\n");
02726 printf(
02727 " If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
02728 printf(
02729 " hull as a by-product in the output .poly file if you use the -c switch.\n");
02730 printf(
02731 " There are faster algorithms for finding a two-dimensional convex hull\n");
02732 printf(" than triangulation, of course, but this one comes for free.\n\n");
02733 printf(
02734 " If the input is an unconstrained mesh (you are using the -r switch but\n");
02735 printf(
02736 " not the -p switch), Triangle produces a list of its boundary edges\n");
02737 printf(
02738 " (including hole boundaries) as a by-product when you use the -c switch.\n");
02739 printf(
02740 " If you also use the -p switch, the output .poly file contains all the\n");
02741 printf(" segments from the input .poly file as well.\n\n");
02742 printf("Voronoi Diagrams:\n\n");
02743 printf(
02744 " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
02745 printf(
02746 " .v.edge. For example, `triangle -v points' reads points.node, produces\n");
02747 printf(
02748 " its Delaunay triangulation in points.1.node and points.1.ele, and\n");
02749 printf(
02750 " produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
02751 );
02752 printf(
02753 " .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
02754 printf(
02755 " file contains a list of all Voronoi edges, some of which may be infinite\n"
02756 );
02757 printf(
02758 " rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
02759 printf(" vertices through Triangle, if so desired.)\n\n");
02760 printf(
02761 " This implementation does not use exact arithmetic to compute the Voronoi\n"
02762 );
02763 printf(
02764 " vertices, and does not check whether neighboring vertices are identical.\n"
02765 );
02766 printf(
02767 " Be forewarned that if the Delaunay triangulation is degenerate or\n");
02768 printf(
02769 " near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
02770 printf(" crossing edges.\n\n");
02771 printf(
02772 " The result is a valid Voronoi diagram only if Triangle's output is a true\n"
02773 );
02774 printf(
02775 " Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
02776 printf(
02777 " may contain crossing edges and other pathology) if the output is a CDT or\n"
02778 );
02779 printf(
02780 " CCDT, or if it has holes or concavities. If the triangulated domain is\n");
02781 printf(
02782 " convex and has no holes, you can use -D switch to force Triangle to\n");
02783 printf(
02784 " construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
02785 printf(" Voronoi diagram will be valid.\n\n");
02786 printf("Mesh Topology:\n\n");
02787 printf(
02788 " You may wish to know which triangles are adjacent to a certain Delaunay\n");
02789 printf(
02790 " edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
02791 printf(
02792 " Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
02793 printf(
02794 " each other. All of this information can be found by cross-referencing\n");
02795 printf(
02796 " output files with the recollection that the Delaunay triangulation and\n");
02797 printf(" the Voronoi diagram are planar duals.\n\n");
02798 printf(
02799 " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
02800 printf(
02801 " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
02802 printf(
02803 " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
02804 printf(
02805 " vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
02806 printf(" of vertex k of the corresponding .node file.\n\n");
02807 printf(
02808 " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
02809 printf(
02810 " vertices of the corresponding Voronoi edge. If the endpoints of a\n");
02811 printf(
02812 " Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
02813 );
02814 printf(
02815 " and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
02816 );
02817 printf(
02818 " respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
02819 );
02820 printf(
02821 " at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
02822 );
02823 printf(
02824 " a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
02825 );
02826 printf(
02827 " adjoin the right and left sides of the corresponding Voronoi edge,\n");
02828 printf(
02829 " respectively. To find which Voronoi cells are adjacent to each other,\n");
02830 printf(" just read the list of Delaunay edges.\n\n");
02831 printf(
02832 " Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
02833 );
02834 printf(
02835 " but you can reconstructed it straightforwardly. For instance, to find\n");
02836 printf(
02837 " all the edges of Voronoi cell 1, search the output .edge file for every\n");
02838 printf(
02839 " edge that has input vertex 1 as an endpoint. The corresponding dual\n");
02840 printf(
02841 " edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
02842 printf("\n");
02843 printf(
02844 " For each Voronoi vertex, the .neigh file gives a list of the three\n");
02845 printf(
02846 " Voronoi vertices attached to it. You might find this more convenient\n");
02847 printf(" than the .v.edge file.\n\n");
02848 printf("Quadratic Elements:\n\n");
02849 printf(
02850 " Triangle generates meshes with subparametric quadratic elements if the\n");
02851 printf(
02852 " -o2 switch is specified. Quadratic elements have six nodes per element,\n"
02853 );
02854 printf(
02855 " rather than three. `Subparametric' means that the edges of the triangles\n"
02856 );
02857 printf(
02858 " are always straight, so that subparametric quadratic elements are\n");
02859 printf(
02860 " geometrically identical to linear elements, even though they can be used\n"
02861 );
02862 printf(
02863 " with quadratic interpolating functions. The three extra nodes of an\n");
02864 printf(
02865 " element fall at the midpoints of the three edges, with the fourth, fifth,\n"
02866 );
02867 printf(
02868 " and sixth nodes appearing opposite the first, second, and third corners\n");
02869 printf(" respectively.\n\n");
02870 printf("Domains with Small Angles:\n\n");
02871 printf(
02872 " If two input segments adjoin each other at a small angle, clearly the -q\n"
02873 );
02874 printf(
02875 " switch cannot remove the small angle. Moreover, Triangle may have no\n");
02876 printf(
02877 " choice but to generate additional triangles whose smallest angles are\n");
02878 printf(
02879 " smaller than the specified bound. However, these triangles only appear\n");
02880 printf(
02881 " between input segments separated by small angles. Moreover, if you\n");
02882 printf(
02883 " request a minimum angle of theta degrees, Triangle will generally produce\n"
02884 );
02885 printf(
02886 " no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
02887 );
02888 printf(" the minimum angle.\n\n");
02889 printf("Statistics:\n\n");
02890 printf(
02891 " After generating a mesh, Triangle prints a count of entities in the\n");
02892 printf(
02893 " output mesh, including the number of vertices, triangles, edges, exterior\n"
02894 );
02895 printf(
02896 " boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
02897 printf(
02898 " including hole boundaries), interior boundary edges (i.e. subsegments of\n"
02899 );
02900 printf(
02901 " input segments not on the boundary), and total subsegments. If you've\n");
02902 printf(
02903 " forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
02904 );
02905 printf(
02906 " with the -rNEP switches to read the mesh and print the statistics without\n"
02907 );
02908 printf(
02909 " writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
02910 printf("\n");
02911 printf(
02912 " The -V switch produces extended statistics, including a rough estimate\n");
02913 printf(
02914 " of memory use, the number of calls to geometric predicates, and\n");
02915 printf(
02916 " histograms of the angles and the aspect ratios of the triangles in the\n");
02917 printf(" mesh.\n\n");
02918 printf("Exact Arithmetic:\n\n");
02919 printf(
02920 " Triangle uses adaptive exact arithmetic to perform what computational\n");
02921 printf(
02922 " geometers call the `orientation' and `incircle' tests. If the floating-\n"
02923 );
02924 printf(
02925 " point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
02926 printf(
02927 " most workstations do), and does not use extended precision internal\n");
02928 printf(
02929 " floating-point registers, then your output is guaranteed to be an\n");
02930 printf(
02931 " absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
02932 );
02933 printf(
02934 " error notwithstanding. The word `adaptive' implies that these arithmetic\n"
02935 );
02936 printf(
02937 " routines compute the result only to the precision necessary to guarantee\n"
02938 );
02939 printf(
02940 " correctness, so they are usually nearly as fast as their approximate\n");
02941 printf(" counterparts.\n\n");
02942 printf(
02943 " May CPUs, including Intel x86 processors, have extended precision\n");
02944 printf(
02945 " floating-point registers. These must be reconfigured so their precision\n"
02946 );
02947 printf(
02948 " is reduced to memory precision. Triangle does this if it is compiled\n");
02949 printf(" correctly. See the makefile for details.\n\n");
02950 printf(
02951 " The exact tests can be disabled with the -X switch. On most inputs, this\n"
02952 );
02953 printf(
02954 " switch reduces the computation time by about eight percent--it's not\n");
02955 printf(
02956 " worth the risk. There are rare difficult inputs (having many collinear\n");
02957 printf(
02958 " and cocircular vertices), however, for which the difference in speed\n");
02959 printf(
02960 " could be a factor of two. Be forewarned that these are precisely the\n");
02961 printf(
02962 " inputs most likely to cause errors if you use the -X switch. Hence, the\n"
02963 );
02964 printf(" -X switch is not recommended.\n\n");
02965 printf(
02966 " Unfortunately, the exact tests don't solve every numerical problem.\n");
02967 printf(
02968 " Exact arithmetic is not used to compute the positions of new vertices,\n");
02969 printf(
02970 " because the bit complexity of vertex coordinates would grow without\n");
02971 printf(
02972 " bound. Hence, segment intersections aren't computed exactly; in very\n");
02973 printf(
02974 " unusual cases, roundoff error in computing an intersection point might\n");
02975 printf(
02976 " actually lead to an inverted triangle and an invalid triangulation.\n");
02977 printf(
02978 " (This is one reason to specify your own intersection points in your .poly\n"
02979 );
02980 printf(
02981 " files.) Similarly, exact arithmetic is not used to compute the vertices\n"
02982 );
02983 printf(" of the Voronoi diagram.\n\n");
02984 printf(
02985 " Another pair of problems not solved by the exact arithmetic routines is\n");
02986 printf(
02987 " underflow and overflow. If Triangle is compiled for double precision\n");
02988 printf(
02989 " arithmetic, I believe that Triangle's geometric predicates work correctly\n"
02990 );
02991 printf(
02992 " if the exponent of every input coordinate falls in the range [-148, 201].\n"
02993 );
02994 printf(
02995 " Underflow can silently prevent the orientation and incircle tests from\n");
02996 printf(
02997 " being performed exactly, while overflow typically causes a floating\n");
02998 printf(" exception.\n\n");
02999 printf("Calling Triangle from Another Program:\n\n");
03000 printf(" Read the file triangle.h for details.\n\n");
03001 printf("Troubleshooting:\n\n");
03002 printf(" Please read this section before mailing me bugs.\n\n");
03003 printf(" `My output mesh has no triangles!'\n\n");
03004 printf(
03005 " If you're using a PSLG, you've probably failed to specify a proper set\n"
03006 );
03007 printf(
03008 " of bounding segments, or forgotten to use the -c switch. Or you may\n");
03009 printf(
03010 " have placed a hole badly, thereby eating all your triangles. To test\n");
03011 printf(" these possibilities, try again with the -c and -O switches.\n");
03012 printf(
03013 " Alternatively, all your input vertices may be collinear, in which case\n"
03014 );
03015 printf(" you can hardly expect to triangulate them.\n\n");
03016 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
03017 printf(
03018 " Bad things can happen when triangles get so small that the distance\n");
03019 printf(
03020 " between their vertices isn't much larger than the precision of your\n");
03021 printf(
03022 " machine's arithmetic. If you've compiled Triangle for single-precision\n"
03023 );
03024 printf(
03025 " arithmetic, you might do better by recompiling it for double-precision.\n"
03026 );
03027 printf(
03028 " Then again, you might just have to settle for more lenient constraints\n"
03029 );
03030 printf(
03031 " on the minimum angle and the maximum area than you had planned.\n");
03032 printf("\n");
03033 printf(
03034 " You can minimize precision problems by ensuring that the origin lies\n");
03035 printf(
03036 " inside your vertex set, or even inside the densest part of your\n");
03037 printf(
03038 " mesh. If you're triangulating an object whose x-coordinates all fall\n");
03039 printf(
03040 " between 6247133 and 6247134, you're not leaving much floating-point\n");
03041 printf(" precision for Triangle to work with.\n\n");
03042 printf(
03043 " Precision problems can occur covertly if the input PSLG contains two\n");
03044 printf(
03045 " segments that meet (or intersect) at an extremely small angle, or if\n");
03046 printf(
03047 " such an angle is introduced by the -c switch. If you don't realize\n");
03048 printf(
03049 " that a tiny angle is being formed, you might never discover why\n");
03050 printf(
03051 " Triangle is crashing. To check for this possibility, use the -S switch\n"
03052 );
03053 printf(
03054 " (with an appropriate limit on the number of Steiner points, found by\n");
03055 printf(
03056 " trial-and-error) to stop Triangle early, and view the output .poly file\n"
03057 );
03058 printf(
03059 " with Show Me (described below). Look carefully for regions where dense\n"
03060 );
03061 printf(
03062 " clusters of vertices are forming and for small angles between segments.\n"
03063 );
03064 printf(
03065 " Zoom in closely, as such segments might look like a single segment from\n"
03066 );
03067 printf(" a distance.\n\n");
03068 printf(
03069 " If some of the input values are too large, Triangle may suffer a\n");
03070 printf(
03071 " floating exception due to overflow when attempting to perform an\n");
03072 printf(
03073 " orientation or incircle test. (Read the section on exact arithmetic\n");
03074 printf(
03075 " above.) Again, I recommend compiling Triangle for double (rather\n");
03076 printf(" than single) precision arithmetic.\n\n");
03077 printf(
03078 " Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
03079 printf(
03080 " -u) with an input that is not segment-bounded--that is, if your input\n");
03081 printf(
03082 " is a vertex set, or you're using the -c switch. If the convex hull of\n"
03083 );
03084 printf(
03085 " your input vertices has collinear vertices on its boundary, an input\n");
03086 printf(
03087 " vertex that you think lies on the convex hull might actually lie just\n");
03088 printf(
03089 " inside the convex hull. If so, the vertex and the nearby convex hull\n");
03090 printf(
03091 " edge form an extremely thin triangle. When Triangle tries to refine\n");
03092 printf(
03093 " the mesh to enforce angle and area constraints, Triangle might generate\n"
03094 );
03095 printf(
03096 " extremely tiny triangles, or it might fail because of insufficient\n");
03097 printf(" floating-point precision.\n\n");
03098 printf(
03099 " `The numbering of the output vertices doesn't match the input vertices.'\n"
03100 );
03101 printf("\n");
03102 printf(
03103 " You may have had duplicate input vertices, or you may have eaten some\n");
03104 printf(
03105 " of your input vertices with a hole, or by placing them outside the area\n"
03106 );
03107 printf(
03108 " enclosed by segments. In any case, you can solve the problem by not\n");
03109 printf(" using the -j switch.\n\n");
03110 printf(
03111 " `Triangle executes without incident, but when I look at the resulting\n");
03112 printf(
03113 " mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
03114 printf("\n");
03115 printf(
03116 " If you select the -X switch, Triangle occasionally makes mistakes due\n");
03117 printf(
03118 " to floating-point roundoff error. Although these errors are rare,\n");
03119 printf(
03120 " don't use the -X switch. If you still have problems, please report the\n"
03121 );
03122 printf(" bug.\n\n");
03123 printf(
03124 " `Triangle executes without incident, but when I look at the resulting\n");
03125 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
03126 printf(" inconsistencies.'\n");
03127 printf("\n");
03128 printf(
03129 " If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
03130 );
03131 printf(
03132 " diagram if the domain you are triangulating is convex and free of\n");
03133 printf(
03134 " holes, and you use the -D switch to construct a conforming Delaunay\n");
03135 printf(" triangulation (instead of a CDT or CCDT).\n\n");
03136 printf(
03137 " Strange things can happen if you've taken liberties with your PSLG. Do\n");
03138 printf(
03139 " you have a vertex lying in the middle of a segment? Triangle sometimes\n");
03140 printf(
03141 " copes poorly with that sort of thing. Do you want to lay out a collinear\n"
03142 );
03143 printf(
03144 " row of evenly spaced, segment-connected vertices? Have you simply\n");
03145 printf(
03146 " defined one long segment connecting the leftmost vertex to the rightmost\n"
03147 );
03148 printf(
03149 " vertex, and a bunch of vertices lying along it? This method occasionally\n"
03150 );
03151 printf(
03152 " works, especially with horizontal and vertical lines, but often it\n");
03153 printf(
03154 " doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
03155 );
03156 printf(" separate segment. If you don't like it, tough.\n\n");
03157 printf(
03158 " Furthermore, if you have segments that intersect other than at their\n");
03159 printf(
03160 " endpoints, try not to let the intersections fall extremely close to PSLG\n"
03161 );
03162 printf(" vertices or each other.\n\n");
03163 printf(
03164 " If you have problems refining a triangulation not produced by Triangle:\n");
03165 printf(
03166 " Are you sure the triangulation is geometrically valid? Is it formatted\n");
03167 printf(
03168 " correctly for Triangle? Are the triangles all listed so the first three\n"
03169 );
03170 printf(
03171 " vertices are their corners in counterclockwise order? Are all of the\n");
03172 printf(
03173 " triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
03174 );
03175 printf(" assumes that it starts with a CDT.\n\n");
03176 printf("Show Me:\n\n");
03177 printf(
03178 " Triangle comes with a separate program named `Show Me', whose primary\n");
03179 printf(
03180 " purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
03181 );
03182 printf(
03183 " purpose is to check the validity of your input files, and do so more\n");
03184 printf(
03185 " thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
03186 printf(
03187 " you have the X Windows system. Sorry, Microsoft Windows users.\n");
03188 printf("\n");
03189 printf("Triangle on the Web:\n");
03190 printf("\n");
03191 printf(" To see an illustrated version of these instructions, check out\n");
03192 printf("\n");
03193 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
03194 printf("\n");
03195 printf("A Brief Plea:\n");
03196 printf("\n");
03197 printf(
03198 " If you use Triangle, and especially if you use it to accomplish real\n");
03199 printf(
03200 " work, I would like very much to hear from you. A short letter or email\n");
03201 printf(
03202 " (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
03203 );
03204 printf(
03205 " to me. The more people I know are using this program, the more easily I\n"
03206 );
03207 printf(
03208 " can justify spending time on improvements, which in turn will benefit\n");
03209 printf(
03210 " you. Also, I can put you on a list to receive email whenever a new\n");
03211 printf(" version of Triangle is available.\n\n");
03212 printf(
03213 " If you use a mesh generated by Triangle in a publication, please include\n"
03214 );
03215 printf(
03216 " an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
03217 );
03218 printf(
03219 " If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
03220 printf(
03221 " ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
03222 printf(
03223 " Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
03224 printf(
03225 " Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
03226 printf(
03227 " Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
03228 printf(
03229 " Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
03230 );
03231 printf(" Geometry.)'\n\n");
03232 printf("Research credit:\n\n");
03233 printf(
03234 " Of course, I can take credit for only a fraction of the ideas that made\n");
03235 printf(
03236 " this mesh generator possible. Triangle owes its existence to the efforts\n"
03237 );
03238 printf(
03239 " of many fine computational geometers and other researchers, including\n");
03240 printf(
03241 " Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
03242 );
03243 printf(
03244 " Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
03245 printf(
03246 " Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
03247 printf(
03248 " Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
03249 printf(
03250 " Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
03251 );
03252 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
03253 printf(
03254 " Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
03255 printf(" source code for references.\n\n");
03256 triexit(0);
03257 }
03258
03259 #endif
03260
03261
03262
03263
03264
03265
03266
03267 void internalerror()
03268 {
03269 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
03270 printf(" Include the message above, your input data set, and the exact\n");
03271 printf(" command line you used to run Triangle.\n");
03272 triexit(1);
03273 }
03274
03275
03276
03277
03278
03279
03280
03281
03282 #ifdef ANSI_DECLARATORS
03283 void parsecommandline(int argc, char **argv, struct behavior *b)
03284 #else
03285 void parsecommandline(argc, argv, b)
03286 int argc;
03287 char **argv;
03288 struct behavior *b;
03289 #endif
03290
03291 {
03292 #ifdef TRILIBRARY
03293 #define STARTINDEX 0
03294 #else
03295 #define STARTINDEX 1
03296 int increment;
03297 int meshnumber;
03298 #endif
03299 int i, j, k;
03300 char workstring[FILENAMESIZE];
03301
03302 b->poly = b->refine = b->quality = 0;
03303 b->vararea = b->fixedarea = b->usertest = 0;
03304 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
03305 b->firstnumber = 1;
03306 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
03307 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
03308 b->noiterationnum = 0;
03309 b->noholes = b->noexact = 0;
03310 b->incremental = b->sweepline = 0;
03311 b->dwyer = 1;
03312 b->splitseg = 0;
03313 b->docheck = 0;
03314 b->nobisect = 0;
03315 b->conformdel = 0;
03316 b->steiner = -1;
03317 b->order = 1;
03318 b->minangle = 0.0;
03319 b->maxarea = -1.0;
03320 b->quiet = b->verbose = 0;
03321 #ifndef TRILIBRARY
03322 b->innodefilename[0] = '\0';
03323 #endif
03324
03325 for (i = STARTINDEX; i < argc; i++) {
03326 #ifndef TRILIBRARY
03327 if (argv[i][0] == '-') {
03328 #endif
03329 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
03330 if (argv[i][j] == 'p') {
03331 b->poly = 1;
03332 }
03333 #ifndef CDT_ONLY
03334 if (argv[i][j] == 'r') {
03335 b->refine = 1;
03336 }
03337 if (argv[i][j] == 'q') {
03338 b->quality = 1;
03339 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03340 (argv[i][j + 1] == '.')) {
03341 k = 0;
03342 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03343 (argv[i][j + 1] == '.')) {
03344 j++;
03345 workstring[k] = argv[i][j];
03346 k++;
03347 }
03348 workstring[k] = '\0';
03349 b->minangle = (REAL) strtod(workstring, (char **) NULL);
03350 } else {
03351 b->minangle = 20.0;
03352 }
03353 }
03354 if (argv[i][j] == 'a') {
03355 b->quality = 1;
03356 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03357 (argv[i][j + 1] == '.')) {
03358 b->fixedarea = 1;
03359 k = 0;
03360 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03361 (argv[i][j + 1] == '.')) {
03362 j++;
03363 workstring[k] = argv[i][j];
03364 k++;
03365 }
03366 workstring[k] = '\0';
03367 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
03368 if (b->maxarea <= 0.0) {
03369 printf("Error: Maximum area must be greater than zero.\n");
03370 triexit(1);
03371 }
03372 } else {
03373 b->vararea = 1;
03374 }
03375 }
03376 if (argv[i][j] == 'u') {
03377 b->quality = 1;
03378 b->usertest = 1;
03379 }
03380 #endif
03381 if (argv[i][j] == 'A') {
03382 b->regionattrib = 1;
03383 }
03384 if (argv[i][j] == 'c') {
03385 b->convex = 1;
03386 }
03387 if (argv[i][j] == 'w') {
03388 b->weighted = 1;
03389 }
03390 if (argv[i][j] == 'W') {
03391 b->weighted = 2;
03392 }
03393 if (argv[i][j] == 'j') {
03394 b->jettison = 1;
03395 }
03396 if (argv[i][j] == 'z') {
03397 b->firstnumber = 0;
03398 }
03399 if (argv[i][j] == 'e') {
03400 b->edgesout = 1;
03401 }
03402 if (argv[i][j] == 'v') {
03403 b->voronoi = 1;
03404 }
03405 if (argv[i][j] == 'n') {
03406 b->neighbors = 1;
03407 }
03408 if (argv[i][j] == 'g') {
03409 b->geomview = 1;
03410 }
03411 if (argv[i][j] == 'B') {
03412 b->nobound = 1;
03413 }
03414 if (argv[i][j] == 'P') {
03415 b->nopolywritten = 1;
03416 }
03417 if (argv[i][j] == 'N') {
03418 b->nonodewritten = 1;
03419 }
03420 if (argv[i][j] == 'E') {
03421 b->noelewritten = 1;
03422 }
03423 #ifndef TRILIBRARY
03424 if (argv[i][j] == 'I') {
03425 b->noiterationnum = 1;
03426 }
03427 #endif
03428 if (argv[i][j] == 'O') {
03429 b->noholes = 1;
03430 }
03431 if (argv[i][j] == 'X') {
03432 b->noexact = 1;
03433 }
03434 if (argv[i][j] == 'o') {
03435 if (argv[i][j + 1] == '2') {
03436 j++;
03437 b->order = 2;
03438 }
03439 }
03440 #ifndef CDT_ONLY
03441 if (argv[i][j] == 'Y') {
03442 b->nobisect++;
03443 }
03444 if (argv[i][j] == 'S') {
03445 b->steiner = 0;
03446 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
03447 j++;
03448 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
03449 }
03450 }
03451 #endif
03452 #ifndef REDUCED
03453 if (argv[i][j] == 'i') {
03454 b->incremental = 1;
03455 }
03456 if (argv[i][j] == 'F') {
03457 b->sweepline = 1;
03458 }
03459 #endif
03460 if (argv[i][j] == 'l') {
03461 b->dwyer = 0;
03462 }
03463 #ifndef REDUCED
03464 #ifndef CDT_ONLY
03465 if (argv[i][j] == 's') {
03466 b->splitseg = 1;
03467 }
03468 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
03469 b->quality = 1;
03470 b->conformdel = 1;
03471 }
03472 #endif
03473 if (argv[i][j] == 'C') {
03474 b->docheck = 1;
03475 }
03476 #endif
03477 if (argv[i][j] == 'Q') {
03478 b->quiet = 1;
03479 }
03480 if (argv[i][j] == 'V') {
03481 b->verbose++;
03482 }
03483 #ifndef TRILIBRARY
03484 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03485 (argv[i][j] == '?')) {
03486 info();
03487 }
03488 #endif
03489 }
03490 #ifndef TRILIBRARY
03491 } else {
03492 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
03493 b->innodefilename[FILENAMESIZE - 1] = '\0';
03494 }
03495 #endif
03496 }
03497 #ifndef TRILIBRARY
03498 if (b->innodefilename[0] == '\0') {
03499 syntax();
03500 }
03501 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
03502 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03503 }
03504 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
03505 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03506 b->poly = 1;
03507 }
03508 #ifndef CDT_ONLY
03509 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
03510 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
03511 b->refine = 1;
03512 }
03513 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
03514 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03515 b->refine = 1;
03516 b->quality = 1;
03517 b->vararea = 1;
03518 }
03519 #endif
03520 #endif
03521 b->usesegments = b->poly || b->refine || b->quality || b->convex;
03522 b->goodangle = cos(b->minangle * PI / 180.0);
03523 if (b->goodangle == 1.0) {
03524 b->offconstant = 0.0;
03525 } else {
03526 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
03527 }
03528 b->goodangle *= b->goodangle;
03529 if (b->refine && b->noiterationnum) {
03530 printf(
03531 "Error: You cannot use the -I switch when refining a triangulation.\n");
03532 triexit(1);
03533 }
03534
03535
03536 if (!b->refine && !b->poly) {
03537 b->vararea = 0;
03538 }
03539
03540
03541 if (b->refine || !b->poly) {
03542 b->regionattrib = 0;
03543 }
03544
03545
03546 if (b->weighted && (b->poly || b->quality)) {
03547 b->weighted = 0;
03548 if (!b->quiet) {
03549 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
03550 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
03551 );
03552 }
03553 }
03554 if (b->jettison && b->nonodewritten && !b->quiet) {
03555 printf("Warning: -j and -N switches are somewhat incompatible.\n");
03556 printf(" If any vertices are jettisoned, you will need the output\n");
03557 printf(" .node file to reconstruct the new node indices.");
03558 }
03559
03560 #ifndef TRILIBRARY
03561 strcpy(b->inpolyfilename, b->innodefilename);
03562 strcpy(b->inelefilename, b->innodefilename);
03563 strcpy(b->areafilename, b->innodefilename);
03564 increment = 0;
03565 strcpy(workstring, b->innodefilename);
03566 j = 1;
03567 while (workstring[j] != '\0') {
03568 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03569 increment = j + 1;
03570 }
03571 j++;
03572 }
03573 meshnumber = 0;
03574 if (increment > 0) {
03575 j = increment;
03576 do {
03577 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03578 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03579 } else {
03580 increment = 0;
03581 }
03582 j++;
03583 } while (workstring[j] != '\0');
03584 }
03585 if (b->noiterationnum) {
03586 strcpy(b->outnodefilename, b->innodefilename);
03587 strcpy(b->outelefilename, b->innodefilename);
03588 strcpy(b->edgefilename, b->innodefilename);
03589 strcpy(b->vnodefilename, b->innodefilename);
03590 strcpy(b->vedgefilename, b->innodefilename);
03591 strcpy(b->neighborfilename, b->innodefilename);
03592 strcpy(b->offfilename, b->innodefilename);
03593 strcat(b->outnodefilename, ".node");
03594 strcat(b->outelefilename, ".ele");
03595 strcat(b->edgefilename, ".edge");
03596 strcat(b->vnodefilename, ".v.node");
03597 strcat(b->vedgefilename, ".v.edge");
03598 strcat(b->neighborfilename, ".neigh");
03599 strcat(b->offfilename, ".off");
03600 } else if (increment == 0) {
03601 strcpy(b->outnodefilename, b->innodefilename);
03602 strcpy(b->outpolyfilename, b->innodefilename);
03603 strcpy(b->outelefilename, b->innodefilename);
03604 strcpy(b->edgefilename, b->innodefilename);
03605 strcpy(b->vnodefilename, b->innodefilename);
03606 strcpy(b->vedgefilename, b->innodefilename);
03607 strcpy(b->neighborfilename, b->innodefilename);
03608 strcpy(b->offfilename, b->innodefilename);
03609 strcat(b->outnodefilename, ".1.node");
03610 strcat(b->outpolyfilename, ".1.poly");
03611 strcat(b->outelefilename, ".1.ele");
03612 strcat(b->edgefilename, ".1.edge");
03613 strcat(b->vnodefilename, ".1.v.node");
03614 strcat(b->vedgefilename, ".1.v.edge");
03615 strcat(b->neighborfilename, ".1.neigh");
03616 strcat(b->offfilename, ".1.off");
03617 } else {
03618 workstring[increment] = '%';
03619 workstring[increment + 1] = 'd';
03620 workstring[increment + 2] = '\0';
03621 sprintf(b->outnodefilename, workstring, meshnumber + 1);
03622 strcpy(b->outpolyfilename, b->outnodefilename);
03623 strcpy(b->outelefilename, b->outnodefilename);
03624 strcpy(b->edgefilename, b->outnodefilename);
03625 strcpy(b->vnodefilename, b->outnodefilename);
03626 strcpy(b->vedgefilename, b->outnodefilename);
03627 strcpy(b->neighborfilename, b->outnodefilename);
03628 strcpy(b->offfilename, b->outnodefilename);
03629 strcat(b->outnodefilename, ".node");
03630 strcat(b->outpolyfilename, ".poly");
03631 strcat(b->outelefilename, ".ele");
03632 strcat(b->edgefilename, ".edge");
03633 strcat(b->vnodefilename, ".v.node");
03634 strcat(b->vedgefilename, ".v.edge");
03635 strcat(b->neighborfilename, ".neigh");
03636 strcat(b->offfilename, ".off");
03637 }
03638 strcat(b->innodefilename, ".node");
03639 strcat(b->inpolyfilename, ".poly");
03640 strcat(b->inelefilename, ".ele");
03641 strcat(b->areafilename, ".area");
03642 #endif
03643 }
03644
03647
03648
03649
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664 #ifdef ANSI_DECLARATORS
03665 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
03666 #else
03667 void printtriangle(m, b, t)
03668 struct mesh *m;
03669 struct behavior *b;
03670 struct otri *t;
03671 #endif
03672
03673 {
03674 struct otri printtri;
03675 struct osub printsh;
03676 vertex printvertex;
03677
03678 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
03679 t->orient);
03680 decode(t->tri[0], printtri);
03681 if (printtri.tri == m->dummytri) {
03682 printf(" [0] = Outer space\n");
03683 } else {
03684 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
03685 printtri.orient);
03686 }
03687 decode(t->tri[1], printtri);
03688 if (printtri.tri == m->dummytri) {
03689 printf(" [1] = Outer space\n");
03690 } else {
03691 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
03692 printtri.orient);
03693 }
03694 decode(t->tri[2], printtri);
03695 if (printtri.tri == m->dummytri) {
03696 printf(" [2] = Outer space\n");
03697 } else {
03698 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
03699 printtri.orient);
03700 }
03701
03702 org(*t, printvertex);
03703 if (printvertex == (vertex) NULL)
03704 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
03705 else
03706 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03707 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
03708 printvertex[0], printvertex[1]);
03709 dest(*t, printvertex);
03710 if (printvertex == (vertex) NULL)
03711 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
03712 else
03713 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03714 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
03715 printvertex[0], printvertex[1]);
03716 apex(*t, printvertex);
03717 if (printvertex == (vertex) NULL)
03718 printf(" Apex [%d] = NULL\n", t->orient + 3);
03719 else
03720 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
03721 t->orient + 3, (unsigned long) printvertex,
03722 printvertex[0], printvertex[1]);
03723
03724 if (b->usesegments) {
03725 sdecode(t->tri[6], printsh);
03726 if (printsh.ss != m->dummysub) {
03727 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
03728 printsh.ssorient);
03729 }
03730 sdecode(t->tri[7], printsh);
03731 if (printsh.ss != m->dummysub) {
03732 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
03733 printsh.ssorient);
03734 }
03735 sdecode(t->tri[8], printsh);
03736 if (printsh.ss != m->dummysub) {
03737 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
03738 printsh.ssorient);
03739 }
03740 }
03741
03742 if (b->vararea) {
03743 printf(" Area constraint: %.4g\n", areabound(*t));
03744 }
03745 }
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758 #ifdef ANSI_DECLARATORS
03759 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
03760 #else
03761 void printsubseg(m, b, s)
03762 struct mesh *m;
03763 struct behavior *b;
03764 struct osub *s;
03765 #endif
03766
03767 {
03768 struct osub printsh;
03769 struct otri printtri;
03770 vertex printvertex;
03771
03772 printf("subsegment x%lx with orientation %d and mark %d:\n",
03773 (unsigned long) s->ss, s->ssorient, mark(*s));
03774 sdecode(s->ss[0], printsh);
03775 if (printsh.ss == m->dummysub) {
03776 printf(" [0] = No subsegment\n");
03777 } else {
03778 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
03779 printsh.ssorient);
03780 }
03781 sdecode(s->ss[1], printsh);
03782 if (printsh.ss == m->dummysub) {
03783 printf(" [1] = No subsegment\n");
03784 } else {
03785 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
03786 printsh.ssorient);
03787 }
03788
03789 sorg(*s, printvertex);
03790 if (printvertex == (vertex) NULL)
03791 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
03792 else
03793 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03794 2 + s->ssorient, (unsigned long) printvertex,
03795 printvertex[0], printvertex[1]);
03796 sdest(*s, printvertex);
03797 if (printvertex == (vertex) NULL)
03798 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
03799 else
03800 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03801 3 - s->ssorient, (unsigned long) printvertex,
03802 printvertex[0], printvertex[1]);
03803
03804 decode(s->ss[6], printtri);
03805 if (printtri.tri == m->dummytri) {
03806 printf(" [6] = Outer space\n");
03807 } else {
03808 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
03809 printtri.orient);
03810 }
03811 decode(s->ss[7], printtri);
03812 if (printtri.tri == m->dummytri) {
03813 printf(" [7] = Outer space\n");
03814 } else {
03815 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
03816 printtri.orient);
03817 }
03818
03819 segorg(*s, printvertex);
03820 if (printvertex == (vertex) NULL)
03821 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
03822 else
03823 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
03824 4 + s->ssorient, (unsigned long) printvertex,
03825 printvertex[0], printvertex[1]);
03826 segdest(*s, printvertex);
03827 if (printvertex == (vertex) NULL)
03828 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
03829 else
03830 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
03831 5 - s->ssorient, (unsigned long) printvertex,
03832 printvertex[0], printvertex[1]);
03833 }
03834
03837
03838
03839
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852 #ifdef ANSI_DECLARATORS
03853 void poolzero(struct memorypool *pool)
03854 #else
03855 void poolzero(pool)
03856 struct memorypool *pool;
03857 #endif
03858
03859 {
03860 pool->firstblock = (VOID **) NULL;
03861 pool->nowblock = (VOID **) NULL;
03862 pool->nextitem = (VOID *) NULL;
03863 pool->deaditemstack = (VOID *) NULL;
03864 pool->pathblock = (VOID **) NULL;
03865 pool->pathitem = (VOID *) NULL;
03866 pool->alignbytes = 0;
03867 pool->itembytes = 0;
03868 pool->itemsperblock = 0;
03869 pool->itemsfirstblock = 0;
03870 pool->items = 0;
03871 pool->maxitems = 0;
03872 pool->unallocateditems = 0;
03873 pool->pathitemsleft = 0;
03874 }
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886 #ifdef ANSI_DECLARATORS
03887 void poolrestart(struct memorypool *pool)
03888 #else
03889 void poolrestart(pool)
03890 struct memorypool *pool;
03891 #endif
03892
03893 {
03894 unsigned long alignptr;
03895
03896 pool->items = 0;
03897 pool->maxitems = 0;
03898
03899
03900 pool->nowblock = pool->firstblock;
03901
03902 alignptr = (unsigned long) (pool->nowblock + 1);
03903
03904 pool->nextitem = (VOID *)
03905 (alignptr + (unsigned long) pool->alignbytes -
03906 (alignptr % (unsigned long) pool->alignbytes));
03907
03908 pool->unallocateditems = pool->itemsfirstblock;
03909
03910 pool->deaditemstack = (VOID *) NULL;
03911 }
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932 #ifdef ANSI_DECLARATORS
03933 void poolinit(struct memorypool *pool, int bytecount, int itemcount,
03934 int firstitemcount, unsigned alignment)
03935 #else
03936 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
03937 struct memorypool *pool;
03938 int bytecount;
03939 int itemcount;
03940 int firstitemcount;
03941 unsigned alignment;
03942 #endif
03943
03944 {
03945
03946
03947
03948
03949 if (alignment > sizeof(VOID *)) {
03950 pool->alignbytes = alignment;
03951 } else {
03952 pool->alignbytes = sizeof(VOID *);
03953 }
03954 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
03955 pool->alignbytes;
03956 pool->itemsperblock = itemcount;
03957 if (firstitemcount == 0) {
03958 pool->itemsfirstblock = itemcount;
03959 } else {
03960 pool->itemsfirstblock = firstitemcount;
03961 }
03962
03963
03964
03965
03966 pool->firstblock = (VOID **)
03967 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
03968 pool->alignbytes);
03969
03970 *(pool->firstblock) = (VOID *) NULL;
03971 poolrestart(pool);
03972 }
03973
03974
03975
03976
03977
03978
03979
03980 #ifdef ANSI_DECLARATORS
03981 void pooldeinit(struct memorypool *pool)
03982 #else
03983 void pooldeinit(pool)
03984 struct memorypool *pool;
03985 #endif
03986
03987 {
03988 while (pool->firstblock != (VOID **) NULL) {
03989 pool->nowblock = (VOID **) *(pool->firstblock);
03990 trifree((VOID *) pool->firstblock);
03991 pool->firstblock = pool->nowblock;
03992 }
03993 }
03994
03995
03996
03997
03998
03999
04000
04001 #ifdef ANSI_DECLARATORS
04002 VOID *poolalloc(struct memorypool *pool)
04003 #else
04004 VOID *poolalloc(pool)
04005 struct memorypool *pool;
04006 #endif
04007
04008 {
04009 VOID *newitem;
04010 VOID **newblock;
04011 unsigned long alignptr;
04012
04013
04014
04015 if (pool->deaditemstack != (VOID *) NULL) {
04016 newitem = pool->deaditemstack;
04017 pool->deaditemstack = * (VOID **) pool->deaditemstack;
04018 } else {
04019
04020 if (pool->unallocateditems == 0) {
04021
04022 if (*(pool->nowblock) == (VOID *) NULL) {
04023
04024 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
04025 (int) sizeof(VOID *) +
04026 pool->alignbytes);
04027 *(pool->nowblock) = (VOID *) newblock;
04028
04029 *newblock = (VOID *) NULL;
04030 }
04031
04032
04033 pool->nowblock = (VOID **) *(pool->nowblock);
04034
04035
04036 alignptr = (unsigned long) (pool->nowblock + 1);
04037
04038 pool->nextitem = (VOID *)
04039 (alignptr + (unsigned long) pool->alignbytes -
04040 (alignptr % (unsigned long) pool->alignbytes));
04041
04042 pool->unallocateditems = pool->itemsperblock;
04043 }
04044
04045
04046 newitem = pool->nextitem;
04047
04048 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
04049 pool->unallocateditems--;
04050 pool->maxitems++;
04051 }
04052 pool->items++;
04053 return newitem;
04054 }
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064 #ifdef ANSI_DECLARATORS
04065 void pooldealloc(struct memorypool *pool, VOID *dyingitem)
04066 #else
04067 void pooldealloc(pool, dyingitem)
04068 struct memorypool *pool;
04069 VOID *dyingitem;
04070 #endif
04071
04072 {
04073
04074 *((VOID **) dyingitem) = pool->deaditemstack;
04075 pool->deaditemstack = dyingitem;
04076 pool->items--;
04077 }
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087 #ifdef ANSI_DECLARATORS
04088 void traversalinit(struct memorypool *pool)
04089 #else
04090 void traversalinit(pool)
04091 struct memorypool *pool;
04092 #endif
04093
04094 {
04095 unsigned long alignptr;
04096
04097
04098 pool->pathblock = pool->firstblock;
04099
04100 alignptr = (unsigned long) (pool->pathblock + 1);
04101
04102 pool->pathitem = (VOID *)
04103 (alignptr + (unsigned long) pool->alignbytes -
04104 (alignptr % (unsigned long) pool->alignbytes));
04105
04106 pool->pathitemsleft = pool->itemsfirstblock;
04107 }
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123 #ifdef ANSI_DECLARATORS
04124 VOID *traverse(struct memorypool *pool)
04125 #else
04126 VOID *traverse(pool)
04127 struct memorypool *pool;
04128 #endif
04129
04130 {
04131 VOID *newitem;
04132 unsigned long alignptr;
04133
04134
04135 if (pool->pathitem == pool->nextitem) {
04136 return (VOID *) NULL;
04137 }
04138
04139
04140 if (pool->pathitemsleft == 0) {
04141
04142 pool->pathblock = (VOID **) *(pool->pathblock);
04143
04144 alignptr = (unsigned long) (pool->pathblock + 1);
04145
04146 pool->pathitem = (VOID *)
04147 (alignptr + (unsigned long) pool->alignbytes -
04148 (alignptr % (unsigned long) pool->alignbytes));
04149
04150 pool->pathitemsleft = pool->itemsperblock;
04151 }
04152
04153 newitem = pool->pathitem;
04154
04155 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
04156 pool->pathitemsleft--;
04157 return newitem;
04158 }
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188 #ifdef ANSI_DECLARATORS
04189 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
04190 int subsegbytes)
04191 #else
04192 void dummyinit(m, b, trianglebytes, subsegbytes)
04193 struct mesh *m;
04194 struct behavior *b;
04195 int trianglebytes;
04196 int subsegbytes;
04197 #endif
04198
04199 {
04200 unsigned long alignptr;
04201
04202
04203 m->dummytribase = (triangle *) trimalloc(trianglebytes +
04204 m->triangles.alignbytes);
04205
04206 alignptr = (unsigned long) m->dummytribase;
04207 m->dummytri = (triangle *)
04208 (alignptr + (unsigned long) m->triangles.alignbytes -
04209 (alignptr % (unsigned long) m->triangles.alignbytes));
04210
04211
04212
04213
04214 m->dummytri[0] = (triangle) m->dummytri;
04215 m->dummytri[1] = (triangle) m->dummytri;
04216 m->dummytri[2] = (triangle) m->dummytri;
04217
04218 m->dummytri[3] = (triangle) NULL;
04219 m->dummytri[4] = (triangle) NULL;
04220 m->dummytri[5] = (triangle) NULL;
04221
04222 if (b->usesegments) {
04223
04224
04225
04226 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
04227 m->subsegs.alignbytes);
04228
04229 alignptr = (unsigned long) m->dummysubbase;
04230 m->dummysub = (subseg *)
04231 (alignptr + (unsigned long) m->subsegs.alignbytes -
04232 (alignptr % (unsigned long) m->subsegs.alignbytes));
04233
04234
04235
04236
04237 m->dummysub[0] = (subseg) m->dummysub;
04238 m->dummysub[1] = (subseg) m->dummysub;
04239
04240 m->dummysub[2] = (subseg) NULL;
04241 m->dummysub[3] = (subseg) NULL;
04242 m->dummysub[4] = (subseg) NULL;
04243 m->dummysub[5] = (subseg) NULL;
04244
04245 m->dummysub[6] = (subseg) m->dummytri;
04246 m->dummysub[7] = (subseg) m->dummytri;
04247
04248 * (int *) (m->dummysub + 8) = 0;
04249
04250
04251
04252 m->dummytri[6] = (triangle) m->dummysub;
04253 m->dummytri[7] = (triangle) m->dummysub;
04254 m->dummytri[8] = (triangle) m->dummysub;
04255 }
04256 }
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268 #ifdef ANSI_DECLARATORS
04269 void initializevertexpool(struct mesh *m, struct behavior *b)
04270 #else
04271 void initializevertexpool(m, b)
04272 struct mesh *m;
04273 struct behavior *b;
04274 #endif
04275
04276 {
04277 int vertexsize;
04278
04279
04280
04281
04282 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
04283 sizeof(int) - 1) /
04284 sizeof(int);
04285 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
04286 if (b->poly) {
04287
04288
04289 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
04290 sizeof(triangle);
04291 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
04292 }
04293
04294
04295 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
04296 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
04297 sizeof(REAL));
04298 }
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311 #ifdef ANSI_DECLARATORS
04312 void initializetrisubpools(struct mesh *m, struct behavior *b)
04313 #else
04314 void initializetrisubpools(m, b)
04315 struct mesh *m;
04316 struct behavior *b;
04317 #endif
04318
04319 {
04320 unsigned trisize;
04321
04322
04323
04324
04325
04326 m->highorderindex = 6 + (b->usesegments * 3);
04327
04328 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
04329 sizeof(triangle);
04330
04331
04332 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
04333
04334
04335
04336 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
04337
04338
04339 if (b->vararea) {
04340 trisize = (m->areaboundindex + 1) * sizeof(REAL);
04341 } else if (m->eextras + b->regionattrib > 0) {
04342 trisize = m->areaboundindex * sizeof(REAL);
04343 }
04344
04345
04346
04347
04348 if ((b->voronoi || b->neighbors) &&
04349 (trisize < 6 * sizeof(triangle) + sizeof(int))) {
04350 trisize = 6 * sizeof(triangle) + sizeof(int);
04351 }
04352
04353
04354 poolinit(&m->triangles, trisize, TRIPERBLOCK,
04355 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
04356 TRIPERBLOCK, 4);
04357
04358 if (b->usesegments) {
04359
04360
04361 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
04362 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
04363
04364
04365 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
04366 } else {
04367
04368 dummyinit(m, b, m->triangles.itembytes, 0);
04369 }
04370 }
04371
04372
04373
04374
04375
04376
04377
04378 #ifdef ANSI_DECLARATORS
04379 void triangledealloc(struct mesh *m, triangle *dyingtriangle)
04380 #else
04381 void triangledealloc(m, dyingtriangle)
04382 struct mesh *m;
04383 triangle *dyingtriangle;
04384 #endif
04385
04386 {
04387
04388
04389 killtri(dyingtriangle);
04390 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
04391 }
04392
04393
04394
04395
04396
04397
04398
04399 #ifdef ANSI_DECLARATORS
04400 triangle *triangletraverse(struct mesh *m)
04401 #else
04402 triangle *triangletraverse(m)
04403 struct mesh *m;
04404 #endif
04405
04406 {
04407 triangle *newtriangle;
04408
04409 do {
04410 newtriangle = (triangle *) traverse(&m->triangles);
04411 if (newtriangle == (triangle *) NULL) {
04412 return (triangle *) NULL;
04413 }
04414 } while (deadtri(newtriangle));
04415 return newtriangle;
04416 }
04417
04418
04419
04420
04421
04422
04423
04424 #ifdef ANSI_DECLARATORS
04425 void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
04426 #else
04427 void subsegdealloc(m, dyingsubseg)
04428 struct mesh *m;
04429 subseg *dyingsubseg;
04430 #endif
04431
04432 {
04433
04434
04435 killsubseg(dyingsubseg);
04436 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
04437 }
04438
04439
04440
04441
04442
04443
04444
04445 #ifdef ANSI_DECLARATORS
04446 subseg *subsegtraverse(struct mesh *m)
04447 #else
04448 subseg *subsegtraverse(m)
04449 struct mesh *m;
04450 #endif
04451
04452 {
04453 subseg *newsubseg;
04454
04455 do {
04456 newsubseg = (subseg *) traverse(&m->subsegs);
04457 if (newsubseg == (subseg *) NULL) {
04458 return (subseg *) NULL;
04459 }
04460 } while (deadsubseg(newsubseg));
04461 return newsubseg;
04462 }
04463
04464
04465
04466
04467
04468
04469
04470 #ifdef ANSI_DECLARATORS
04471 void vertexdealloc(struct mesh *m, vertex dyingvertex)
04472 #else
04473 void vertexdealloc(m, dyingvertex)
04474 struct mesh *m;
04475 vertex dyingvertex;
04476 #endif
04477
04478 {
04479
04480
04481 setvertextype(dyingvertex, DEADVERTEX);
04482 pooldealloc(&m->vertices, (VOID *) dyingvertex);
04483 }
04484
04485
04486
04487
04488
04489
04490
04491 #ifdef ANSI_DECLARATORS
04492 vertex vertextraverse(struct mesh *m)
04493 #else
04494 vertex vertextraverse(m)
04495 struct mesh *m;
04496 #endif
04497
04498 {
04499 vertex newvertex;
04500
04501 do {
04502 newvertex = (vertex) traverse(&m->vertices);
04503 if (newvertex == (vertex) NULL) {
04504 return (vertex) NULL;
04505 }
04506 } while (vertextype(newvertex) == DEADVERTEX);
04507 return newvertex;
04508 }
04509
04510
04511
04512
04513
04514
04515
04516
04517 #ifndef CDT_ONLY
04518
04519 #ifdef ANSI_DECLARATORS
04520 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
04521 #else
04522 void badsubsegdealloc(m, dyingseg)
04523 struct mesh *m;
04524 struct badsubseg *dyingseg;
04525 #endif
04526
04527 {
04528
04529
04530 dyingseg->subsegorg = (vertex) NULL;
04531 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
04532 }
04533
04534 #endif
04535
04536
04537
04538
04539
04540
04541
04542 #ifndef CDT_ONLY
04543
04544 #ifdef ANSI_DECLARATORS
04545 struct badsubseg *badsubsegtraverse(struct mesh *m)
04546 #else
04547 struct badsubseg *badsubsegtraverse(m)
04548 struct mesh *m;
04549 #endif
04550
04551 {
04552 struct badsubseg *newseg;
04553
04554 do {
04555 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
04556 if (newseg == (struct badsubseg *) NULL) {
04557 return (struct badsubseg *) NULL;
04558 }
04559 } while (newseg->subsegorg == (vertex) NULL);
04560 return newseg;
04561 }
04562
04563 #endif
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577 #ifdef ANSI_DECLARATORS
04578 vertex getvertex(struct mesh *m, struct behavior *b, int number)
04579 #else
04580 vertex getvertex(m, b, number)
04581 struct mesh *m;
04582 struct behavior *b;
04583 int number;
04584 #endif
04585
04586 {
04587 VOID **getblock;
04588 char *foundvertex;
04589 unsigned long alignptr;
04590 int current;
04591
04592 getblock = m->vertices.firstblock;
04593 current = b->firstnumber;
04594
04595
04596 if (current + m->vertices.itemsfirstblock <= number) {
04597 getblock = (VOID **) *getblock;
04598 current += m->vertices.itemsfirstblock;
04599 while (current + m->vertices.itemsperblock <= number) {
04600 getblock = (VOID **) *getblock;
04601 current += m->vertices.itemsperblock;
04602 }
04603 }
04604
04605
04606 alignptr = (unsigned long) (getblock + 1);
04607 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
04608 (alignptr % (unsigned long) m->vertices.alignbytes));
04609 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
04610 }
04611
04612
04613
04614
04615
04616
04617
04618 #ifdef ANSI_DECLARATORS
04619 void triangledeinit(struct mesh *m, struct behavior *b)
04620 #else
04621 void triangledeinit(m, b)
04622 struct mesh *m;
04623 struct behavior *b;
04624 #endif
04625
04626 {
04627 pooldeinit(&m->triangles);
04628 trifree((VOID *) m->dummytribase);
04629 if (b->usesegments) {
04630 pooldeinit(&m->subsegs);
04631 trifree((VOID *) m->dummysubbase);
04632 }
04633 pooldeinit(&m->vertices);
04634 #ifndef CDT_ONLY
04635 if (b->quality) {
04636 pooldeinit(&m->badsubsegs);
04637 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
04638 pooldeinit(&m->badtriangles);
04639 pooldeinit(&m->flipstackers);
04640 }
04641 }
04642 #endif
04643 }
04644
04647
04648
04649
04653
04654
04655
04656
04657
04658
04659 #ifdef ANSI_DECLARATORS
04660 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
04661 #else
04662 void maketriangle(m, b, newotri)
04663 struct mesh *m;
04664 struct behavior *b;
04665 struct otri *newotri;
04666 #endif
04667
04668 {
04669 int i;
04670
04671 newotri->tri = (triangle *) poolalloc(&m->triangles);
04672
04673 newotri->tri[0] = (triangle) m->dummytri;
04674 newotri->tri[1] = (triangle) m->dummytri;
04675 newotri->tri[2] = (triangle) m->dummytri;
04676
04677 newotri->tri[3] = (triangle) NULL;
04678 newotri->tri[4] = (triangle) NULL;
04679 newotri->tri[5] = (triangle) NULL;
04680 if (b->usesegments) {
04681
04682
04683 newotri->tri[6] = (triangle) m->dummysub;
04684 newotri->tri[7] = (triangle) m->dummysub;
04685 newotri->tri[8] = (triangle) m->dummysub;
04686 }
04687 for (i = 0; i < m->eextras; i++) {
04688 setelemattribute(*newotri, i, 0.0);
04689 }
04690 if (b->vararea) {
04691 setareabound(*newotri, -1.0);
04692 }
04693
04694 newotri->orient = 0;
04695 }
04696
04697
04698
04699
04700
04701
04702
04703 #ifdef ANSI_DECLARATORS
04704 void makesubseg(struct mesh *m, struct osub *newsubseg)
04705 #else
04706 void makesubseg(m, newsubseg)
04707 struct mesh *m;
04708 struct osub *newsubseg;
04709 #endif
04710
04711 {
04712 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
04713
04714
04715 newsubseg->ss[0] = (subseg) m->dummysub;
04716 newsubseg->ss[1] = (subseg) m->dummysub;
04717
04718 newsubseg->ss[2] = (subseg) NULL;
04719 newsubseg->ss[3] = (subseg) NULL;
04720 newsubseg->ss[4] = (subseg) NULL;
04721 newsubseg->ss[5] = (subseg) NULL;
04722
04723 newsubseg->ss[6] = (subseg) m->dummytri;
04724 newsubseg->ss[7] = (subseg) m->dummytri;
04725
04726 setmark(*newsubseg, 0);
04727
04728 newsubseg->ssorient = 0;
04729 }
04730
04733
04734
04735
04739
04740
04741
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768 #define Fast_Two_Sum_Tail(a, b, x, y) \
04769 bvirt = x - a; \
04770 y = b - bvirt
04771
04772 #define Fast_Two_Sum(a, b, x, y) \
04773 x = (REAL) (a + b); \
04774 Fast_Two_Sum_Tail(a, b, x, y)
04775
04776 #define Two_Sum_Tail(a, b, x, y) \
04777 bvirt = (REAL) (x - a); \
04778 avirt = x - bvirt; \
04779 bround = b - bvirt; \
04780 around = a - avirt; \
04781 y = around + bround
04782
04783 #define Two_Sum(a, b, x, y) \
04784 x = (REAL) (a + b); \
04785 Two_Sum_Tail(a, b, x, y)
04786
04787 #define Two_Diff_Tail(a, b, x, y) \
04788 bvirt = (REAL) (a - x); \
04789 avirt = x + bvirt; \
04790 bround = bvirt - b; \
04791 around = a - avirt; \
04792 y = around + bround
04793
04794 #define Two_Diff(a, b, x, y) \
04795 x = (REAL) (a - b); \
04796 Two_Diff_Tail(a, b, x, y)
04797
04798 #define Split(a, ahi, alo) \
04799 c = (REAL) (splitter * a); \
04800 abig = (REAL) (c - a); \
04801 ahi = c - abig; \
04802 alo = a - ahi
04803
04804 #define Two_Product_Tail(a, b, x, y) \
04805 Split(a, ahi, alo); \
04806 Split(b, bhi, blo); \
04807 err1 = x - (ahi * bhi); \
04808 err2 = err1 - (alo * bhi); \
04809 err3 = err2 - (ahi * blo); \
04810 y = (alo * blo) - err3
04811
04812 #define Two_Product(a, b, x, y) \
04813 x = (REAL) (a * b); \
04814 Two_Product_Tail(a, b, x, y)
04815
04816
04817
04818
04819 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
04820 x = (REAL) (a * b); \
04821 Split(a, ahi, alo); \
04822 err1 = x - (ahi * bhi); \
04823 err2 = err1 - (alo * bhi); \
04824 err3 = err2 - (ahi * blo); \
04825 y = (alo * blo) - err3
04826
04827
04828
04829 #define Square_Tail(a, x, y) \
04830 Split(a, ahi, alo); \
04831 err1 = x - (ahi * ahi); \
04832 err3 = err1 - ((ahi + ahi) * alo); \
04833 y = (alo * alo) - err3
04834
04835 #define Square(a, x, y) \
04836 x = (REAL) (a * a); \
04837 Square_Tail(a, x, y)
04838
04839
04840
04841
04842 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
04843 Two_Sum(a0, b , _i, x0); \
04844 Two_Sum(a1, _i, x2, x1)
04845
04846 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
04847 Two_Diff(a0, b , _i, x0); \
04848 Two_Sum( a1, _i, x2, x1)
04849
04850 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
04851 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
04852 Two_One_Sum(_j, _0, b1, x3, x2, x1)
04853
04854 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
04855 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
04856 Two_One_Diff(_j, _0, b1, x3, x2, x1)
04857
04858
04859
04860 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
04861 Split(b, bhi, blo); \
04862 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
04863 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
04864 Two_Sum(_i, _0, _k, x1); \
04865 Fast_Two_Sum(_j, _k, x3, x2)
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886 void exactinit()
04887 {
04888 REAL half;
04889 REAL check, lastcheck;
04890 int every_other;
04891 #ifdef LINUX
04892 int cword;
04893 #endif
04894
04895 #ifdef CPU86
04896 #ifdef SINGLE
04897 _control87(_PC_24, _MCW_PC);
04898 #else
04899 _control87(_PC_53, _MCW_PC);
04900 #endif
04901 #endif
04902 #ifdef LINUX
04903 #ifdef SINGLE
04904
04905 cword = 4210;
04906 #else
04907
04908 cword = 4722;
04909 #endif
04910 _FPU_SETCW(cword);
04911 #endif
04912
04913 every_other = 1;
04914 half = 0.5;
04915 epsilon = 1.0;
04916 splitter = 1.0;
04917 check = 1.0;
04918
04919
04920
04921
04922 do {
04923 lastcheck = check;
04924 epsilon *= half;
04925 if (every_other) {
04926 splitter *= 2.0;
04927 }
04928 every_other = !every_other;
04929 check = 1.0 + epsilon;
04930 } while ((check != 1.0) && (check != lastcheck));
04931 splitter += 1.0;
04932
04933 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
04934 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
04935 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
04936 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
04937 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
04938 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
04939 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
04940 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
04941 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
04942 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
04943 }
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959 #ifdef ANSI_DECLARATORS
04960 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
04961 #else
04962 int fast_expansion_sum_zeroelim(elen, e, flen, f, h)
04963 int elen;
04964 REAL *e;
04965 int flen;
04966 REAL *f;
04967 REAL *h;
04968 #endif
04969
04970 {
04971 REAL Q;
04972 INEXACT REAL Qnew;
04973 INEXACT REAL hh;
04974 INEXACT REAL bvirt;
04975 REAL avirt, bround, around;
04976 int eindex, findex, hindex;
04977 REAL enow, fnow;
04978
04979 enow = e[0];
04980 fnow = f[0];
04981 eindex = findex = 0;
04982 if ((fnow > enow) == (fnow > -enow)) {
04983 Q = enow;
04984 enow = e[++eindex];
04985 } else {
04986 Q = fnow;
04987 fnow = f[++findex];
04988 }
04989 hindex = 0;
04990 if ((eindex < elen) && (findex < flen)) {
04991 if ((fnow > enow) == (fnow > -enow)) {
04992 Fast_Two_Sum(enow, Q, Qnew, hh);
04993 enow = e[++eindex];
04994 } else {
04995 Fast_Two_Sum(fnow, Q, Qnew, hh);
04996 fnow = f[++findex];
04997 }
04998 Q = Qnew;
04999 if (hh != 0.0) {
05000 h[hindex++] = hh;
05001 }
05002 while ((eindex < elen) && (findex < flen)) {
05003 if ((fnow > enow) == (fnow > -enow)) {
05004 Two_Sum(Q, enow, Qnew, hh);
05005 enow = e[++eindex];
05006 } else {
05007 Two_Sum(Q, fnow, Qnew, hh);
05008 fnow = f[++findex];
05009 }
05010 Q = Qnew;
05011 if (hh != 0.0) {
05012 h[hindex++] = hh;
05013 }
05014 }
05015 }
05016 while (eindex < elen) {
05017 Two_Sum(Q, enow, Qnew, hh);
05018 enow = e[++eindex];
05019 Q = Qnew;
05020 if (hh != 0.0) {
05021 h[hindex++] = hh;
05022 }
05023 }
05024 while (findex < flen) {
05025 Two_Sum(Q, fnow, Qnew, hh);
05026 fnow = f[++findex];
05027 Q = Qnew;
05028 if (hh != 0.0) {
05029 h[hindex++] = hh;
05030 }
05031 }
05032 if ((Q != 0.0) || (hindex == 0)) {
05033 h[hindex++] = Q;
05034 }
05035 return hindex;
05036 }
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053 #ifdef ANSI_DECLARATORS
05054 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
05055 #else
05056 int scale_expansion_zeroelim(elen, e, b, h)
05057 int elen;
05058 REAL *e;
05059 REAL b;
05060 REAL *h;
05061 #endif
05062
05063 {
05064 INEXACT REAL Q, sum;
05065 REAL hh;
05066 INEXACT REAL product1;
05067 REAL product0;
05068 int eindex, hindex;
05069 REAL enow;
05070 INEXACT REAL bvirt;
05071 REAL avirt, bround, around;
05072 INEXACT REAL c;
05073 INEXACT REAL abig;
05074 REAL ahi, alo, bhi, blo;
05075 REAL err1, err2, err3;
05076
05077 Split(b, bhi, blo);
05078 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
05079 hindex = 0;
05080 if (hh != 0) {
05081 h[hindex++] = hh;
05082 }
05083 for (eindex = 1; eindex < elen; eindex++) {
05084 enow = e[eindex];
05085 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
05086 Two_Sum(Q, product0, sum, hh);
05087 if (hh != 0) {
05088 h[hindex++] = hh;
05089 }
05090 Fast_Two_Sum(product1, sum, Q, hh);
05091 if (hh != 0) {
05092 h[hindex++] = hh;
05093 }
05094 }
05095 if ((Q != 0.0) || (hindex == 0)) {
05096 h[hindex++] = Q;
05097 }
05098 return hindex;
05099 }
05100
05101
05102
05103
05104
05105
05106
05107
05108
05109 #ifdef ANSI_DECLARATORS
05110 REAL estimate(int elen, REAL *e)
05111 #else
05112 REAL estimate(elen, e)
05113 int elen;
05114 REAL *e;
05115 #endif
05116
05117 {
05118 REAL Q;
05119 int eindex;
05120
05121 Q = e[0];
05122 for (eindex = 1; eindex < elen; eindex++) {
05123 Q += e[eindex];
05124 }
05125 return Q;
05126 }
05127
05128
05129
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148 #ifdef ANSI_DECLARATORS
05149 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
05150 #else
05151 REAL counterclockwiseadapt(pa, pb, pc, detsum)
05152 vertex pa;
05153 vertex pb;
05154 vertex pc;
05155 REAL detsum;
05156 #endif
05157
05158 {
05159 INEXACT REAL acx, acy, bcx, bcy;
05160 REAL acxtail, acytail, bcxtail, bcytail;
05161 INEXACT REAL detleft, detright;
05162 REAL detlefttail, detrighttail;
05163 REAL det, errbound;
05164 REAL B[4], C1[8], C2[12], D[16];
05165 INEXACT REAL B3;
05166 int C1length, C2length, Dlength;
05167 REAL u[4];
05168 INEXACT REAL u3;
05169 INEXACT REAL s1, t1;
05170 REAL s0, t0;
05171
05172 INEXACT REAL bvirt;
05173 REAL avirt, bround, around;
05174 INEXACT REAL c;
05175 INEXACT REAL abig;
05176 REAL ahi, alo, bhi, blo;
05177 REAL err1, err2, err3;
05178 INEXACT REAL _i, _j;
05179 REAL _0;
05180
05181 acx = (REAL) (pa[0] - pc[0]);
05182 bcx = (REAL) (pb[0] - pc[0]);
05183 acy = (REAL) (pa[1] - pc[1]);
05184 bcy = (REAL) (pb[1] - pc[1]);
05185
05186 Two_Product(acx, bcy, detleft, detlefttail);
05187 Two_Product(acy, bcx, detright, detrighttail);
05188
05189 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
05190 B3, B[2], B[1], B[0]);
05191 B[3] = B3;
05192
05193 det = estimate(4, B);
05194 errbound = ccwerrboundB * detsum;
05195 if ((det >= errbound) || (-det >= errbound)) {
05196 return det;
05197 }
05198
05199 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
05200 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
05201 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
05202 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
05203
05204 if ((acxtail == 0.0) && (acytail == 0.0)
05205 && (bcxtail == 0.0) && (bcytail == 0.0)) {
05206 return det;
05207 }
05208
05209 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
05210 det += (acx * bcytail + bcy * acxtail)
05211 - (acy * bcxtail + bcx * acytail);
05212 if ((det >= errbound) || (-det >= errbound)) {
05213 return det;
05214 }
05215
05216 Two_Product(acxtail, bcy, s1, s0);
05217 Two_Product(acytail, bcx, t1, t0);
05218 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05219 u[3] = u3;
05220 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
05221
05222 Two_Product(acx, bcytail, s1, s0);
05223 Two_Product(acy, bcxtail, t1, t0);
05224 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05225 u[3] = u3;
05226 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
05227
05228 Two_Product(acxtail, bcytail, s1, s0);
05229 Two_Product(acytail, bcxtail, t1, t0);
05230 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05231 u[3] = u3;
05232 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
05233
05234 return(D[Dlength - 1]);
05235 }
05236
05237 #ifdef ANSI_DECLARATORS
05238 REAL counterclockwise(struct mesh *m, struct behavior *b,
05239 vertex pa, vertex pb, vertex pc)
05240 #else
05241 REAL counterclockwise(m, b, pa, pb, pc)
05242 struct mesh *m;
05243 struct behavior *b;
05244 vertex pa;
05245 vertex pb;
05246 vertex pc;
05247 #endif
05248
05249 {
05250 REAL detleft, detright, det;
05251 REAL detsum, errbound;
05252
05253 m->counterclockcount++;
05254
05255 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
05256 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
05257 det = detleft - detright;
05258
05259 if (b->noexact) {
05260 return det;
05261 }
05262
05263 if (detleft > 0.0) {
05264 if (detright <= 0.0) {
05265 return det;
05266 } else {
05267 detsum = detleft + detright;
05268 }
05269 } else if (detleft < 0.0) {
05270 if (detright >= 0.0) {
05271 return det;
05272 } else {
05273 detsum = -detleft - detright;
05274 }
05275 } else {
05276 return det;
05277 }
05278
05279 errbound = ccwerrboundA * detsum;
05280 if ((det >= errbound) || (-det >= errbound)) {
05281 return det;
05282 }
05283
05284 return counterclockwiseadapt(pa, pb, pc, detsum);
05285 }
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306 #ifdef ANSI_DECLARATORS
05307 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
05308 #else
05309 REAL incircleadapt(pa, pb, pc, pd, permanent)
05310 vertex pa;
05311 vertex pb;
05312 vertex pc;
05313 vertex pd;
05314 REAL permanent;
05315 #endif
05316
05317 {
05318 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
05319 REAL det, errbound;
05320
05321 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05322 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05323 REAL bc[4], ca[4], ab[4];
05324 INEXACT REAL bc3, ca3, ab3;
05325 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
05326 int axbclen, axxbclen, aybclen, ayybclen, alen;
05327 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
05328 int bxcalen, bxxcalen, bycalen, byycalen, blen;
05329 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
05330 int cxablen, cxxablen, cyablen, cyyablen, clen;
05331 REAL abdet[64];
05332 int ablen;
05333 REAL fin1[1152], fin2[1152];
05334 REAL *finnow, *finother, *finswap;
05335 int finlength;
05336
05337 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
05338 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
05339 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
05340 REAL aa[4], bb[4], cc[4];
05341 INEXACT REAL aa3, bb3, cc3;
05342 INEXACT REAL ti1, tj1;
05343 REAL ti0, tj0;
05344 REAL u[4], v[4];
05345 INEXACT REAL u3, v3;
05346 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
05347 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
05348 int temp8len, temp16alen, temp16blen, temp16clen;
05349 int temp32alen, temp32blen, temp48len, temp64len;
05350 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
05351 int axtbblen, axtcclen, aytbblen, aytcclen;
05352 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
05353 int bxtaalen, bxtcclen, bytaalen, bytcclen;
05354 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
05355 int cxtaalen, cxtbblen, cytaalen, cytbblen;
05356 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
05357 int axtbclen=0, aytbclen=0, bxtcalen=0, bytcalen=0, cxtablen=0, cytablen=0;
05358 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
05359 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
05360 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
05361 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
05362 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
05363 REAL abt[8], bct[8], cat[8];
05364 int abtlen, bctlen, catlen;
05365 REAL abtt[4], bctt[4], catt[4];
05366 int abttlen, bcttlen, cattlen;
05367 INEXACT REAL abtt3, bctt3, catt3;
05368 REAL negate;
05369
05370 INEXACT REAL bvirt;
05371 REAL avirt, bround, around;
05372 INEXACT REAL c;
05373 INEXACT REAL abig;
05374 REAL ahi, alo, bhi, blo;
05375 REAL err1, err2, err3;
05376 INEXACT REAL _i, _j;
05377 REAL _0;
05378
05379 adx = (REAL) (pa[0] - pd[0]);
05380 bdx = (REAL) (pb[0] - pd[0]);
05381 cdx = (REAL) (pc[0] - pd[0]);
05382 ady = (REAL) (pa[1] - pd[1]);
05383 bdy = (REAL) (pb[1] - pd[1]);
05384 cdy = (REAL) (pc[1] - pd[1]);
05385
05386 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
05387 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
05388 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
05389 bc[3] = bc3;
05390 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
05391 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
05392 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
05393 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
05394 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
05395
05396 Two_Product(cdx, ady, cdxady1, cdxady0);
05397 Two_Product(adx, cdy, adxcdy1, adxcdy0);
05398 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
05399 ca[3] = ca3;
05400 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
05401 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
05402 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
05403 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
05404 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
05405
05406 Two_Product(adx, bdy, adxbdy1, adxbdy0);
05407 Two_Product(bdx, ady, bdxady1, bdxady0);
05408 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
05409 ab[3] = ab3;
05410 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
05411 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
05412 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
05413 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
05414 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
05415
05416 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
05417 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
05418
05419 det = estimate(finlength, fin1);
05420 errbound = iccerrboundB * permanent;
05421 if ((det >= errbound) || (-det >= errbound)) {
05422 return det;
05423 }
05424
05425 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
05426 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
05427 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
05428 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
05429 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
05430 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
05431 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
05432 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
05433 return det;
05434 }
05435
05436 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
05437 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
05438 - (bdy * cdxtail + cdx * bdytail))
05439 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
05440 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
05441 - (cdy * adxtail + adx * cdytail))
05442 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
05443 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
05444 - (ady * bdxtail + bdx * adytail))
05445 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
05446 if ((det >= errbound) || (-det >= errbound)) {
05447 return det;
05448 }
05449
05450 finnow = fin1;
05451 finother = fin2;
05452
05453 if ((bdxtail != 0.0) || (bdytail != 0.0)
05454 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05455 Square(adx, adxadx1, adxadx0);
05456 Square(ady, adyady1, adyady0);
05457 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
05458 aa[3] = aa3;
05459 }
05460 if ((cdxtail != 0.0) || (cdytail != 0.0)
05461 || (adxtail != 0.0) || (adytail != 0.0)) {
05462 Square(bdx, bdxbdx1, bdxbdx0);
05463 Square(bdy, bdybdy1, bdybdy0);
05464 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
05465 bb[3] = bb3;
05466 }
05467 if ((adxtail != 0.0) || (adytail != 0.0)
05468 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05469 Square(cdx, cdxcdx1, cdxcdx0);
05470 Square(cdy, cdycdy1, cdycdy0);
05471 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
05472 cc[3] = cc3;
05473 }
05474
05475 if (adxtail != 0.0) {
05476 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
05477 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
05478 temp16a);
05479
05480 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
05481 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
05482
05483 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
05484 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
05485
05486 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05487 temp16blen, temp16b, temp32a);
05488 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05489 temp32alen, temp32a, temp48);
05490 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05491 temp48, finother);
05492 finswap = finnow; finnow = finother; finother = finswap;
05493 }
05494 if (adytail != 0.0) {
05495 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
05496 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
05497 temp16a);
05498
05499 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
05500 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
05501
05502 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
05503 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
05504
05505 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05506 temp16blen, temp16b, temp32a);
05507 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05508 temp32alen, temp32a, temp48);
05509 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05510 temp48, finother);
05511 finswap = finnow; finnow = finother; finother = finswap;
05512 }
05513 if (bdxtail != 0.0) {
05514 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
05515 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
05516 temp16a);
05517
05518 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
05519 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
05520
05521 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
05522 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
05523
05524 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05525 temp16blen, temp16b, temp32a);
05526 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05527 temp32alen, temp32a, temp48);
05528 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05529 temp48, finother);
05530 finswap = finnow; finnow = finother; finother = finswap;
05531 }
05532 if (bdytail != 0.0) {
05533 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
05534 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
05535 temp16a);
05536
05537 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
05538 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
05539
05540 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
05541 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
05542
05543 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05544 temp16blen, temp16b, temp32a);
05545 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05546 temp32alen, temp32a, temp48);
05547 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05548 temp48, finother);
05549 finswap = finnow; finnow = finother; finother = finswap;
05550 }
05551 if (cdxtail != 0.0) {
05552 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
05553 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
05554 temp16a);
05555
05556 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
05557 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
05558
05559 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
05560 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
05561
05562 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05563 temp16blen, temp16b, temp32a);
05564 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05565 temp32alen, temp32a, temp48);
05566 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05567 temp48, finother);
05568 finswap = finnow; finnow = finother; finother = finswap;
05569 }
05570 if (cdytail != 0.0) {
05571 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
05572 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
05573 temp16a);
05574
05575 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
05576 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
05577
05578 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
05579 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
05580
05581 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05582 temp16blen, temp16b, temp32a);
05583 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05584 temp32alen, temp32a, temp48);
05585 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05586 temp48, finother);
05587 finswap = finnow; finnow = finother; finother = finswap;
05588 }
05589
05590 if ((adxtail != 0.0) || (adytail != 0.0)) {
05591 if ((bdxtail != 0.0) || (bdytail != 0.0)
05592 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05593 Two_Product(bdxtail, cdy, ti1, ti0);
05594 Two_Product(bdx, cdytail, tj1, tj0);
05595 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05596 u[3] = u3;
05597 negate = -bdy;
05598 Two_Product(cdxtail, negate, ti1, ti0);
05599 negate = -bdytail;
05600 Two_Product(cdx, negate, tj1, tj0);
05601 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05602 v[3] = v3;
05603 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
05604
05605 Two_Product(bdxtail, cdytail, ti1, ti0);
05606 Two_Product(cdxtail, bdytail, tj1, tj0);
05607 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
05608 bctt[3] = bctt3;
05609 bcttlen = 4;
05610 } else {
05611 bct[0] = 0.0;
05612 bctlen = 1;
05613 bctt[0] = 0.0;
05614 bcttlen = 1;
05615 }
05616
05617 if (adxtail != 0.0) {
05618 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
05619 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
05620 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
05621 temp32a);
05622 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05623 temp32alen, temp32a, temp48);
05624 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05625 temp48, finother);
05626 finswap = finnow; finnow = finother; finother = finswap;
05627 if (bdytail != 0.0) {
05628 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
05629 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05630 temp16a);
05631 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05632 temp16a, finother);
05633 finswap = finnow; finnow = finother; finother = finswap;
05634 }
05635 if (cdytail != 0.0) {
05636 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
05637 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05638 temp16a);
05639 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05640 temp16a, finother);
05641 finswap = finnow; finnow = finother; finother = finswap;
05642 }
05643
05644 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
05645 temp32a);
05646 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
05647 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
05648 temp16a);
05649 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
05650 temp16b);
05651 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05652 temp16blen, temp16b, temp32b);
05653 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05654 temp32blen, temp32b, temp64);
05655 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05656 temp64, finother);
05657 finswap = finnow; finnow = finother; finother = finswap;
05658 }
05659 if (adytail != 0.0) {
05660 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
05661 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
05662 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
05663 temp32a);
05664 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05665 temp32alen, temp32a, temp48);
05666 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05667 temp48, finother);
05668 finswap = finnow; finnow = finother; finother = finswap;
05669
05670
05671 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
05672 temp32a);
05673 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
05674 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
05675 temp16a);
05676 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
05677 temp16b);
05678 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05679 temp16blen, temp16b, temp32b);
05680 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05681 temp32blen, temp32b, temp64);
05682 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05683 temp64, finother);
05684 finswap = finnow; finnow = finother; finother = finswap;
05685 }
05686 }
05687 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
05688 if ((cdxtail != 0.0) || (cdytail != 0.0)
05689 || (adxtail != 0.0) || (adytail != 0.0)) {
05690 Two_Product(cdxtail, ady, ti1, ti0);
05691 Two_Product(cdx, adytail, tj1, tj0);
05692 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05693 u[3] = u3;
05694 negate = -cdy;
05695 Two_Product(adxtail, negate, ti1, ti0);
05696 negate = -cdytail;
05697 Two_Product(adx, negate, tj1, tj0);
05698 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05699 v[3] = v3;
05700 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
05701
05702 Two_Product(cdxtail, adytail, ti1, ti0);
05703 Two_Product(adxtail, cdytail, tj1, tj0);
05704 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
05705 catt[3] = catt3;
05706 cattlen = 4;
05707 } else {
05708 cat[0] = 0.0;
05709 catlen = 1;
05710 catt[0] = 0.0;
05711 cattlen = 1;
05712 }
05713
05714 if (bdxtail != 0.0) {
05715 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
05716 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
05717 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
05718 temp32a);
05719 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05720 temp32alen, temp32a, temp48);
05721 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05722 temp48, finother);
05723 finswap = finnow; finnow = finother; finother = finswap;
05724 if (cdytail != 0.0) {
05725 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
05726 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05727 temp16a);
05728 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05729 temp16a, finother);
05730 finswap = finnow; finnow = finother; finother = finswap;
05731 }
05732 if (adytail != 0.0) {
05733 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
05734 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05735 temp16a);
05736 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05737 temp16a, finother);
05738 finswap = finnow; finnow = finother; finother = finswap;
05739 }
05740
05741 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
05742 temp32a);
05743 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
05744 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
05745 temp16a);
05746 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
05747 temp16b);
05748 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05749 temp16blen, temp16b, temp32b);
05750 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05751 temp32blen, temp32b, temp64);
05752 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05753 temp64, finother);
05754 finswap = finnow; finnow = finother; finother = finswap;
05755 }
05756 if (bdytail != 0.0) {
05757 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
05758 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
05759 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
05760 temp32a);
05761 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05762 temp32alen, temp32a, temp48);
05763 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05764 temp48, finother);
05765 finswap = finnow; finnow = finother; finother = finswap;
05766
05767
05768 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
05769 temp32a);
05770 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
05771 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
05772 temp16a);
05773 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
05774 temp16b);
05775 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05776 temp16blen, temp16b, temp32b);
05777 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05778 temp32blen, temp32b, temp64);
05779 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05780 temp64, finother);
05781 finswap = finnow; finnow = finother; finother = finswap;
05782 }
05783 }
05784 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
05785 if ((adxtail != 0.0) || (adytail != 0.0)
05786 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05787 Two_Product(adxtail, bdy, ti1, ti0);
05788 Two_Product(adx, bdytail, tj1, tj0);
05789 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05790 u[3] = u3;
05791 negate = -ady;
05792 Two_Product(bdxtail, negate, ti1, ti0);
05793 negate = -adytail;
05794 Two_Product(bdx, negate, tj1, tj0);
05795 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05796 v[3] = v3;
05797 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
05798
05799 Two_Product(adxtail, bdytail, ti1, ti0);
05800 Two_Product(bdxtail, adytail, tj1, tj0);
05801 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
05802 abtt[3] = abtt3;
05803 abttlen = 4;
05804 } else {
05805 abt[0] = 0.0;
05806 abtlen = 1;
05807 abtt[0] = 0.0;
05808 abttlen = 1;
05809 }
05810
05811 if (cdxtail != 0.0) {
05812 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
05813 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
05814 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
05815 temp32a);
05816 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05817 temp32alen, temp32a, temp48);
05818 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05819 temp48, finother);
05820 finswap = finnow; finnow = finother; finother = finswap;
05821 if (adytail != 0.0) {
05822 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
05823 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05824 temp16a);
05825 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05826 temp16a, finother);
05827 finswap = finnow; finnow = finother; finother = finswap;
05828 }
05829 if (bdytail != 0.0) {
05830 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
05831 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05832 temp16a);
05833 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05834 temp16a, finother);
05835 finswap = finnow; finnow = finother; finother = finswap;
05836 }
05837
05838 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
05839 temp32a);
05840 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
05841 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
05842 temp16a);
05843 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
05844 temp16b);
05845 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05846 temp16blen, temp16b, temp32b);
05847 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05848 temp32blen, temp32b, temp64);
05849 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05850 temp64, finother);
05851 finswap = finnow; finnow = finother; finother = finswap;
05852 }
05853 if (cdytail != 0.0) {
05854 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
05855 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
05856 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
05857 temp32a);
05858 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05859 temp32alen, temp32a, temp48);
05860 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05861 temp48, finother);
05862 finswap = finnow; finnow = finother; finother = finswap;
05863
05864
05865 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
05866 temp32a);
05867 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
05868 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
05869 temp16a);
05870 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
05871 temp16b);
05872 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05873 temp16blen, temp16b, temp32b);
05874 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05875 temp32blen, temp32b, temp64);
05876 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05877 temp64, finother);
05878 finswap = finnow; finnow = finother; finother = finswap;
05879 }
05880 }
05881
05882 return finnow[finlength - 1];
05883 }
05884
05885 #ifdef ANSI_DECLARATORS
05886 REAL incircle(struct mesh *m, struct behavior *b,
05887 vertex pa, vertex pb, vertex pc, vertex pd)
05888 #else
05889 REAL incircle(m, b, pa, pb, pc, pd)
05890 struct mesh *m;
05891 struct behavior *b;
05892 vertex pa;
05893 vertex pb;
05894 vertex pc;
05895 vertex pd;
05896 #endif
05897
05898 {
05899 REAL adx, bdx, cdx, ady, bdy, cdy;
05900 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
05901 REAL alift, blift, clift;
05902 REAL det;
05903 REAL permanent, errbound;
05904
05905 m->incirclecount++;
05906
05907 adx = pa[0] - pd[0];
05908 bdx = pb[0] - pd[0];
05909 cdx = pc[0] - pd[0];
05910 ady = pa[1] - pd[1];
05911 bdy = pb[1] - pd[1];
05912 cdy = pc[1] - pd[1];
05913
05914 bdxcdy = bdx * cdy;
05915 cdxbdy = cdx * bdy;
05916 alift = adx * adx + ady * ady;
05917
05918 cdxady = cdx * ady;
05919 adxcdy = adx * cdy;
05920 blift = bdx * bdx + bdy * bdy;
05921
05922 adxbdy = adx * bdy;
05923 bdxady = bdx * ady;
05924 clift = cdx * cdx + cdy * cdy;
05925
05926 det = alift * (bdxcdy - cdxbdy)
05927 + blift * (cdxady - adxcdy)
05928 + clift * (adxbdy - bdxady);
05929
05930 if (b->noexact) {
05931 return det;
05932 }
05933
05934 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
05935 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
05936 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
05937 errbound = iccerrboundA * permanent;
05938 if ((det > errbound) || (-det > errbound)) {
05939 return det;
05940 }
05941
05942 return incircleadapt(pa, pb, pc, pd, permanent);
05943 }
05944
05945
05946
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967 #ifdef ANSI_DECLARATORS
05968 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
05969 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
05970 REAL permanent)
05971 #else
05972 REAL orient3dadapt(pa, pb, pc, pd,
05973 aheight, bheight, cheight, dheight, permanent)
05974 vertex pa;
05975 vertex pb;
05976 vertex pc;
05977 vertex pd;
05978 REAL aheight;
05979 REAL bheight;
05980 REAL cheight;
05981 REAL dheight;
05982 REAL permanent;
05983 #endif
05984
05985 {
05986 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
05987 REAL det, errbound;
05988
05989 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05990 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05991 REAL bc[4], ca[4], ab[4];
05992 INEXACT REAL bc3, ca3, ab3;
05993 REAL adet[8], bdet[8], cdet[8];
05994 int alen, blen, clen;
05995 REAL abdet[16];
05996 int ablen;
05997 REAL *finnow, *finother, *finswap;
05998 REAL fin1[192], fin2[192];
05999 int finlength;
06000
06001 REAL adxtail, bdxtail, cdxtail;
06002 REAL adytail, bdytail, cdytail;
06003 REAL adheighttail, bdheighttail, cdheighttail;
06004 INEXACT REAL at_blarge, at_clarge;
06005 INEXACT REAL bt_clarge, bt_alarge;
06006 INEXACT REAL ct_alarge, ct_blarge;
06007 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
06008 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
06009 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
06010 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
06011 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
06012 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
06013 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
06014 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
06015 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
06016 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
06017 REAL bct[8], cat[8], abt[8];
06018 int bctlen, catlen, abtlen;
06019 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
06020 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
06021 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
06022 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
06023 REAL u[4], v[12], w[16];
06024 INEXACT REAL u3;
06025 int vlength, wlength;
06026 REAL negate;
06027
06028 INEXACT REAL bvirt;
06029 REAL avirt, bround, around;
06030 INEXACT REAL c;
06031 INEXACT REAL abig;
06032 REAL ahi, alo, bhi, blo;
06033 REAL err1, err2, err3;
06034 INEXACT REAL _i, _j, _k;
06035 REAL _0;
06036
06037 adx = (REAL) (pa[0] - pd[0]);
06038 bdx = (REAL) (pb[0] - pd[0]);
06039 cdx = (REAL) (pc[0] - pd[0]);
06040 ady = (REAL) (pa[1] - pd[1]);
06041 bdy = (REAL) (pb[1] - pd[1]);
06042 cdy = (REAL) (pc[1] - pd[1]);
06043 adheight = (REAL) (aheight - dheight);
06044 bdheight = (REAL) (bheight - dheight);
06045 cdheight = (REAL) (cheight - dheight);
06046
06047 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
06048 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
06049 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
06050 bc[3] = bc3;
06051 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
06052
06053 Two_Product(cdx, ady, cdxady1, cdxady0);
06054 Two_Product(adx, cdy, adxcdy1, adxcdy0);
06055 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
06056 ca[3] = ca3;
06057 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
06058
06059 Two_Product(adx, bdy, adxbdy1, adxbdy0);
06060 Two_Product(bdx, ady, bdxady1, bdxady0);
06061 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
06062 ab[3] = ab3;
06063 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
06064
06065 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
06066 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
06067
06068 det = estimate(finlength, fin1);
06069 errbound = o3derrboundB * permanent;
06070 if ((det >= errbound) || (-det >= errbound)) {
06071 return det;
06072 }
06073
06074 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
06075 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
06076 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
06077 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
06078 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
06079 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
06080 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
06081 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
06082 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
06083
06084 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
06085 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
06086 (adheighttail == 0.0) &&
06087 (bdheighttail == 0.0) &&
06088 (cdheighttail == 0.0)) {
06089 return det;
06090 }
06091
06092 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
06093 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
06094 (bdy * cdxtail + cdx * bdytail)) +
06095 adheighttail * (bdx * cdy - bdy * cdx)) +
06096 (bdheight * ((cdx * adytail + ady * cdxtail) -
06097 (cdy * adxtail + adx * cdytail)) +
06098 bdheighttail * (cdx * ady - cdy * adx)) +
06099 (cdheight * ((adx * bdytail + bdy * adxtail) -
06100 (ady * bdxtail + bdx * adytail)) +
06101 cdheighttail * (adx * bdy - ady * bdx));
06102 if ((det >= errbound) || (-det >= errbound)) {
06103 return det;
06104 }
06105
06106 finnow = fin1;
06107 finother = fin2;
06108
06109 if (adxtail == 0.0) {
06110 if (adytail == 0.0) {
06111 at_b[0] = 0.0;
06112 at_blen = 1;
06113 at_c[0] = 0.0;
06114 at_clen = 1;
06115 } else {
06116 negate = -adytail;
06117 Two_Product(negate, bdx, at_blarge, at_b[0]);
06118 at_b[1] = at_blarge;
06119 at_blen = 2;
06120 Two_Product(adytail, cdx, at_clarge, at_c[0]);
06121 at_c[1] = at_clarge;
06122 at_clen = 2;
06123 }
06124 } else {
06125 if (adytail == 0.0) {
06126 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
06127 at_b[1] = at_blarge;
06128 at_blen = 2;
06129 negate = -adxtail;
06130 Two_Product(negate, cdy, at_clarge, at_c[0]);
06131 at_c[1] = at_clarge;
06132 at_clen = 2;
06133 } else {
06134 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
06135 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
06136 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
06137 at_blarge, at_b[2], at_b[1], at_b[0]);
06138 at_b[3] = at_blarge;
06139 at_blen = 4;
06140 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
06141 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
06142 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
06143 at_clarge, at_c[2], at_c[1], at_c[0]);
06144 at_c[3] = at_clarge;
06145 at_clen = 4;
06146 }
06147 }
06148 if (bdxtail == 0.0) {
06149 if (bdytail == 0.0) {
06150 bt_c[0] = 0.0;
06151 bt_clen = 1;
06152 bt_a[0] = 0.0;
06153 bt_alen = 1;
06154 } else {
06155 negate = -bdytail;
06156 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
06157 bt_c[1] = bt_clarge;
06158 bt_clen = 2;
06159 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
06160 bt_a[1] = bt_alarge;
06161 bt_alen = 2;
06162 }
06163 } else {
06164 if (bdytail == 0.0) {
06165 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
06166 bt_c[1] = bt_clarge;
06167 bt_clen = 2;
06168 negate = -bdxtail;
06169 Two_Product(negate, ady, bt_alarge, bt_a[0]);
06170 bt_a[1] = bt_alarge;
06171 bt_alen = 2;
06172 } else {
06173 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
06174 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
06175 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
06176 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
06177 bt_c[3] = bt_clarge;
06178 bt_clen = 4;
06179 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
06180 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
06181 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
06182 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
06183 bt_a[3] = bt_alarge;
06184 bt_alen = 4;
06185 }
06186 }
06187 if (cdxtail == 0.0) {
06188 if (cdytail == 0.0) {
06189 ct_a[0] = 0.0;
06190 ct_alen = 1;
06191 ct_b[0] = 0.0;
06192 ct_blen = 1;
06193 } else {
06194 negate = -cdytail;
06195 Two_Product(negate, adx, ct_alarge, ct_a[0]);
06196 ct_a[1] = ct_alarge;
06197 ct_alen = 2;
06198 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
06199 ct_b[1] = ct_blarge;
06200 ct_blen = 2;
06201 }
06202 } else {
06203 if (cdytail == 0.0) {
06204 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
06205 ct_a[1] = ct_alarge;
06206 ct_alen = 2;
06207 negate = -cdxtail;
06208 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
06209 ct_b[1] = ct_blarge;
06210 ct_blen = 2;
06211 } else {
06212 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
06213 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
06214 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
06215 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
06216 ct_a[3] = ct_alarge;
06217 ct_alen = 4;
06218 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
06219 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
06220 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
06221 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
06222 ct_b[3] = ct_blarge;
06223 ct_blen = 4;
06224 }
06225 }
06226
06227 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
06228 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
06229 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06230 finother);
06231 finswap = finnow; finnow = finother; finother = finswap;
06232
06233 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
06234 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
06235 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06236 finother);
06237 finswap = finnow; finnow = finother; finother = finswap;
06238
06239 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
06240 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
06241 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06242 finother);
06243 finswap = finnow; finnow = finother; finother = finswap;
06244
06245 if (adheighttail != 0.0) {
06246 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
06247 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06248 finother);
06249 finswap = finnow; finnow = finother; finother = finswap;
06250 }
06251 if (bdheighttail != 0.0) {
06252 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
06253 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06254 finother);
06255 finswap = finnow; finnow = finother; finother = finswap;
06256 }
06257 if (cdheighttail != 0.0) {
06258 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
06259 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06260 finother);
06261 finswap = finnow; finnow = finother; finother = finswap;
06262 }
06263
06264 if (adxtail != 0.0) {
06265 if (bdytail != 0.0) {
06266 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
06267 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
06268 u[3] = u3;
06269 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06270 finother);
06271 finswap = finnow; finnow = finother; finother = finswap;
06272 if (cdheighttail != 0.0) {
06273 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
06274 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 }
06280 }
06281 if (cdytail != 0.0) {
06282 negate = -adxtail;
06283 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
06284 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
06285 u[3] = u3;
06286 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06287 finother);
06288 finswap = finnow; finnow = finother; finother = finswap;
06289 if (bdheighttail != 0.0) {
06290 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
06291 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 }
06297 }
06298 }
06299 if (bdxtail != 0.0) {
06300 if (cdytail != 0.0) {
06301 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
06302 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
06303 u[3] = u3;
06304 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06305 finother);
06306 finswap = finnow; finnow = finother; finother = finswap;
06307 if (adheighttail != 0.0) {
06308 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
06309 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 }
06315 }
06316 if (adytail != 0.0) {
06317 negate = -bdxtail;
06318 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
06319 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
06320 u[3] = u3;
06321 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06322 finother);
06323 finswap = finnow; finnow = finother; finother = finswap;
06324 if (cdheighttail != 0.0) {
06325 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
06326 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 }
06332 }
06333 }
06334 if (cdxtail != 0.0) {
06335 if (adytail != 0.0) {
06336 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
06337 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
06338 u[3] = u3;
06339 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06340 finother);
06341 finswap = finnow; finnow = finother; finother = finswap;
06342 if (bdheighttail != 0.0) {
06343 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
06344 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 }
06350 }
06351 if (bdytail != 0.0) {
06352 negate = -cdxtail;
06353 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
06354 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
06355 u[3] = u3;
06356 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06357 finother);
06358 finswap = finnow; finnow = finother; finother = finswap;
06359 if (adheighttail != 0.0) {
06360 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
06361 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 }
06367 }
06368 }
06369
06370 if (adheighttail != 0.0) {
06371 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
06372 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06373 finother);
06374 finswap = finnow; finnow = finother; finother = finswap;
06375 }
06376 if (bdheighttail != 0.0) {
06377 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
06378 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06379 finother);
06380 finswap = finnow; finnow = finother; finother = finswap;
06381 }
06382 if (cdheighttail != 0.0) {
06383 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
06384 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06385 finother);
06386 finswap = finnow; finnow = finother; finother = finswap;
06387 }
06388
06389 return finnow[finlength - 1];
06390 }
06391
06392 #ifdef ANSI_DECLARATORS
06393 REAL orient3d(struct mesh *m, struct behavior *b,
06394 vertex pa, vertex pb, vertex pc, vertex pd,
06395 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
06396 #else
06397 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
06398 struct mesh *m;
06399 struct behavior *b;
06400 vertex pa;
06401 vertex pb;
06402 vertex pc;
06403 vertex pd;
06404 REAL aheight;
06405 REAL bheight;
06406 REAL cheight;
06407 REAL dheight;
06408 #endif
06409
06410 {
06411 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06412 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
06413 REAL det;
06414 REAL permanent, errbound;
06415
06416 m->orient3dcount++;
06417
06418 adx = pa[0] - pd[0];
06419 bdx = pb[0] - pd[0];
06420 cdx = pc[0] - pd[0];
06421 ady = pa[1] - pd[1];
06422 bdy = pb[1] - pd[1];
06423 cdy = pc[1] - pd[1];
06424 adheight = aheight - dheight;
06425 bdheight = bheight - dheight;
06426 cdheight = cheight - dheight;
06427
06428 bdxcdy = bdx * cdy;
06429 cdxbdy = cdx * bdy;
06430
06431 cdxady = cdx * ady;
06432 adxcdy = adx * cdy;
06433
06434 adxbdy = adx * bdy;
06435 bdxady = bdx * ady;
06436
06437 det = adheight * (bdxcdy - cdxbdy)
06438 + bdheight * (cdxady - adxcdy)
06439 + cdheight * (adxbdy - bdxady);
06440
06441 if (b->noexact) {
06442 return det;
06443 }
06444
06445 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
06446 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
06447 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
06448 errbound = o3derrboundA * permanent;
06449 if ((det > errbound) || (-det > errbound)) {
06450 return det;
06451 }
06452
06453 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
06454 permanent);
06455 }
06456
06457
06458
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475 #ifdef ANSI_DECLARATORS
06476 REAL nonregular(struct mesh *m, struct behavior *b,
06477 vertex pa, vertex pb, vertex pc, vertex pd)
06478 #else
06479 REAL nonregular(m, b, pa, pb, pc, pd)
06480 struct mesh *m;
06481 struct behavior *b;
06482 vertex pa;
06483 vertex pb;
06484 vertex pc;
06485 vertex pd;
06486 #endif
06487
06488 {
06489 if (b->weighted == 0) {
06490 return incircle(m, b, pa, pb, pc, pd);
06491 } else if (b->weighted == 1) {
06492 return orient3d(m, b, pa, pb, pc, pd,
06493 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
06494 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
06495 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
06496 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
06497 } else {
06498 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
06499 }
06500 }
06501
06502
06503
06504
06505
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516 #ifdef ANSI_DECLARATORS
06517 void findcircumcenter(struct mesh *m, struct behavior *b,
06518 vertex torg, vertex tdest, vertex tapex,
06519 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
06520 #else
06521 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
06522 offcenter)
06523 struct mesh *m;
06524 struct behavior *b;
06525 vertex torg;
06526 vertex tdest;
06527 vertex tapex;
06528 vertex circumcenter;
06529 REAL *xi;
06530 REAL *eta;
06531 int offcenter;
06532 #endif
06533
06534 {
06535 REAL xdo, ydo, xao, yao;
06536 REAL dodist, aodist, dadist;
06537 REAL denominator;
06538 REAL dx, dy, dxoff, dyoff;
06539
06540 m->circumcentercount++;
06541
06542
06543 xdo = tdest[0] - torg[0];
06544 ydo = tdest[1] - torg[1];
06545 xao = tapex[0] - torg[0];
06546 yao = tapex[1] - torg[1];
06547 dodist = xdo * xdo + ydo * ydo;
06548 aodist = xao * xao + yao * yao;
06549 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
06550 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
06551 if (b->noexact) {
06552 denominator = 0.5 / (xdo * yao - xao * ydo);
06553 } else {
06554
06555
06556
06557 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
06558
06559 m->counterclockcount--;
06560 }
06561 dx = (yao * dodist - ydo * aodist) * denominator;
06562 dy = (xdo * aodist - xao * dodist) * denominator;
06563
06564
06565
06566
06567
06568
06569 if ((dodist < aodist) && (dodist < dadist)) {
06570 if (offcenter && (b->offconstant > 0.0)) {
06571
06572 dxoff = 0.5 * xdo - b->offconstant * ydo;
06573 dyoff = 0.5 * ydo + b->offconstant * xdo;
06574
06575
06576 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06577 dx = dxoff;
06578 dy = dyoff;
06579 }
06580 }
06581 } else if (aodist < dadist) {
06582 if (offcenter && (b->offconstant > 0.0)) {
06583 dxoff = 0.5 * xao + b->offconstant * yao;
06584 dyoff = 0.5 * yao - b->offconstant * xao;
06585
06586
06587 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06588 dx = dxoff;
06589 dy = dyoff;
06590 }
06591 }
06592 } else {
06593 if (offcenter && (b->offconstant > 0.0)) {
06594 dxoff = 0.5 * (tapex[0] - tdest[0]) -
06595 b->offconstant * (tapex[1] - tdest[1]);
06596 dyoff = 0.5 * (tapex[1] - tdest[1]) +
06597 b->offconstant * (tapex[0] - tdest[0]);
06598
06599
06600 if (dxoff * dxoff + dyoff * dyoff <
06601 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
06602 dx = xdo + dxoff;
06603 dy = ydo + dyoff;
06604 }
06605 }
06606 }
06607
06608 circumcenter[0] = torg[0] + dx;
06609 circumcenter[1] = torg[1] + dy;
06610
06611
06612
06613
06614
06615
06616 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
06617 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
06618 }
06619
06622
06623
06624
06625
06626
06627
06628
06629
06630 #ifdef ANSI_DECLARATORS
06631 void triangleinit(struct mesh *m)
06632 #else
06633 void triangleinit(m)
06634 struct mesh *m;
06635 #endif
06636
06637 {
06638 poolzero(&m->vertices);
06639 poolzero(&m->triangles);
06640 poolzero(&m->subsegs);
06641 poolzero(&m->viri);
06642 poolzero(&m->badsubsegs);
06643 poolzero(&m->badtriangles);
06644 poolzero(&m->flipstackers);
06645 poolzero(&m->splaynodes);
06646
06647 m->recenttri.tri = (triangle *) NULL;
06648 m->undeads = 0;
06649 m->samples = 1;
06650 m->checksegments = 0;
06651 m->checkquality = 0;
06652 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
06653 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
06654 randomseed = 1;
06655
06656 exactinit();
06657 }
06658
06659
06660
06661
06662
06663
06664
06665
06666
06667
06668
06669 #ifdef ANSI_DECLARATORS
06670 unsigned long randomnation(unsigned int choices)
06671 #else
06672 unsigned long randomnation(choices)
06673 unsigned int choices;
06674 #endif
06675
06676 {
06677 randomseed = (randomseed * 1366l + 150889l) % 714025l;
06678 return randomseed / (714025l / choices + 1);
06679 }
06680
06681
06685
06686
06687
06688
06689
06690
06691 #ifndef REDUCED
06692
06693 #ifdef ANSI_DECLARATORS
06694 void checkmesh(struct mesh *m, struct behavior *b)
06695 #else
06696 void checkmesh(m, b)
06697 struct mesh *m;
06698 struct behavior *b;
06699 #endif
06700
06701 {
06702 struct otri triangleloop;
06703 struct otri oppotri, oppooppotri;
06704 vertex triorg, tridest, triapex;
06705 vertex oppoorg, oppodest;
06706 int horrors;
06707 int saveexact;
06708 triangle ptr;
06709
06710
06711 saveexact = b->noexact;
06712 b->noexact = 0;
06713 if (!b->quiet) {
06714 printf(" Checking consistency of mesh...\n");
06715 }
06716 horrors = 0;
06717
06718 traversalinit(&m->triangles);
06719 triangleloop.tri = triangletraverse(m);
06720 while (triangleloop.tri != (triangle *) NULL) {
06721
06722 for (triangleloop.orient = 0; triangleloop.orient < 3;
06723 triangleloop.orient++) {
06724 org(triangleloop, triorg);
06725 dest(triangleloop, tridest);
06726 if (triangleloop.orient == 0) {
06727
06728 apex(triangleloop, triapex);
06729 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
06730 printf(" !! !! Inverted ");
06731 printtriangle(m, b, &triangleloop);
06732 horrors++;
06733 }
06734 }
06735
06736 sym(triangleloop, oppotri);
06737 if (oppotri.tri != m->dummytri) {
06738
06739 sym(oppotri, oppooppotri);
06740 if ((triangleloop.tri != oppooppotri.tri)
06741 || (triangleloop.orient != oppooppotri.orient)) {
06742 printf(" !! !! Asymmetric triangle-triangle bond:\n");
06743 if (triangleloop.tri == oppooppotri.tri) {
06744 printf(" (Right triangle, wrong orientation)\n");
06745 }
06746 printf(" First ");
06747 printtriangle(m, b, &triangleloop);
06748 printf(" Second (nonreciprocating) ");
06749 printtriangle(m, b, &oppotri);
06750 horrors++;
06751 }
06752
06753
06754 org(oppotri, oppoorg);
06755 dest(oppotri, oppodest);
06756 if ((triorg != oppodest) || (tridest != oppoorg)) {
06757 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
06758 );
06759 printf(" First mismatched ");
06760 printtriangle(m, b, &triangleloop);
06761 printf(" Second mismatched ");
06762 printtriangle(m, b, &oppotri);
06763 horrors++;
06764 }
06765 }
06766 }
06767 triangleloop.tri = triangletraverse(m);
06768 }
06769 if (horrors == 0) {
06770 if (!b->quiet) {
06771 printf(" In my studied opinion, the mesh appears to be consistent.\n");
06772 }
06773 } else if (horrors == 1) {
06774 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
06775 } else {
06776 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
06777 }
06778
06779 b->noexact = saveexact;
06780 }
06781
06782 #endif
06783
06784
06785
06786
06787
06788
06789
06790 #ifndef REDUCED
06791
06792 #ifdef ANSI_DECLARATORS
06793 void checkdelaunay(struct mesh *m, struct behavior *b)
06794 #else
06795 void checkdelaunay(m, b)
06796 struct mesh *m;
06797 struct behavior *b;
06798 #endif
06799
06800 {
06801 struct otri triangleloop;
06802 struct otri oppotri;
06803 struct osub opposubseg;
06804 vertex triorg, tridest, triapex;
06805 vertex oppoapex;
06806 int shouldbedelaunay;
06807 int horrors;
06808 int saveexact;
06809 triangle ptr;
06810 subseg sptr;
06811
06812
06813 saveexact = b->noexact;
06814 b->noexact = 0;
06815 if (!b->quiet) {
06816 printf(" Checking Delaunay property of mesh...\n");
06817 }
06818 horrors = 0;
06819
06820 traversalinit(&m->triangles);
06821 triangleloop.tri = triangletraverse(m);
06822 while (triangleloop.tri != (triangle *) NULL) {
06823
06824 for (triangleloop.orient = 0; triangleloop.orient < 3;
06825 triangleloop.orient++) {
06826 org(triangleloop, triorg);
06827 dest(triangleloop, tridest);
06828 apex(triangleloop, triapex);
06829 sym(triangleloop, oppotri);
06830 apex(oppotri, oppoapex);
06831
06832
06833
06834 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
06835 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
06836 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
06837 (triorg != m->infvertex3) &&
06838 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
06839 (tridest != m->infvertex3) &&
06840 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
06841 (triapex != m->infvertex3) &&
06842 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
06843 (oppoapex != m->infvertex3);
06844 if (m->checksegments && shouldbedelaunay) {
06845
06846
06847 tspivot(triangleloop, opposubseg);
06848 if (opposubseg.ss != m->dummysub){
06849 shouldbedelaunay = 0;
06850 }
06851 }
06852 if (shouldbedelaunay) {
06853 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
06854 if (!b->weighted) {
06855 printf(" !! !! Non-Delaunay pair of triangles:\n");
06856 printf(" First non-Delaunay ");
06857 printtriangle(m, b, &triangleloop);
06858 printf(" Second non-Delaunay ");
06859 } else {
06860 printf(" !! !! Non-regular pair of triangles:\n");
06861 printf(" First non-regular ");
06862 printtriangle(m, b, &triangleloop);
06863 printf(" Second non-regular ");
06864 }
06865 printtriangle(m, b, &oppotri);
06866 horrors++;
06867 }
06868 }
06869 }
06870 triangleloop.tri = triangletraverse(m);
06871 }
06872 if (horrors == 0) {
06873 if (!b->quiet) {
06874 printf(
06875 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
06876 }
06877 } else if (horrors == 1) {
06878 printf(
06879 " !! !! !! !! Precisely one terrifying transgression identified.\n");
06880 } else {
06881 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
06882 }
06883
06884 b->noexact = saveexact;
06885 }
06886
06887 #endif
06888
06889
06890
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900 #ifndef CDT_ONLY
06901
06902 #ifdef ANSI_DECLARATORS
06903 void enqueuebadtriang(struct mesh *m, struct behavior *b,
06904 struct badtriang *badtri)
06905 #else
06906 void enqueuebadtriang(m, b, badtri)
06907 struct mesh *m;
06908 struct behavior *b;
06909 struct badtriang *badtri;
06910 #endif
06911
06912 {
06913 REAL length, multiplier;
06914 int exponent, expincrement;
06915 int queuenumber;
06916 int posexponent;
06917 int i;
06918
06919 if (b->verbose > 2) {
06920 printf(" Queueing bad triangle:\n");
06921 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
06922 badtri->triangorg[0], badtri->triangorg[1],
06923 badtri->triangdest[0], badtri->triangdest[1],
06924 badtri->triangapex[0], badtri->triangapex[1]);
06925 }
06926
06927
06928
06929 if (badtri->key >= 1.0) {
06930 length = badtri->key;
06931 posexponent = 1;
06932 } else {
06933
06934
06935 length = 1.0 / badtri->key;
06936 posexponent = 0;
06937 }
06938
06939
06940 exponent = 0;
06941 while (length > 2.0) {
06942
06943 expincrement = 1;
06944 multiplier = 0.5;
06945 while (length * multiplier * multiplier > 1.0) {
06946 expincrement *= 2;
06947 multiplier *= multiplier;
06948 }
06949
06950 exponent += expincrement;
06951 length *= multiplier;
06952 }
06953
06954 exponent = 2 * exponent + (length > SQUAREROOTTWO);
06955
06956
06957
06958 if (posexponent) {
06959 queuenumber = 2047 - exponent;
06960 } else {
06961 queuenumber = 2048 + exponent;
06962 }
06963
06964
06965 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
06966
06967
06968 if (queuenumber > m->firstnonemptyq) {
06969
06970 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
06971 m->firstnonemptyq = queuenumber;
06972 } else {
06973
06974
06975 i = queuenumber + 1;
06976 while (m->queuefront[i] == (struct badtriang *) NULL) {
06977 i++;
06978 }
06979
06980 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
06981 m->nextnonemptyq[i] = queuenumber;
06982 }
06983
06984 m->queuefront[queuenumber] = badtri;
06985 } else {
06986
06987 m->queuetail[queuenumber]->nexttriang = badtri;
06988 }
06989
06990 m->queuetail[queuenumber] = badtri;
06991
06992 badtri->nexttriang = (struct badtriang *) NULL;
06993 }
06994
06995 #endif
06996
06997
06998
06999
07000
07001
07002
07003
07004
07005
07006 #ifndef CDT_ONLY
07007
07008 #ifdef ANSI_DECLARATORS
07009 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
07010 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
07011 #else
07012 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
07013 struct mesh *m;
07014 struct behavior *b;
07015 struct otri *enqtri;
07016 REAL minedge;
07017 vertex enqapex;
07018 vertex enqorg;
07019 vertex enqdest;
07020 #endif
07021
07022 {
07023 struct badtriang *newbad;
07024
07025
07026 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
07027 newbad->poortri = encode(*enqtri);
07028 newbad->key = minedge;
07029 newbad->triangapex = enqapex;
07030 newbad->triangorg = enqorg;
07031 newbad->triangdest = enqdest;
07032 enqueuebadtriang(m, b, newbad);
07033 }
07034
07035 #endif
07036
07037
07038
07039
07040
07041
07042
07043 #ifndef CDT_ONLY
07044
07045 #ifdef ANSI_DECLARATORS
07046 struct badtriang *dequeuebadtriang(struct mesh *m)
07047 #else
07048 struct badtriang *dequeuebadtriang(m)
07049 struct mesh *m;
07050 #endif
07051
07052 {
07053 struct badtriang *result;
07054
07055
07056 if (m->firstnonemptyq < 0) {
07057 return (struct badtriang *) NULL;
07058 }
07059
07060 result = m->queuefront[m->firstnonemptyq];
07061
07062 m->queuefront[m->firstnonemptyq] = result->nexttriang;
07063
07064
07065 if (result == m->queuetail[m->firstnonemptyq]) {
07066 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
07067 }
07068 return result;
07069 }
07070
07071 #endif
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096 #ifndef CDT_ONLY
07097
07098 #ifdef ANSI_DECLARATORS
07099 int checkseg4encroach(struct mesh *m, struct behavior *b,
07100 struct osub *testsubseg)
07101 #else
07102 int checkseg4encroach(m, b, testsubseg)
07103 struct mesh *m;
07104 struct behavior *b;
07105 struct osub *testsubseg;
07106 #endif
07107
07108 {
07109 struct otri neighbortri;
07110 struct osub testsym;
07111 struct badsubseg *encroachedseg;
07112 REAL dotproduct;
07113 int encroached;
07114 int sides;
07115 vertex eorg, edest, eapex;
07116 triangle ptr;
07117
07118 encroached = 0;
07119 sides = 0;
07120
07121 sorg(*testsubseg, eorg);
07122 sdest(*testsubseg, edest);
07123
07124 stpivot(*testsubseg, neighbortri);
07125
07126 if (neighbortri.tri != m->dummytri) {
07127 sides++;
07128
07129 apex(neighbortri, eapex);
07130
07131
07132
07133
07134
07135 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07136 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07137 if (dotproduct < 0.0) {
07138 if (b->conformdel ||
07139 (dotproduct * dotproduct >=
07140 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07141 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07142 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07143 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07144 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07145 encroached = 1;
07146 }
07147 }
07148 }
07149
07150 ssym(*testsubseg, testsym);
07151 stpivot(testsym, neighbortri);
07152
07153 if (neighbortri.tri != m->dummytri) {
07154 sides++;
07155
07156 apex(neighbortri, eapex);
07157
07158
07159 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07160 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07161 if (dotproduct < 0.0) {
07162 if (b->conformdel ||
07163 (dotproduct * dotproduct >=
07164 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07165 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07166 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07167 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07168 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07169 encroached += 2;
07170 }
07171 }
07172 }
07173
07174 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
07175 if (b->verbose > 2) {
07176 printf(
07177 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
07178 eorg[0], eorg[1], edest[0], edest[1]);
07179 }
07180
07181
07182 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
07183 if (encroached == 1) {
07184 encroachedseg->encsubseg = sencode(*testsubseg);
07185 encroachedseg->subsegorg = eorg;
07186 encroachedseg->subsegdest = edest;
07187 } else {
07188 encroachedseg->encsubseg = sencode(testsym);
07189 encroachedseg->subsegorg = edest;
07190 encroachedseg->subsegdest = eorg;
07191 }
07192 }
07193
07194 return encroached;
07195 }
07196
07197 #endif
07198
07199
07200
07201
07202
07203
07204
07205
07206
07207
07208
07209 #ifndef CDT_ONLY
07210
07211 #ifdef ANSI_DECLARATORS
07212 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
07213 #else
07214 void testtriangle(m, b, testtri)
07215 struct mesh *m;
07216 struct behavior *b;
07217 struct otri *testtri;
07218 #endif
07219
07220 {
07221 struct otri tri1, tri2;
07222 struct osub testsub;
07223 vertex torg, tdest, tapex;
07224 vertex base1, base2;
07225 vertex org1, dest1, org2, dest2;
07226 vertex joinvertex;
07227 REAL dxod, dyod, dxda, dyda, dxao, dyao;
07228 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
07229 REAL apexlen, orglen, destlen, minedge;
07230 REAL angle;
07231 REAL area;
07232 REAL dist1, dist2;
07233 subseg sptr;
07234 triangle ptr;
07235
07236 org(*testtri, torg);
07237 dest(*testtri, tdest);
07238 apex(*testtri, tapex);
07239 dxod = torg[0] - tdest[0];
07240 dyod = torg[1] - tdest[1];
07241 dxda = tdest[0] - tapex[0];
07242 dyda = tdest[1] - tapex[1];
07243 dxao = tapex[0] - torg[0];
07244 dyao = tapex[1] - torg[1];
07245 dxod2 = dxod * dxod;
07246 dyod2 = dyod * dyod;
07247 dxda2 = dxda * dxda;
07248 dyda2 = dyda * dyda;
07249 dxao2 = dxao * dxao;
07250 dyao2 = dyao * dyao;
07251
07252 apexlen = dxod2 + dyod2;
07253 orglen = dxda2 + dyda2;
07254 destlen = dxao2 + dyao2;
07255
07256 if ((apexlen < orglen) && (apexlen < destlen)) {
07257
07258 minedge = apexlen;
07259
07260 angle = dxda * dxao + dyda * dyao;
07261 angle = angle * angle / (orglen * destlen);
07262 base1 = torg;
07263 base2 = tdest;
07264 otricopy(*testtri, tri1);
07265 } else if (orglen < destlen) {
07266
07267 minedge = orglen;
07268
07269 angle = dxod * dxao + dyod * dyao;
07270 angle = angle * angle / (apexlen * destlen);
07271 base1 = tdest;
07272 base2 = tapex;
07273 lnext(*testtri, tri1);
07274 } else {
07275
07276 minedge = destlen;
07277
07278 angle = dxod * dxda + dyod * dyda;
07279 angle = angle * angle / (apexlen * orglen);
07280 base1 = tapex;
07281 base2 = torg;
07282 lprev(*testtri, tri1);
07283 }
07284
07285 if (b->vararea || b->fixedarea || b->usertest) {
07286
07287 area = 0.5 * (dxod * dyda - dyod * dxda);
07288 if (b->fixedarea && (area > b->maxarea)) {
07289
07290 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07291 return;
07292 }
07293
07294
07295 if ((b->vararea) && (area > areabound(*testtri)) &&
07296 (areabound(*testtri) > 0.0)) {
07297
07298 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07299 return;
07300 }
07301
07302 if (b->usertest) {
07303
07304 if (triunsuitable(torg, tdest, tapex, area)) {
07305 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07306 return;
07307 }
07308 }
07309 }
07310
07311
07312 if (angle > b->goodangle) {
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322 if ((vertextype(base1) == SEGMENTVERTEX) &&
07323 (vertextype(base2) == SEGMENTVERTEX)) {
07324
07325
07326 tspivot(tri1, testsub);
07327 if (testsub.ss == m->dummysub) {
07328
07329 otricopy(tri1, tri2);
07330 do {
07331 oprevself(tri1);
07332 tspivot(tri1, testsub);
07333 } while (testsub.ss == m->dummysub);
07334
07335 segorg(testsub, org1);
07336 segdest(testsub, dest1);
07337
07338 do {
07339 dnextself(tri2);
07340 tspivot(tri2, testsub);
07341 } while (testsub.ss == m->dummysub);
07342
07343 segorg(testsub, org2);
07344 segdest(testsub, dest2);
07345
07346 joinvertex = (vertex) NULL;
07347 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
07348 joinvertex = dest1;
07349 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
07350 joinvertex = org1;
07351 }
07352 if (joinvertex != (vertex) NULL) {
07353
07354
07355 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
07356 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
07357 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
07358 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
07359
07360 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
07361
07362 return;
07363 }
07364 }
07365 }
07366 }
07367
07368
07369 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07370 }
07371 }
07372
07373 #endif
07374
07377
07378
07379
07383
07384
07385
07386
07387
07388
07389
07390
07391
07392
07393
07394
07395
07396
07397 #ifdef ANSI_DECLARATORS
07398 void makevertexmap(struct mesh *m, struct behavior *b)
07399 #else
07400 void makevertexmap(m, b)
07401 struct mesh *m;
07402 struct behavior *b;
07403 #endif
07404
07405 {
07406 struct otri triangleloop;
07407 vertex triorg;
07408
07409 if (b->verbose) {
07410 printf(" Constructing mapping from vertices to triangles.\n");
07411 }
07412 traversalinit(&m->triangles);
07413 triangleloop.tri = triangletraverse(m);
07414 while (triangleloop.tri != (triangle *) NULL) {
07415
07416 for (triangleloop.orient = 0; triangleloop.orient < 3;
07417 triangleloop.orient++) {
07418 org(triangleloop, triorg);
07419 setvertex2tri(triorg, encode(triangleloop));
07420 }
07421 triangleloop.tri = triangletraverse(m);
07422 }
07423 }
07424
07425
07426
07427
07428
07429
07430
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454
07455
07456
07457
07458
07459
07460
07461
07462
07463
07464
07465
07466
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477
07478
07479
07480
07481
07482
07483
07484
07485
07486
07487
07488
07489
07490
07491
07492 #ifdef ANSI_DECLARATORS
07493 enum locateresult preciselocate(struct mesh *m, struct behavior *b,
07494 vertex searchpoint, struct otri *searchtri,
07495 int stopatsubsegment)
07496 #else
07497 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
07498 struct mesh *m;
07499 struct behavior *b;
07500 vertex searchpoint;
07501 struct otri *searchtri;
07502 int stopatsubsegment;
07503 #endif
07504
07505 {
07506 struct otri backtracktri;
07507 struct osub checkedge;
07508 vertex forg, fdest, fapex;
07509 REAL orgorient, destorient;
07510 int moveleft;
07511 triangle ptr;
07512 subseg sptr;
07513
07514 if (b->verbose > 2) {
07515 printf(" Searching for point (%.12g, %.12g).\n",
07516 searchpoint[0], searchpoint[1]);
07517 }
07518
07519 org(*searchtri, forg);
07520 dest(*searchtri, fdest);
07521 apex(*searchtri, fapex);
07522 while (1) {
07523 if (b->verbose > 2) {
07524 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07525 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
07526 }
07527
07528 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
07529 lprevself(*searchtri);
07530 return ONVERTEX;
07531 }
07532
07533
07534 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
07535
07536
07537 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
07538 if (destorient > 0.0) {
07539 if (orgorient > 0.0) {
07540
07541
07542
07543
07544
07545 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
07546 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
07547 } else {
07548 moveleft = 1;
07549 }
07550 } else {
07551 if (orgorient > 0.0) {
07552 moveleft = 0;
07553 } else {
07554
07555
07556 if (destorient == 0.0) {
07557 lprevself(*searchtri);
07558 return ONEDGE;
07559 }
07560 if (orgorient == 0.0) {
07561 lnextself(*searchtri);
07562 return ONEDGE;
07563 }
07564 return INTRIANGLE;
07565 }
07566 }
07567
07568
07569
07570
07571 if (moveleft) {
07572 lprev(*searchtri, backtracktri);
07573 fdest = fapex;
07574 } else {
07575 lnext(*searchtri, backtracktri);
07576 forg = fapex;
07577 }
07578 sym(backtracktri, *searchtri);
07579
07580 if (m->checksegments && stopatsubsegment) {
07581
07582 tspivot(backtracktri, checkedge);
07583 if (checkedge.ss != m->dummysub) {
07584
07585 otricopy(backtracktri, *searchtri);
07586 return OUTSIDE;
07587 }
07588 }
07589
07590 if (searchtri->tri == m->dummytri) {
07591
07592 otricopy(backtracktri, *searchtri);
07593 return OUTSIDE;
07594 }
07595
07596 apex(*searchtri, fapex);
07597 }
07598 }
07599
07600
07601
07602
07603
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616
07617
07618
07619
07620
07621
07622
07623
07624
07625
07626
07627
07628
07629
07630
07631
07632
07633
07634
07635
07636 #ifdef ANSI_DECLARATORS
07637 enum locateresult locate(struct mesh *m, struct behavior *b,
07638 vertex searchpoint, struct otri *searchtri)
07639 #else
07640 enum locateresult locate(m, b, searchpoint, searchtri)
07641 struct mesh *m;
07642 struct behavior *b;
07643 vertex searchpoint;
07644 struct otri *searchtri;
07645 #endif
07646
07647 {
07648 VOID **sampleblock;
07649 char *firsttri;
07650 struct otri sampletri;
07651 vertex torg, tdest;
07652 unsigned long alignptr;
07653 REAL searchdist, dist;
07654 REAL ahead;
07655 long samplesperblock, totalsamplesleft, samplesleft;
07656 long population, totalpopulation;
07657 triangle ptr;
07658
07659 if (b->verbose > 2) {
07660 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
07661 searchpoint[0], searchpoint[1]);
07662 }
07663
07664
07665 org(*searchtri, torg);
07666 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07667 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07668 if (b->verbose > 2) {
07669 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
07670 torg[0], torg[1]);
07671 }
07672
07673
07674
07675 if (m->recenttri.tri != (triangle *) NULL) {
07676 if (!deadtri(m->recenttri.tri)) {
07677 org(m->recenttri, torg);
07678 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07679 otricopy(m->recenttri, *searchtri);
07680 return ONVERTEX;
07681 }
07682 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07683 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07684 if (dist < searchdist) {
07685 otricopy(m->recenttri, *searchtri);
07686 searchdist = dist;
07687 if (b->verbose > 2) {
07688 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
07689 torg[0], torg[1]);
07690 }
07691 }
07692 }
07693 }
07694
07695
07696
07697
07698
07699 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
07700 m->triangles.items) {
07701 m->samples++;
07702 }
07703
07704
07705
07706
07707
07708 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
07709
07710
07711 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
07712 m->triangles.maxitems + 1;
07713 totalsamplesleft = m->samples;
07714 population = m->triangles.itemsfirstblock;
07715 totalpopulation = m->triangles.maxitems;
07716 sampleblock = m->triangles.firstblock;
07717 sampletri.orient = 0;
07718 while (totalsamplesleft > 0) {
07719
07720 if (population > totalpopulation) {
07721 population = totalpopulation;
07722 }
07723
07724 alignptr = (unsigned long) (sampleblock + 1);
07725 firsttri = (char *) (alignptr +
07726 (unsigned long) m->triangles.alignbytes -
07727 (alignptr %
07728 (unsigned long) m->triangles.alignbytes));
07729
07730
07731 do {
07732 sampletri.tri = (triangle *) (firsttri +
07733 (randomnation((unsigned int) population) *
07734 m->triangles.itembytes));
07735 if (!deadtri(sampletri.tri)) {
07736 org(sampletri, torg);
07737 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07738 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07739 if (dist < searchdist) {
07740 otricopy(sampletri, *searchtri);
07741 searchdist = dist;
07742 if (b->verbose > 2) {
07743 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
07744 torg[0], torg[1]);
07745 }
07746 }
07747 }
07748
07749 samplesleft--;
07750 totalsamplesleft--;
07751 } while ((samplesleft > 0) && (totalsamplesleft > 0));
07752
07753 if (totalsamplesleft > 0) {
07754 sampleblock = (VOID **) *sampleblock;
07755 samplesleft = samplesperblock;
07756 totalpopulation -= population;
07757 population = TRIPERBLOCK;
07758 }
07759 }
07760
07761
07762 org(*searchtri, torg);
07763 dest(*searchtri, tdest);
07764
07765 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07766 return ONVERTEX;
07767 }
07768 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
07769 lnextself(*searchtri);
07770 return ONVERTEX;
07771 }
07772
07773 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
07774 if (ahead < 0.0) {
07775
07776
07777 symself(*searchtri);
07778 } else if (ahead == 0.0) {
07779
07780 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
07781 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
07782 return ONEDGE;
07783 }
07784 }
07785 return preciselocate(m, b, searchpoint, searchtri, 0);
07786 }
07787
07790
07791
07792
07796
07797
07798
07799
07800
07801
07802
07803
07804
07805
07806
07807 #ifdef ANSI_DECLARATORS
07808 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
07809 int subsegmark)
07810 #else
07811 void insertsubseg(m, b, tri, subsegmark)
07812 struct mesh *m;
07813 struct behavior *b;
07814 struct otri *tri;
07815 int subsegmark;
07816 #endif
07817
07818 {
07819 struct otri oppotri;
07820 struct osub newsubseg;
07821 vertex triorg, tridest;
07822 triangle ptr;
07823 subseg sptr;
07824
07825 org(*tri, triorg);
07826 dest(*tri, tridest);
07827
07828 if (vertexmark(triorg) == 0) {
07829 setvertexmark(triorg, subsegmark);
07830 }
07831 if (vertexmark(tridest) == 0) {
07832 setvertexmark(tridest, subsegmark);
07833 }
07834
07835 tspivot(*tri, newsubseg);
07836 if (newsubseg.ss == m->dummysub) {
07837
07838 makesubseg(m, &newsubseg);
07839 setsorg(newsubseg, tridest);
07840 setsdest(newsubseg, triorg);
07841 setsegorg(newsubseg, tridest);
07842 setsegdest(newsubseg, triorg);
07843
07844
07845
07846
07847 tsbond(*tri, newsubseg);
07848 sym(*tri, oppotri);
07849 ssymself(newsubseg);
07850 tsbond(oppotri, newsubseg);
07851 setmark(newsubseg, subsegmark);
07852 if (b->verbose > 2) {
07853 printf(" Inserting new ");
07854 printsubseg(m, b, &newsubseg);
07855 }
07856 } else {
07857 if (mark(newsubseg) == 0) {
07858 setmark(newsubseg, subsegmark);
07859 }
07860 }
07861 }
07862
07863
07864
07865
07866
07867
07868
07869
07870
07871
07872
07873
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887
07888
07889
07890
07891
07892
07893
07894
07895
07896
07897
07898
07899
07900
07901
07902
07903
07904
07905
07906
07907
07908
07909
07910
07911 #ifdef ANSI_DECLARATORS
07912 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
07913 #else
07914 void flip(m, b, flipedge)
07915 struct mesh *m;
07916 struct behavior *b;
07917 struct otri *flipedge;
07918 #endif
07919
07920 {
07921 struct otri botleft, botright;
07922 struct otri topleft, topright;
07923 struct otri top;
07924 struct otri botlcasing, botrcasing;
07925 struct otri toplcasing, toprcasing;
07926 struct osub botlsubseg, botrsubseg;
07927 struct osub toplsubseg, toprsubseg;
07928 vertex leftvertex, rightvertex, botvertex;
07929 vertex farvertex;
07930 triangle ptr;
07931 subseg sptr;
07932
07933
07934 org(*flipedge, rightvertex);
07935 dest(*flipedge, leftvertex);
07936 apex(*flipedge, botvertex);
07937 sym(*flipedge, top);
07938 #ifdef SELF_CHECK
07939 if (top.tri == m->dummytri) {
07940 printf("Internal error in flip(): Attempt to flip on boundary.\n");
07941 lnextself(*flipedge);
07942 return;
07943 }
07944 if (m->checksegments) {
07945 tspivot(*flipedge, toplsubseg);
07946 if (toplsubseg.ss != m->dummysub) {
07947 printf("Internal error in flip(): Attempt to flip a segment.\n");
07948 lnextself(*flipedge);
07949 return;
07950 }
07951 }
07952 #endif
07953 apex(top, farvertex);
07954
07955
07956 lprev(top, topleft);
07957 sym(topleft, toplcasing);
07958 lnext(top, topright);
07959 sym(topright, toprcasing);
07960 lnext(*flipedge, botleft);
07961 sym(botleft, botlcasing);
07962 lprev(*flipedge, botright);
07963 sym(botright, botrcasing);
07964
07965 bond(topleft, botlcasing);
07966 bond(botleft, botrcasing);
07967 bond(botright, toprcasing);
07968 bond(topright, toplcasing);
07969
07970 if (m->checksegments) {
07971
07972 tspivot(topleft, toplsubseg);
07973 tspivot(botleft, botlsubseg);
07974 tspivot(botright, botrsubseg);
07975 tspivot(topright, toprsubseg);
07976 if (toplsubseg.ss == m->dummysub) {
07977 tsdissolve(topright);
07978 } else {
07979 tsbond(topright, toplsubseg);
07980 }
07981 if (botlsubseg.ss == m->dummysub) {
07982 tsdissolve(topleft);
07983 } else {
07984 tsbond(topleft, botlsubseg);
07985 }
07986 if (botrsubseg.ss == m->dummysub) {
07987 tsdissolve(botleft);
07988 } else {
07989 tsbond(botleft, botrsubseg);
07990 }
07991 if (toprsubseg.ss == m->dummysub) {
07992 tsdissolve(botright);
07993 } else {
07994 tsbond(botright, toprsubseg);
07995 }
07996 }
07997
07998
07999 setorg(*flipedge, farvertex);
08000 setdest(*flipedge, botvertex);
08001 setapex(*flipedge, rightvertex);
08002 setorg(top, botvertex);
08003 setdest(top, farvertex);
08004 setapex(top, leftvertex);
08005 if (b->verbose > 2) {
08006 printf(" Edge flip results in left ");
08007 printtriangle(m, b, &top);
08008 printf(" and right ");
08009 printtriangle(m, b, flipedge);
08010 }
08011 }
08012
08013
08014
08015
08016
08017
08018
08019
08020
08021
08022
08023
08024
08025
08026
08027
08028
08029
08030
08031
08032
08033
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046 #ifdef ANSI_DECLARATORS
08047 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
08048 #else
08049 void unflip(m, b, flipedge)
08050 struct mesh *m;
08051 struct behavior *b;
08052 struct otri *flipedge;
08053 #endif
08054
08055 {
08056 struct otri botleft, botright;
08057 struct otri topleft, topright;
08058 struct otri top;
08059 struct otri botlcasing, botrcasing;
08060 struct otri toplcasing, toprcasing;
08061 struct osub botlsubseg, botrsubseg;
08062 struct osub toplsubseg, toprsubseg;
08063 vertex leftvertex, rightvertex, botvertex;
08064 vertex farvertex;
08065 triangle ptr;
08066 subseg sptr;
08067
08068
08069 org(*flipedge, rightvertex);
08070 dest(*flipedge, leftvertex);
08071 apex(*flipedge, botvertex);
08072 sym(*flipedge, top);
08073 #ifdef SELF_CHECK
08074 if (top.tri == m->dummytri) {
08075 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
08076 lnextself(*flipedge);
08077 return;
08078 }
08079 if (m->checksegments) {
08080 tspivot(*flipedge, toplsubseg);
08081 if (toplsubseg.ss != m->dummysub) {
08082 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
08083 lnextself(*flipedge);
08084 return;
08085 }
08086 }
08087 #endif
08088 apex(top, farvertex);
08089
08090
08091 lprev(top, topleft);
08092 sym(topleft, toplcasing);
08093 lnext(top, topright);
08094 sym(topright, toprcasing);
08095 lnext(*flipedge, botleft);
08096 sym(botleft, botlcasing);
08097 lprev(*flipedge, botright);
08098 sym(botright, botrcasing);
08099
08100 bond(topleft, toprcasing);
08101 bond(botleft, toplcasing);
08102 bond(botright, botlcasing);
08103 bond(topright, botrcasing);
08104
08105 if (m->checksegments) {
08106
08107 tspivot(topleft, toplsubseg);
08108 tspivot(botleft, botlsubseg);
08109 tspivot(botright, botrsubseg);
08110 tspivot(topright, toprsubseg);
08111 if (toplsubseg.ss == m->dummysub) {
08112 tsdissolve(botleft);
08113 } else {
08114 tsbond(botleft, toplsubseg);
08115 }
08116 if (botlsubseg.ss == m->dummysub) {
08117 tsdissolve(botright);
08118 } else {
08119 tsbond(botright, botlsubseg);
08120 }
08121 if (botrsubseg.ss == m->dummysub) {
08122 tsdissolve(topright);
08123 } else {
08124 tsbond(topright, botrsubseg);
08125 }
08126 if (toprsubseg.ss == m->dummysub) {
08127 tsdissolve(topleft);
08128 } else {
08129 tsbond(topleft, toprsubseg);
08130 }
08131 }
08132
08133
08134 setorg(*flipedge, botvertex);
08135 setdest(*flipedge, farvertex);
08136 setapex(*flipedge, leftvertex);
08137 setorg(top, farvertex);
08138 setdest(top, botvertex);
08139 setapex(top, rightvertex);
08140 if (b->verbose > 2) {
08141 printf(" Edge unflip results in left ");
08142 printtriangle(m, b, flipedge);
08143 printf(" and right ");
08144 printtriangle(m, b, &top);
08145 }
08146 }
08147
08148
08149
08150
08151
08152
08153
08154
08155
08156
08157
08158
08159
08160
08161
08162
08163
08164
08165
08166
08167
08168
08169
08170
08171
08172
08173
08174
08175
08176
08177
08178
08179
08180
08181
08182
08183
08184
08185
08186
08187
08188
08189
08190
08191
08192
08193
08194
08195 #ifdef ANSI_DECLARATORS
08196 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
08197 vertex newvertex, struct otri *searchtri,
08198 struct osub *splitseg,
08199 int segmentflaws, int triflaws)
08200 #else
08201 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
08202 segmentflaws, triflaws)
08203 struct mesh *m;
08204 struct behavior *b;
08205 vertex newvertex;
08206 struct otri *searchtri;
08207 struct osub *splitseg;
08208 int segmentflaws;
08209 int triflaws;
08210 #endif
08211
08212 {
08213 struct otri horiz;
08214 struct otri top;
08215 struct otri botleft, botright;
08216 struct otri topleft, topright;
08217 struct otri newbotleft, newbotright;
08218 struct otri newtopright;
08219 struct otri botlcasing, botrcasing;
08220 struct otri toplcasing={NULL, 0}, toprcasing={NULL, 0};
08221 struct otri testtri;
08222 struct osub botlsubseg, botrsubseg;
08223 struct osub toplsubseg, toprsubseg;
08224 struct osub brokensubseg;
08225 struct osub checksubseg;
08226 struct osub rightsubseg;
08227 struct osub newsubseg;
08228 struct badsubseg *encroached;
08229 struct flipstacker *newflip;
08230 vertex first;
08231 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
08232 vertex segmentorg, segmentdest;
08233 REAL attrib;
08234 REAL area;
08235 enum insertvertexresult success;
08236 enum locateresult intersect;
08237 int doflip;
08238 int mirrorflag;
08239 int enq;
08240 int i;
08241 triangle ptr;
08242 subseg sptr;
08243
08244 if (b->verbose > 1) {
08245 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
08246 }
08247
08248 if (splitseg == (struct osub *) NULL) {
08249
08250
08251 if (searchtri->tri == m->dummytri) {
08252
08253 horiz.tri = m->dummytri;
08254 horiz.orient = 0;
08255 symself(horiz);
08256
08257 intersect = locate(m, b, newvertex, &horiz);
08258 } else {
08259
08260 otricopy(*searchtri, horiz);
08261 intersect = preciselocate(m, b, newvertex, &horiz, 1);
08262 }
08263 } else {
08264
08265
08266 otricopy(*searchtri, horiz);
08267 intersect = ONEDGE;
08268 }
08269
08270 if (intersect == ONVERTEX) {
08271
08272
08273 otricopy(horiz, *searchtri);
08274 otricopy(horiz, m->recenttri);
08275 return DUPLICATEVERTEX;
08276 }
08277 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
08278
08279 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
08280
08281 tspivot(horiz, brokensubseg);
08282 if (brokensubseg.ss != m->dummysub) {
08283
08284 if (segmentflaws) {
08285 enq = b->nobisect != 2;
08286 if (enq && (b->nobisect == 1)) {
08287
08288
08289 sym(horiz, testtri);
08290 enq = testtri.tri != m->dummytri;
08291 }
08292 if (enq) {
08293
08294 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
08295 encroached->encsubseg = sencode(brokensubseg);
08296 sorg(brokensubseg, encroached->subsegorg);
08297 sdest(brokensubseg, encroached->subsegdest);
08298 if (b->verbose > 2) {
08299 printf(
08300 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
08301 encroached->subsegorg[0], encroached->subsegorg[1],
08302 encroached->subsegdest[0], encroached->subsegdest[1]);
08303 }
08304 }
08305 }
08306
08307
08308 otricopy(horiz, *searchtri);
08309 otricopy(horiz, m->recenttri);
08310 return VIOLATINGVERTEX;
08311 }
08312 }
08313
08314
08315
08316 lprev(horiz, botright);
08317 sym(botright, botrcasing);
08318 sym(horiz, topright);
08319
08320 mirrorflag = topright.tri != m->dummytri;
08321 if (mirrorflag) {
08322 lnextself(topright);
08323 sym(topright, toprcasing);
08324 maketriangle(m, b, &newtopright);
08325 } else {
08326
08327 m->hullsize++;
08328 }
08329 maketriangle(m, b, &newbotright);
08330
08331
08332 org(horiz, rightvertex);
08333 dest(horiz, leftvertex);
08334 apex(horiz, botvertex);
08335 setorg(newbotright, botvertex);
08336 setdest(newbotright, rightvertex);
08337 setapex(newbotright, newvertex);
08338 setorg(horiz, newvertex);
08339 for (i = 0; i < m->eextras; i++) {
08340
08341 setelemattribute(newbotright, i, elemattribute(botright, i));
08342 }
08343 if (b->vararea) {
08344
08345 setareabound(newbotright, areabound(botright));
08346 }
08347 if (mirrorflag) {
08348 dest(topright, topvertex);
08349 setorg(newtopright, rightvertex);
08350 setdest(newtopright, topvertex);
08351 setapex(newtopright, newvertex);
08352 setorg(topright, newvertex);
08353 for (i = 0; i < m->eextras; i++) {
08354
08355 setelemattribute(newtopright, i, elemattribute(topright, i));
08356 }
08357 if (b->vararea) {
08358
08359 setareabound(newtopright, areabound(topright));
08360 }
08361 }
08362
08363
08364
08365 if (m->checksegments) {
08366 tspivot(botright, botrsubseg);
08367 if (botrsubseg.ss != m->dummysub) {
08368 tsdissolve(botright);
08369 tsbond(newbotright, botrsubseg);
08370 }
08371 if (mirrorflag) {
08372 tspivot(topright, toprsubseg);
08373 if (toprsubseg.ss != m->dummysub) {
08374 tsdissolve(topright);
08375 tsbond(newtopright, toprsubseg);
08376 }
08377 }
08378 }
08379
08380
08381 bond(newbotright, botrcasing);
08382 lprevself(newbotright);
08383 bond(newbotright, botright);
08384 lprevself(newbotright);
08385 if (mirrorflag) {
08386 bond(newtopright, toprcasing);
08387 lnextself(newtopright);
08388 bond(newtopright, topright);
08389 lnextself(newtopright);
08390 bond(newtopright, newbotright);
08391 }
08392
08393 if (splitseg != (struct osub *) NULL) {
08394
08395 setsdest(*splitseg, newvertex);
08396 segorg(*splitseg, segmentorg);
08397 segdest(*splitseg, segmentdest);
08398 ssymself(*splitseg);
08399 spivot(*splitseg, rightsubseg);
08400 insertsubseg(m, b, &newbotright, mark(*splitseg));
08401 tspivot(newbotright, newsubseg);
08402 setsegorg(newsubseg, segmentorg);
08403 setsegdest(newsubseg, segmentdest);
08404 sbond(*splitseg, newsubseg);
08405 ssymself(newsubseg);
08406 sbond(newsubseg, rightsubseg);
08407 ssymself(*splitseg);
08408
08409
08410 if (vertexmark(newvertex) == 0) {
08411 setvertexmark(newvertex, mark(*splitseg));
08412 }
08413 }
08414
08415 if (m->checkquality) {
08416 poolrestart(&m->flipstackers);
08417 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08418 m->lastflip->flippedtri = encode(horiz);
08419 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
08420 }
08421
08422 #ifdef SELF_CHECK
08423 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08424 printf("Internal error in insertvertex():\n");
08425 printf(
08426 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
08427 }
08428 if (mirrorflag) {
08429 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
08430 printf("Internal error in insertvertex():\n");
08431 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
08432 }
08433 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
08434 printf("Internal error in insertvertex():\n");
08435 printf(
08436 " Clockwise triangle after edge vertex insertion (top right).\n");
08437 }
08438 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
08439 printf("Internal error in insertvertex():\n");
08440 printf(
08441 " Clockwise triangle after edge vertex insertion (top left).\n");
08442 }
08443 }
08444 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08445 printf("Internal error in insertvertex():\n");
08446 printf(
08447 " Clockwise triangle after edge vertex insertion (bottom left).\n");
08448 }
08449 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08450 printf("Internal error in insertvertex():\n");
08451 printf(
08452 " Clockwise triangle after edge vertex insertion (bottom right).\n");
08453 }
08454 #endif
08455 if (b->verbose > 2) {
08456 printf(" Updating bottom left ");
08457 printtriangle(m, b, &botright);
08458 if (mirrorflag) {
08459 printf(" Updating top left ");
08460 printtriangle(m, b, &topright);
08461 printf(" Creating top right ");
08462 printtriangle(m, b, &newtopright);
08463 }
08464 printf(" Creating bottom right ");
08465 printtriangle(m, b, &newbotright);
08466 }
08467
08468
08469
08470 lnextself(horiz);
08471 } else {
08472
08473 lnext(horiz, botleft);
08474 lprev(horiz, botright);
08475 sym(botleft, botlcasing);
08476 sym(botright, botrcasing);
08477 maketriangle(m, b, &newbotleft);
08478 maketriangle(m, b, &newbotright);
08479
08480
08481 org(horiz, rightvertex);
08482 dest(horiz, leftvertex);
08483 apex(horiz, botvertex);
08484 setorg(newbotleft, leftvertex);
08485 setdest(newbotleft, botvertex);
08486 setapex(newbotleft, newvertex);
08487 setorg(newbotright, botvertex);
08488 setdest(newbotright, rightvertex);
08489 setapex(newbotright, newvertex);
08490 setapex(horiz, newvertex);
08491 for (i = 0; i < m->eextras; i++) {
08492
08493 attrib = elemattribute(horiz, i);
08494 setelemattribute(newbotleft, i, attrib);
08495 setelemattribute(newbotright, i, attrib);
08496 }
08497 if (b->vararea) {
08498
08499 area = areabound(horiz);
08500 setareabound(newbotleft, area);
08501 setareabound(newbotright, area);
08502 }
08503
08504
08505
08506 if (m->checksegments) {
08507 tspivot(botleft, botlsubseg);
08508 if (botlsubseg.ss != m->dummysub) {
08509 tsdissolve(botleft);
08510 tsbond(newbotleft, botlsubseg);
08511 }
08512 tspivot(botright, botrsubseg);
08513 if (botrsubseg.ss != m->dummysub) {
08514 tsdissolve(botright);
08515 tsbond(newbotright, botrsubseg);
08516 }
08517 }
08518
08519
08520 bond(newbotleft, botlcasing);
08521 bond(newbotright, botrcasing);
08522 lnextself(newbotleft);
08523 lprevself(newbotright);
08524 bond(newbotleft, newbotright);
08525 lnextself(newbotleft);
08526 bond(botleft, newbotleft);
08527 lprevself(newbotright);
08528 bond(botright, newbotright);
08529
08530 if (m->checkquality) {
08531 poolrestart(&m->flipstackers);
08532 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08533 m->lastflip->flippedtri = encode(horiz);
08534 m->lastflip->prevflip = (struct flipstacker *) NULL;
08535 }
08536
08537 #ifdef SELF_CHECK
08538 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08539 printf("Internal error in insertvertex():\n");
08540 printf(" Clockwise triangle prior to vertex insertion.\n");
08541 }
08542 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
08543 printf("Internal error in insertvertex():\n");
08544 printf(" Clockwise triangle after vertex insertion (top).\n");
08545 }
08546 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08547 printf("Internal error in insertvertex():\n");
08548 printf(" Clockwise triangle after vertex insertion (left).\n");
08549 }
08550 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08551 printf("Internal error in insertvertex():\n");
08552 printf(" Clockwise triangle after vertex insertion (right).\n");
08553 }
08554 #endif
08555 if (b->verbose > 2) {
08556 printf(" Updating top ");
08557 printtriangle(m, b, &horiz);
08558 printf(" Creating left ");
08559 printtriangle(m, b, &newbotleft);
08560 printf(" Creating right ");
08561 printtriangle(m, b, &newbotright);
08562 }
08563 }
08564
08565
08566
08567 success = SUCCESSFULVERTEX;
08568
08569
08570
08571
08572 org(horiz, first);
08573 rightvertex = first;
08574 dest(horiz, leftvertex);
08575
08576 while (1) {
08577
08578 doflip = 1;
08579
08580 if (m->checksegments) {
08581
08582 tspivot(horiz, checksubseg);
08583 if (checksubseg.ss != m->dummysub) {
08584
08585 doflip = 0;
08586 #ifndef CDT_ONLY
08587 if (segmentflaws) {
08588
08589 if (checkseg4encroach(m, b, &checksubseg)) {
08590 success = ENCROACHINGVERTEX;
08591 }
08592 }
08593 #endif
08594 }
08595 }
08596
08597 if (doflip) {
08598
08599 sym(horiz, top);
08600 if (top.tri == m->dummytri) {
08601
08602 doflip = 0;
08603 } else {
08604
08605 apex(top, farvertex);
08606
08607
08608
08609
08610
08611 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
08612 (leftvertex == m->infvertex3)) {
08613
08614
08615
08616
08617 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
08618 > 0.0;
08619 } else if ((rightvertex == m->infvertex1) ||
08620 (rightvertex == m->infvertex2) ||
08621 (rightvertex == m->infvertex3)) {
08622
08623
08624
08625
08626 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
08627 > 0.0;
08628 } else if ((farvertex == m->infvertex1) ||
08629 (farvertex == m->infvertex2) ||
08630 (farvertex == m->infvertex3)) {
08631
08632
08633 doflip = 0;
08634 } else {
08635
08636 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
08637 farvertex) > 0.0;
08638 }
08639 if (doflip) {
08640
08641
08642
08643 lprev(top, topleft);
08644 sym(topleft, toplcasing);
08645 lnext(top, topright);
08646 sym(topright, toprcasing);
08647 lnext(horiz, botleft);
08648 sym(botleft, botlcasing);
08649 lprev(horiz, botright);
08650 sym(botright, botrcasing);
08651
08652 bond(topleft, botlcasing);
08653 bond(botleft, botrcasing);
08654 bond(botright, toprcasing);
08655 bond(topright, toplcasing);
08656 if (m->checksegments) {
08657
08658 tspivot(topleft, toplsubseg);
08659 tspivot(botleft, botlsubseg);
08660 tspivot(botright, botrsubseg);
08661 tspivot(topright, toprsubseg);
08662 if (toplsubseg.ss == m->dummysub) {
08663 tsdissolve(topright);
08664 } else {
08665 tsbond(topright, toplsubseg);
08666 }
08667 if (botlsubseg.ss == m->dummysub) {
08668 tsdissolve(topleft);
08669 } else {
08670 tsbond(topleft, botlsubseg);
08671 }
08672 if (botrsubseg.ss == m->dummysub) {
08673 tsdissolve(botleft);
08674 } else {
08675 tsbond(botleft, botrsubseg);
08676 }
08677 if (toprsubseg.ss == m->dummysub) {
08678 tsdissolve(botright);
08679 } else {
08680 tsbond(botright, toprsubseg);
08681 }
08682 }
08683
08684 setorg(horiz, farvertex);
08685 setdest(horiz, newvertex);
08686 setapex(horiz, rightvertex);
08687 setorg(top, newvertex);
08688 setdest(top, farvertex);
08689 setapex(top, leftvertex);
08690 for (i = 0; i < m->eextras; i++) {
08691
08692 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
08693 setelemattribute(top, i, attrib);
08694 setelemattribute(horiz, i, attrib);
08695 }
08696 if (b->vararea) {
08697 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
08698 area = -1.0;
08699 } else {
08700
08701
08702
08703 area = 0.5 * (areabound(top) + areabound(horiz));
08704 }
08705 setareabound(top, area);
08706 setareabound(horiz, area);
08707 }
08708
08709 if (m->checkquality) {
08710 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08711 newflip->flippedtri = encode(horiz);
08712 newflip->prevflip = m->lastflip;
08713 m->lastflip = newflip;
08714 }
08715
08716 #ifdef SELF_CHECK
08717 if (newvertex != (vertex) NULL) {
08718 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
08719 0.0) {
08720 printf("Internal error in insertvertex():\n");
08721 printf(" Clockwise triangle prior to edge flip (bottom).\n");
08722 }
08723
08724
08725
08726
08727
08728
08729
08730
08731
08732
08733 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
08734 0.0) {
08735 printf("Internal error in insertvertex():\n");
08736 printf(" Clockwise triangle after edge flip (left).\n");
08737 }
08738 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
08739 0.0) {
08740 printf("Internal error in insertvertex():\n");
08741 printf(" Clockwise triangle after edge flip (right).\n");
08742 }
08743 }
08744 #endif
08745 if (b->verbose > 2) {
08746 printf(" Edge flip results in left ");
08747 lnextself(topleft);
08748 printtriangle(m, b, &topleft);
08749 printf(" and right ");
08750 printtriangle(m, b, &horiz);
08751 }
08752
08753
08754
08755 lprevself(horiz);
08756 leftvertex = farvertex;
08757 }
08758 }
08759 }
08760 if (!doflip) {
08761
08762 #ifndef CDT_ONLY
08763 if (triflaws) {
08764
08765 testtriangle(m, b, &horiz);
08766 }
08767 #endif
08768
08769 lnextself(horiz);
08770 sym(horiz, testtri);
08771
08772
08773
08774 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
08775
08776 lnext(horiz, *searchtri);
08777 lnext(horiz, m->recenttri);
08778 return success;
08779 }
08780
08781 lnext(testtri, horiz);
08782 rightvertex = leftvertex;
08783 dest(horiz, leftvertex);
08784 }
08785 }
08786 }
08787
08788
08789
08790
08791
08792
08793
08794
08795
08796
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822
08823
08824
08825
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837
08838
08839
08840
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852 #ifdef ANSI_DECLARATORS
08853 void triangulatepolygon(struct mesh *m, struct behavior *b,
08854 struct otri *firstedge, struct otri *lastedge,
08855 int edgecount, int doflip, int triflaws)
08856 #else
08857 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
08858 struct mesh *m;
08859 struct behavior *b;
08860 struct otri *firstedge;
08861 struct otri *lastedge;
08862 int edgecount;
08863 int doflip;
08864 int triflaws;
08865 #endif
08866
08867 {
08868 struct otri testtri;
08869 struct otri besttri;
08870 struct otri tempedge;
08871 vertex leftbasevertex, rightbasevertex;
08872 vertex testvertex;
08873 vertex bestvertex;
08874 int bestnumber;
08875 int i;
08876 triangle ptr;
08877
08878
08879 apex(*lastedge, leftbasevertex);
08880 dest(*firstedge, rightbasevertex);
08881 if (b->verbose > 2) {
08882 printf(" Triangulating interior polygon at edge\n");
08883 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
08884 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
08885 }
08886
08887 onext(*firstedge, besttri);
08888 dest(besttri, bestvertex);
08889 otricopy(besttri, testtri);
08890 bestnumber = 1;
08891 for (i = 2; i <= edgecount - 2; i++) {
08892 onextself(testtri);
08893 dest(testtri, testvertex);
08894
08895 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
08896 testvertex) > 0.0) {
08897 otricopy(testtri, besttri);
08898 bestvertex = testvertex;
08899 bestnumber = i;
08900 }
08901 }
08902 if (b->verbose > 2) {
08903 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
08904 bestvertex[1]);
08905 }
08906 if (bestnumber > 1) {
08907
08908 oprev(besttri, tempedge);
08909 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
08910 triflaws);
08911 }
08912 if (bestnumber < edgecount - 2) {
08913
08914 sym(besttri, tempedge);
08915 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
08916 triflaws);
08917
08918 sym(tempedge, besttri);
08919 }
08920 if (doflip) {
08921
08922 flip(m, b, &besttri);
08923 #ifndef CDT_ONLY
08924 if (triflaws) {
08925
08926 sym(besttri, testtri);
08927 testtriangle(m, b, &testtri);
08928 }
08929 #endif
08930 }
08931
08932 otricopy(besttri, *lastedge);
08933 }
08934
08935
08936
08937
08938
08939
08940
08941
08942
08943
08944
08945
08946
08947
08948
08949 #ifndef CDT_ONLY
08950
08951 #ifdef ANSI_DECLARATORS
08952 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
08953 #else
08954 void deletevertex(m, b, deltri)
08955 struct mesh *m;
08956 struct behavior *b;
08957 struct otri *deltri;
08958 #endif
08959
08960 {
08961 struct otri countingtri;
08962 struct otri firstedge, lastedge;
08963 struct otri deltriright;
08964 struct otri lefttri, righttri;
08965 struct otri leftcasing, rightcasing;
08966 struct osub leftsubseg, rightsubseg;
08967 vertex delvertex;
08968 vertex neworg;
08969 int edgecount;
08970 triangle ptr;
08971 subseg sptr;
08972
08973 org(*deltri, delvertex);
08974 if (b->verbose > 1) {
08975 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
08976 }
08977 vertexdealloc(m, delvertex);
08978
08979
08980 onext(*deltri, countingtri);
08981 edgecount = 1;
08982 while (!otriequal(*deltri, countingtri)) {
08983 #ifdef SELF_CHECK
08984 if (countingtri.tri == m->dummytri) {
08985 printf("Internal error in deletevertex():\n");
08986 printf(" Attempt to delete boundary vertex.\n");
08987 internalerror();
08988 }
08989 #endif
08990 edgecount++;
08991 onextself(countingtri);
08992 }
08993
08994 #ifdef SELF_CHECK
08995 if (edgecount < 3) {
08996 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
08997 edgecount);
08998 internalerror();
08999 }
09000 #endif
09001 if (edgecount > 3) {
09002
09003
09004
09005 onext(*deltri, firstedge);
09006 oprev(*deltri, lastedge);
09007 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
09008 !b->nobisect);
09009 }
09010
09011 lprev(*deltri, deltriright);
09012 dnext(*deltri, lefttri);
09013 sym(lefttri, leftcasing);
09014 oprev(deltriright, righttri);
09015 sym(righttri, rightcasing);
09016 bond(*deltri, leftcasing);
09017 bond(deltriright, rightcasing);
09018 tspivot(lefttri, leftsubseg);
09019 if (leftsubseg.ss != m->dummysub) {
09020 tsbond(*deltri, leftsubseg);
09021 }
09022 tspivot(righttri, rightsubseg);
09023 if (rightsubseg.ss != m->dummysub) {
09024 tsbond(deltriright, rightsubseg);
09025 }
09026
09027
09028 org(lefttri, neworg);
09029 setorg(*deltri, neworg);
09030 if (!b->nobisect) {
09031 testtriangle(m, b, deltri);
09032 }
09033
09034
09035 triangledealloc(m, lefttri.tri);
09036 triangledealloc(m, righttri.tri);
09037 }
09038
09039 #endif
09040
09041
09042
09043
09044
09045
09046
09047
09048
09049
09050
09051
09052 #ifndef CDT_ONLY
09053
09054 #ifdef ANSI_DECLARATORS
09055 void undovertex(struct mesh *m, struct behavior *b)
09056 #else
09057 void undovertex(m, b)
09058 struct mesh *m;
09059 struct behavior *b;
09060 #endif
09061
09062 {
09063 struct otri fliptri;
09064 struct otri botleft, botright, topright;
09065 struct otri botlcasing, botrcasing, toprcasing;
09066 struct otri gluetri;
09067 struct osub botlsubseg, botrsubseg, toprsubseg;
09068 vertex botvertex, rightvertex;
09069 triangle ptr;
09070 subseg sptr;
09071
09072
09073
09074 while (m->lastflip != (struct flipstacker *) NULL) {
09075
09076 decode(m->lastflip->flippedtri, fliptri);
09077
09078
09079
09080
09081
09082 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
09083
09084
09085 dprev(fliptri, botleft);
09086 lnextself(botleft);
09087 onext(fliptri, botright);
09088 lprevself(botright);
09089 sym(botleft, botlcasing);
09090 sym(botright, botrcasing);
09091 dest(botleft, botvertex);
09092
09093 setapex(fliptri, botvertex);
09094 lnextself(fliptri);
09095 bond(fliptri, botlcasing);
09096 tspivot(botleft, botlsubseg);
09097 tsbond(fliptri, botlsubseg);
09098 lnextself(fliptri);
09099 bond(fliptri, botrcasing);
09100 tspivot(botright, botrsubseg);
09101 tsbond(fliptri, botrsubseg);
09102
09103
09104 triangledealloc(m, botleft.tri);
09105 triangledealloc(m, botright.tri);
09106 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
09107
09108
09109 lprev(fliptri, gluetri);
09110 sym(gluetri, botright);
09111 lnextself(botright);
09112 sym(botright, botrcasing);
09113 dest(botright, rightvertex);
09114
09115 setorg(fliptri, rightvertex);
09116 bond(gluetri, botrcasing);
09117 tspivot(botright, botrsubseg);
09118 tsbond(gluetri, botrsubseg);
09119
09120
09121 triangledealloc(m, botright.tri);
09122
09123 sym(fliptri, gluetri);
09124 if (gluetri.tri != m->dummytri) {
09125 lnextself(gluetri);
09126 dnext(gluetri, topright);
09127 sym(topright, toprcasing);
09128
09129 setorg(gluetri, rightvertex);
09130 bond(gluetri, toprcasing);
09131 tspivot(topright, toprsubseg);
09132 tsbond(gluetri, toprsubseg);
09133
09134
09135 triangledealloc(m, topright.tri);
09136 }
09137
09138
09139 m->lastflip->prevflip = (struct flipstacker *) NULL;
09140 } else {
09141
09142 unflip(m, b, &fliptri);
09143 }
09144
09145
09146 m->lastflip = m->lastflip->prevflip;
09147 }
09148 }
09149
09150 #endif
09151
09154
09155
09156
09160
09161
09162
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172
09173
09174
09175
09176
09177
09178
09179
09180
09181
09182
09183
09184
09185
09186
09187
09188
09189
09190
09191
09192
09193
09194
09195
09196
09197
09198
09199
09200
09201 #ifdef ANSI_DECLARATORS
09202 void vertexsort(vertex *sortarray, int arraysize)
09203 #else
09204 void vertexsort(sortarray, arraysize)
09205 vertex *sortarray;
09206 int arraysize;
09207 #endif
09208
09209 {
09210 int left, right;
09211 int pivot;
09212 REAL pivotx, pivoty;
09213 vertex temp;
09214
09215 if (arraysize == 2) {
09216
09217 if ((sortarray[0][0] > sortarray[1][0]) ||
09218 ((sortarray[0][0] == sortarray[1][0]) &&
09219 (sortarray[0][1] > sortarray[1][1]))) {
09220 temp = sortarray[1];
09221 sortarray[1] = sortarray[0];
09222 sortarray[0] = temp;
09223 }
09224 return;
09225 }
09226
09227 pivot = (int) randomnation((unsigned int) arraysize);
09228 pivotx = sortarray[pivot][0];
09229 pivoty = sortarray[pivot][1];
09230
09231 left = -1;
09232 right = arraysize;
09233 while (left < right) {
09234
09235 do {
09236 left++;
09237 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
09238 ((sortarray[left][0] == pivotx) &&
09239 (sortarray[left][1] < pivoty))));
09240
09241 do {
09242 right--;
09243 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
09244 ((sortarray[right][0] == pivotx) &&
09245 (sortarray[right][1] > pivoty))));
09246 if (left < right) {
09247
09248 temp = sortarray[left];
09249 sortarray[left] = sortarray[right];
09250 sortarray[right] = temp;
09251 }
09252 }
09253 if (left > 1) {
09254
09255 vertexsort(sortarray, left);
09256 }
09257 if (right < arraysize - 2) {
09258
09259 vertexsort(&sortarray[right + 1], arraysize - right - 1);
09260 }
09261 }
09262
09263
09264
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275 #ifdef ANSI_DECLARATORS
09276 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
09277 #else
09278 void vertexmedian(sortarray, arraysize, median, axis)
09279 vertex *sortarray;
09280 int arraysize;
09281 int median;
09282 int axis;
09283 #endif
09284
09285 {
09286 int left, right;
09287 int pivot;
09288 REAL pivot1, pivot2;
09289 vertex temp;
09290
09291 if (arraysize == 2) {
09292
09293 if ((sortarray[0][axis] > sortarray[1][axis]) ||
09294 ((sortarray[0][axis] == sortarray[1][axis]) &&
09295 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
09296 temp = sortarray[1];
09297 sortarray[1] = sortarray[0];
09298 sortarray[0] = temp;
09299 }
09300 return;
09301 }
09302
09303 pivot = (int) randomnation((unsigned int) arraysize);
09304 pivot1 = sortarray[pivot][axis];
09305 pivot2 = sortarray[pivot][1 - axis];
09306
09307 left = -1;
09308 right = arraysize;
09309 while (left < right) {
09310
09311 do {
09312 left++;
09313 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
09314 ((sortarray[left][axis] == pivot1) &&
09315 (sortarray[left][1 - axis] < pivot2))));
09316
09317 do {
09318 right--;
09319 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
09320 ((sortarray[right][axis] == pivot1) &&
09321 (sortarray[right][1 - axis] > pivot2))));
09322 if (left < right) {
09323
09324 temp = sortarray[left];
09325 sortarray[left] = sortarray[right];
09326 sortarray[right] = temp;
09327 }
09328 }
09329
09330
09331 if (left > median) {
09332
09333 vertexmedian(sortarray, left, median, axis);
09334 }
09335 if (right < median - 1) {
09336
09337 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
09338 median - right - 1, axis);
09339 }
09340 }
09341
09342
09343
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353 #ifdef ANSI_DECLARATORS
09354 void alternateaxes(vertex *sortarray, int arraysize, int axis)
09355 #else
09356 void alternateaxes(sortarray, arraysize, axis)
09357 vertex *sortarray;
09358 int arraysize;
09359 int axis;
09360 #endif
09361
09362 {
09363 int divider;
09364
09365 divider = arraysize >> 1;
09366 if (arraysize <= 3) {
09367
09368
09369 axis = 0;
09370 }
09371
09372 vertexmedian(sortarray, arraysize, divider, axis);
09373
09374 if (arraysize - divider >= 2) {
09375 if (divider >= 2) {
09376 alternateaxes(sortarray, divider, 1 - axis);
09377 }
09378 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
09379 }
09380 }
09381
09382
09383
09384
09385
09386
09387
09388
09389
09390
09391
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417 #ifdef ANSI_DECLARATORS
09418 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
09419 struct otri *innerleft, struct otri *innerright,
09420 struct otri *farright, int axis)
09421 #else
09422 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
09423 struct mesh *m;
09424 struct behavior *b;
09425 struct otri *farleft;
09426 struct otri *innerleft;
09427 struct otri *innerright;
09428 struct otri *farright;
09429 int axis;
09430 #endif
09431
09432 {
09433 struct otri leftcand, rightcand;
09434 struct otri baseedge;
09435 struct otri nextedge;
09436 struct otri sidecasing, topcasing, outercasing;
09437 struct otri checkedge;
09438 vertex innerleftdest;
09439 vertex innerrightorg;
09440 vertex innerleftapex, innerrightapex;
09441 vertex farleftpt, farrightpt;
09442 vertex farleftapex, farrightapex;
09443 vertex lowerleft, lowerright;
09444 vertex upperleft, upperright;
09445 vertex nextapex;
09446 vertex checkvertex;
09447 int changemade;
09448 int badedge;
09449 int leftfinished, rightfinished;
09450 triangle ptr;
09451
09452 dest(*innerleft, innerleftdest);
09453 apex(*innerleft, innerleftapex);
09454 org(*innerright, innerrightorg);
09455 apex(*innerright, innerrightapex);
09456
09457 if (b->dwyer && (axis == 1)) {
09458 org(*farleft, farleftpt);
09459 apex(*farleft, farleftapex);
09460 dest(*farright, farrightpt);
09461 apex(*farright, farrightapex);
09462
09463
09464
09465 while (farleftapex[1] < farleftpt[1]) {
09466 lnextself(*farleft);
09467 symself(*farleft);
09468 farleftpt = farleftapex;
09469 apex(*farleft, farleftapex);
09470 }
09471 sym(*innerleft, checkedge);
09472 apex(checkedge, checkvertex);
09473 while (checkvertex[1] > innerleftdest[1]) {
09474 lnext(checkedge, *innerleft);
09475 innerleftapex = innerleftdest;
09476 innerleftdest = checkvertex;
09477 sym(*innerleft, checkedge);
09478 apex(checkedge, checkvertex);
09479 }
09480 while (innerrightapex[1] < innerrightorg[1]) {
09481 lnextself(*innerright);
09482 symself(*innerright);
09483 innerrightorg = innerrightapex;
09484 apex(*innerright, innerrightapex);
09485 }
09486 sym(*farright, checkedge);
09487 apex(checkedge, checkvertex);
09488 while (checkvertex[1] > farrightpt[1]) {
09489 lnext(checkedge, *farright);
09490 farrightapex = farrightpt;
09491 farrightpt = checkvertex;
09492 sym(*farright, checkedge);
09493 apex(checkedge, checkvertex);
09494 }
09495 }
09496
09497 do {
09498 changemade = 0;
09499
09500 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
09501 0.0) {
09502 lprevself(*innerleft);
09503 symself(*innerleft);
09504 innerleftdest = innerleftapex;
09505 apex(*innerleft, innerleftapex);
09506 changemade = 1;
09507 }
09508
09509 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
09510 0.0) {
09511 lnextself(*innerright);
09512 symself(*innerright);
09513 innerrightorg = innerrightapex;
09514 apex(*innerright, innerrightapex);
09515 changemade = 1;
09516 }
09517 } while (changemade);
09518
09519 sym(*innerleft, leftcand);
09520 sym(*innerright, rightcand);
09521
09522 maketriangle(m, b, &baseedge);
09523
09524 bond(baseedge, *innerleft);
09525 lnextself(baseedge);
09526 bond(baseedge, *innerright);
09527 lnextself(baseedge);
09528 setorg(baseedge, innerrightorg);
09529 setdest(baseedge, innerleftdest);
09530
09531 if (b->verbose > 2) {
09532 printf(" Creating base bounding ");
09533 printtriangle(m, b, &baseedge);
09534 }
09535
09536 org(*farleft, farleftpt);
09537 if (innerleftdest == farleftpt) {
09538 lnext(baseedge, *farleft);
09539 }
09540 dest(*farright, farrightpt);
09541 if (innerrightorg == farrightpt) {
09542 lprev(baseedge, *farright);
09543 }
09544
09545 lowerleft = innerleftdest;
09546 lowerright = innerrightorg;
09547
09548 apex(leftcand, upperleft);
09549 apex(rightcand, upperright);
09550
09551 while (1) {
09552
09553
09554
09555
09556 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
09557 0.0;
09558 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
09559 <= 0.0;
09560 if (leftfinished && rightfinished) {
09561
09562 maketriangle(m, b, &nextedge);
09563 setorg(nextedge, lowerleft);
09564 setdest(nextedge, lowerright);
09565
09566
09567 bond(nextedge, baseedge);
09568 lnextself(nextedge);
09569 bond(nextedge, rightcand);
09570 lnextself(nextedge);
09571 bond(nextedge, leftcand);
09572 if (b->verbose > 2) {
09573 printf(" Creating top bounding ");
09574 printtriangle(m, b, &nextedge);
09575 }
09576
09577 if (b->dwyer && (axis == 1)) {
09578 org(*farleft, farleftpt);
09579 apex(*farleft, farleftapex);
09580 dest(*farright, farrightpt);
09581 apex(*farright, farrightapex);
09582 sym(*farleft, checkedge);
09583 apex(checkedge, checkvertex);
09584
09585
09586
09587 while (checkvertex[0] < farleftpt[0]) {
09588 lprev(checkedge, *farleft);
09589 farleftapex = farleftpt;
09590 farleftpt = checkvertex;
09591 sym(*farleft, checkedge);
09592 apex(checkedge, checkvertex);
09593 }
09594 while (farrightapex[0] > farrightpt[0]) {
09595 lprevself(*farright);
09596 symself(*farright);
09597 farrightpt = farrightapex;
09598 apex(*farright, farrightapex);
09599 }
09600 }
09601 return;
09602 }
09603
09604 if (!leftfinished) {
09605
09606 lprev(leftcand, nextedge);
09607 symself(nextedge);
09608 apex(nextedge, nextapex);
09609
09610
09611 if (nextapex != (vertex) NULL) {
09612
09613 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
09614 0.0;
09615 while (badedge) {
09616
09617
09618 lnextself(nextedge);
09619 sym(nextedge, topcasing);
09620 lnextself(nextedge);
09621 sym(nextedge, sidecasing);
09622 bond(nextedge, topcasing);
09623 bond(leftcand, sidecasing);
09624 lnextself(leftcand);
09625 sym(leftcand, outercasing);
09626 lprevself(nextedge);
09627 bond(nextedge, outercasing);
09628
09629 setorg(leftcand, lowerleft);
09630 setdest(leftcand, NULL);
09631 setapex(leftcand, nextapex);
09632 setorg(nextedge, NULL);
09633 setdest(nextedge, upperleft);
09634 setapex(nextedge, nextapex);
09635
09636 upperleft = nextapex;
09637
09638 otricopy(sidecasing, nextedge);
09639 apex(nextedge, nextapex);
09640 if (nextapex != (vertex) NULL) {
09641
09642 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
09643 nextapex) > 0.0;
09644 } else {
09645
09646 badedge = 0;
09647 }
09648 }
09649 }
09650 }
09651
09652 if (!rightfinished) {
09653
09654 lnext(rightcand, nextedge);
09655 symself(nextedge);
09656 apex(nextedge, nextapex);
09657
09658
09659 if (nextapex != (vertex) NULL) {
09660
09661 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
09662 0.0;
09663 while (badedge) {
09664
09665
09666 lprevself(nextedge);
09667 sym(nextedge, topcasing);
09668 lprevself(nextedge);
09669 sym(nextedge, sidecasing);
09670 bond(nextedge, topcasing);
09671 bond(rightcand, sidecasing);
09672 lprevself(rightcand);
09673 sym(rightcand, outercasing);
09674 lnextself(nextedge);
09675 bond(nextedge, outercasing);
09676
09677 setorg(rightcand, NULL);
09678 setdest(rightcand, lowerright);
09679 setapex(rightcand, nextapex);
09680 setorg(nextedge, upperright);
09681 setdest(nextedge, NULL);
09682 setapex(nextedge, nextapex);
09683
09684 upperright = nextapex;
09685
09686 otricopy(sidecasing, nextedge);
09687 apex(nextedge, nextapex);
09688 if (nextapex != (vertex) NULL) {
09689
09690 badedge = incircle(m, b, lowerleft, lowerright, upperright,
09691 nextapex) > 0.0;
09692 } else {
09693
09694 badedge = 0;
09695 }
09696 }
09697 }
09698 }
09699 if (leftfinished || (!rightfinished &&
09700 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
09701 0.0))) {
09702
09703
09704 bond(baseedge, rightcand);
09705 lprev(rightcand, baseedge);
09706 setdest(baseedge, lowerleft);
09707 lowerright = upperright;
09708 sym(baseedge, rightcand);
09709 apex(rightcand, upperright);
09710 } else {
09711
09712
09713 bond(baseedge, leftcand);
09714 lnext(leftcand, baseedge);
09715 setorg(baseedge, lowerright);
09716 lowerleft = upperleft;
09717 sym(baseedge, leftcand);
09718 apex(leftcand, upperleft);
09719 }
09720 if (b->verbose > 2) {
09721 printf(" Connecting ");
09722 printtriangle(m, b, &baseedge);
09723 }
09724 }
09725 }
09726
09727
09728
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744 #ifdef ANSI_DECLARATORS
09745 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
09746 int vertices, int axis,
09747 struct otri *farleft, struct otri *farright)
09748 #else
09749 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
09750 struct mesh *m;
09751 struct behavior *b;
09752 vertex *sortarray;
09753 int vertices;
09754 int axis;
09755 struct otri *farleft;
09756 struct otri *farright;
09757 #endif
09758
09759 {
09760 struct otri midtri, tri1, tri2, tri3;
09761 struct otri innerleft, innerright;
09762 REAL area;
09763 int divider;
09764
09765 if (b->verbose > 2) {
09766 printf(" Triangulating %d vertices.\n", vertices);
09767 }
09768 if (vertices == 2) {
09769
09770
09771 maketriangle(m, b, farleft);
09772 setorg(*farleft, sortarray[0]);
09773 setdest(*farleft, sortarray[1]);
09774
09775 maketriangle(m, b, farright);
09776 setorg(*farright, sortarray[1]);
09777 setdest(*farright, sortarray[0]);
09778
09779 bond(*farleft, *farright);
09780 lprevself(*farleft);
09781 lnextself(*farright);
09782 bond(*farleft, *farright);
09783 lprevself(*farleft);
09784 lnextself(*farright);
09785 bond(*farleft, *farright);
09786 if (b->verbose > 2) {
09787 printf(" Creating ");
09788 printtriangle(m, b, farleft);
09789 printf(" Creating ");
09790 printtriangle(m, b, farright);
09791 }
09792
09793 lprev(*farright, *farleft);
09794 return;
09795 } else if (vertices == 3) {
09796
09797
09798
09799 maketriangle(m, b, &midtri);
09800 maketriangle(m, b, &tri1);
09801 maketriangle(m, b, &tri2);
09802 maketriangle(m, b, &tri3);
09803 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
09804 if (area == 0.0) {
09805
09806 setorg(midtri, sortarray[0]);
09807 setdest(midtri, sortarray[1]);
09808 setorg(tri1, sortarray[1]);
09809 setdest(tri1, sortarray[0]);
09810 setorg(tri2, sortarray[2]);
09811 setdest(tri2, sortarray[1]);
09812 setorg(tri3, sortarray[1]);
09813 setdest(tri3, sortarray[2]);
09814
09815 bond(midtri, tri1);
09816 bond(tri2, tri3);
09817 lnextself(midtri);
09818 lprevself(tri1);
09819 lnextself(tri2);
09820 lprevself(tri3);
09821 bond(midtri, tri3);
09822 bond(tri1, tri2);
09823 lnextself(midtri);
09824 lprevself(tri1);
09825 lnextself(tri2);
09826 lprevself(tri3);
09827 bond(midtri, tri1);
09828 bond(tri2, tri3);
09829
09830 otricopy(tri1, *farleft);
09831
09832 otricopy(tri2, *farright);
09833 } else {
09834
09835
09836 setorg(midtri, sortarray[0]);
09837 setdest(tri1, sortarray[0]);
09838 setorg(tri3, sortarray[0]);
09839
09840 if (area > 0.0) {
09841
09842 setdest(midtri, sortarray[1]);
09843 setorg(tri1, sortarray[1]);
09844 setdest(tri2, sortarray[1]);
09845 setapex(midtri, sortarray[2]);
09846 setorg(tri2, sortarray[2]);
09847 setdest(tri3, sortarray[2]);
09848 } else {
09849
09850 setdest(midtri, sortarray[2]);
09851 setorg(tri1, sortarray[2]);
09852 setdest(tri2, sortarray[2]);
09853 setapex(midtri, sortarray[1]);
09854 setorg(tri2, sortarray[1]);
09855 setdest(tri3, sortarray[1]);
09856 }
09857
09858 bond(midtri, tri1);
09859 lnextself(midtri);
09860 bond(midtri, tri2);
09861 lnextself(midtri);
09862 bond(midtri, tri3);
09863 lprevself(tri1);
09864 lnextself(tri2);
09865 bond(tri1, tri2);
09866 lprevself(tri1);
09867 lprevself(tri3);
09868 bond(tri1, tri3);
09869 lnextself(tri2);
09870 lprevself(tri3);
09871 bond(tri2, tri3);
09872
09873 otricopy(tri1, *farleft);
09874
09875 if (area > 0.0) {
09876 otricopy(tri2, *farright);
09877 } else {
09878 lnext(*farleft, *farright);
09879 }
09880 }
09881 if (b->verbose > 2) {
09882 printf(" Creating ");
09883 printtriangle(m, b, &midtri);
09884 printf(" Creating ");
09885 printtriangle(m, b, &tri1);
09886 printf(" Creating ");
09887 printtriangle(m, b, &tri2);
09888 printf(" Creating ");
09889 printtriangle(m, b, &tri3);
09890 }
09891 return;
09892 } else {
09893
09894 divider = vertices >> 1;
09895
09896 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
09897 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
09898 &innerright, farright);
09899 if (b->verbose > 1) {
09900 printf(" Joining triangulations with %d and %d vertices.\n", divider,
09901 vertices - divider);
09902 }
09903
09904 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
09905 }
09906 }
09907
09908 #ifdef ANSI_DECLARATORS
09909 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
09910 #else
09911 long removeghosts(m, b, startghost)
09912 struct mesh *m;
09913 struct behavior *b;
09914 struct otri *startghost;
09915 #endif
09916
09917 {
09918 struct otri searchedge;
09919 struct otri dissolveedge;
09920 struct otri deadtriangle;
09921 vertex markorg;
09922 long hullsize;
09923 triangle ptr;
09924
09925 if (b->verbose) {
09926 printf(" Removing ghost triangles.\n");
09927 }
09928
09929 lprev(*startghost, searchedge);
09930 symself(searchedge);
09931 m->dummytri[0] = encode(searchedge);
09932
09933 otricopy(*startghost, dissolveedge);
09934 hullsize = 0;
09935 do {
09936 hullsize++;
09937 lnext(dissolveedge, deadtriangle);
09938 lprevself(dissolveedge);
09939 symself(dissolveedge);
09940
09941
09942 if (!b->poly) {
09943
09944 if (dissolveedge.tri != m->dummytri) {
09945 org(dissolveedge, markorg);
09946 if (vertexmark(markorg) == 0) {
09947 setvertexmark(markorg, 1);
09948 }
09949 }
09950 }
09951
09952 dissolve(dissolveedge);
09953
09954 sym(deadtriangle, dissolveedge);
09955
09956 triangledealloc(m, deadtriangle.tri);
09957 } while (!otriequal(dissolveedge, *startghost));
09958 return hullsize;
09959 }
09960
09961
09962
09963
09964
09965
09966
09967
09968
09969
09970
09971 #ifdef ANSI_DECLARATORS
09972 long divconqdelaunay(struct mesh *m, struct behavior *b)
09973 #else
09974 long divconqdelaunay(m, b)
09975 struct mesh *m;
09976 struct behavior *b;
09977 #endif
09978
09979 {
09980 vertex *sortarray;
09981 struct otri hullleft, hullright;
09982 int divider;
09983 int i, j;
09984
09985 if (b->verbose) {
09986 printf(" Sorting vertices.\n");
09987 }
09988
09989
09990 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
09991 traversalinit(&m->vertices);
09992 for (i = 0; i < m->invertices; i++) {
09993 sortarray[i] = vertextraverse(m);
09994 }
09995
09996 vertexsort(sortarray, m->invertices);
09997
09998 i = 0;
09999 for (j = 1; j < m->invertices; j++) {
10000 if ((sortarray[i][0] == sortarray[j][0])
10001 && (sortarray[i][1] == sortarray[j][1])) {
10002 if (!b->quiet) {
10003 printf(
10004 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10005 sortarray[j][0], sortarray[j][1]);
10006 }
10007 setvertextype(sortarray[j], UNDEADVERTEX);
10008 m->undeads++;
10009 } else {
10010 i++;
10011 sortarray[i] = sortarray[j];
10012 }
10013 }
10014 i++;
10015 if (b->dwyer) {
10016
10017 divider = i >> 1;
10018 if (i - divider >= 2) {
10019 if (divider >= 2) {
10020 alternateaxes(sortarray, divider, 1);
10021 }
10022 alternateaxes(&sortarray[divider], i - divider, 1);
10023 }
10024 }
10025
10026 if (b->verbose) {
10027 printf(" Forming triangulation.\n");
10028 }
10029
10030
10031 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10032 trifree((VOID *) sortarray);
10033
10034 return removeghosts(m, b, &hullleft);
10035 }
10036
10039
10040
10041
10045
10046
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056 #ifndef REDUCED
10057
10058 #ifdef ANSI_DECLARATORS
10059 void boundingbox(struct mesh *m, struct behavior *b)
10060 #else
10061 void boundingbox(m, b)
10062 struct mesh *m;
10063 struct behavior *b;
10064 #endif
10065
10066 {
10067 struct otri inftri;
10068 REAL width;
10069
10070 if (b->verbose) {
10071 printf(" Creating triangular bounding box.\n");
10072 }
10073
10074 width = m->xmax - m->xmin;
10075 if (m->ymax - m->ymin > width) {
10076 width = m->ymax - m->ymin;
10077 }
10078 if (width == 0.0) {
10079 width = 1.0;
10080 }
10081
10082 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10083 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10084 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10085 m->infvertex1[0] = m->xmin - 50.0 * width;
10086 m->infvertex1[1] = m->ymin - 40.0 * width;
10087 m->infvertex2[0] = m->xmax + 50.0 * width;
10088 m->infvertex2[1] = m->ymin - 40.0 * width;
10089 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10090 m->infvertex3[1] = m->ymax + 60.0 * width;
10091
10092
10093 maketriangle(m, b, &inftri);
10094 setorg(inftri, m->infvertex1);
10095 setdest(inftri, m->infvertex2);
10096 setapex(inftri, m->infvertex3);
10097
10098
10099 m->dummytri[0] = (triangle) inftri.tri;
10100 if (b->verbose > 2) {
10101 printf(" Creating ");
10102 printtriangle(m, b, &inftri);
10103 }
10104 }
10105
10106 #endif
10107
10108
10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122 #ifndef REDUCED
10123
10124 #ifdef ANSI_DECLARATORS
10125 long removebox(struct mesh *m, struct behavior *b)
10126 #else
10127 long removebox(m, b)
10128 struct mesh *m;
10129 struct behavior *b;
10130 #endif
10131
10132 {
10133 struct otri deadtriangle;
10134 struct otri searchedge;
10135 struct otri checkedge;
10136 struct otri nextedge, finaledge, dissolveedge;
10137 vertex markorg;
10138 long hullsize;
10139 triangle ptr;
10140
10141 if (b->verbose) {
10142 printf(" Removing triangular bounding box.\n");
10143 }
10144
10145 nextedge.tri = m->dummytri;
10146 nextedge.orient = 0;
10147 symself(nextedge);
10148
10149 lprev(nextedge, finaledge);
10150 lnextself(nextedge);
10151 symself(nextedge);
10152
10153
10154 lprev(nextedge, searchedge);
10155 symself(searchedge);
10156
10157
10158 lnext(nextedge, checkedge);
10159 symself(checkedge);
10160 if (checkedge.tri == m->dummytri) {
10161
10162
10163
10164 lprevself(searchedge);
10165 symself(searchedge);
10166 }
10167
10168
10169 m->dummytri[0] = encode(searchedge);
10170 hullsize = -2l;
10171 while (!otriequal(nextedge, finaledge)) {
10172 hullsize++;
10173 lprev(nextedge, dissolveedge);
10174 symself(dissolveedge);
10175
10176
10177 if (!b->poly) {
10178
10179
10180
10181
10182 if (dissolveedge.tri != m->dummytri) {
10183 org(dissolveedge, markorg);
10184 if (vertexmark(markorg) == 0) {
10185 setvertexmark(markorg, 1);
10186 }
10187 }
10188 }
10189
10190 dissolve(dissolveedge);
10191 lnext(nextedge, deadtriangle);
10192 sym(deadtriangle, nextedge);
10193
10194 triangledealloc(m, deadtriangle.tri);
10195
10196 if (nextedge.tri == m->dummytri) {
10197
10198 otricopy(dissolveedge, nextedge);
10199 }
10200 }
10201 triangledealloc(m, finaledge.tri);
10202
10203 trifree((VOID *) m->infvertex1);
10204 trifree((VOID *) m->infvertex2);
10205 trifree((VOID *) m->infvertex3);
10206
10207 return hullsize;
10208 }
10209
10210 #endif
10211
10212
10213
10214
10215
10216
10217
10218
10219
10220
10221 #ifndef REDUCED
10222
10223 #ifdef ANSI_DECLARATORS
10224 long incrementaldelaunay(struct mesh *m, struct behavior *b)
10225 #else
10226 long incrementaldelaunay(m, b)
10227 struct mesh *m;
10228 struct behavior *b;
10229 #endif
10230
10231 {
10232 struct otri starttri;
10233 vertex vertexloop;
10234
10235
10236 boundingbox(m, b);
10237 if (b->verbose) {
10238 printf(" Incrementally inserting vertices.\n");
10239 }
10240 traversalinit(&m->vertices);
10241 vertexloop = vertextraverse(m);
10242 while (vertexloop != (vertex) NULL) {
10243 starttri.tri = m->dummytri;
10244 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10245 == DUPLICATEVERTEX) {
10246 if (!b->quiet) {
10247 printf(
10248 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10249 vertexloop[0], vertexloop[1]);
10250 }
10251 setvertextype(vertexloop, UNDEADVERTEX);
10252 m->undeads++;
10253 }
10254 vertexloop = vertextraverse(m);
10255 }
10256
10257 return removebox(m, b);
10258 }
10259
10260 #endif
10261
10264
10265
10266
10270 #ifndef REDUCED
10271
10272 #ifdef ANSI_DECLARATORS
10273 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10274 #else
10275 void eventheapinsert(heap, heapsize, newevent)
10276 struct event **heap;
10277 int heapsize;
10278 struct event *newevent;
10279 #endif
10280
10281 {
10282 REAL eventx, eventy;
10283 int eventnum;
10284 int parent;
10285 int notdone;
10286
10287 eventx = newevent->xkey;
10288 eventy = newevent->ykey;
10289 eventnum = heapsize;
10290 notdone = eventnum > 0;
10291 while (notdone) {
10292 parent = (eventnum - 1) >> 1;
10293 if ((heap[parent]->ykey < eventy) ||
10294 ((heap[parent]->ykey == eventy)
10295 && (heap[parent]->xkey <= eventx))) {
10296 notdone = 0;
10297 } else {
10298 heap[eventnum] = heap[parent];
10299 heap[eventnum]->heapposition = eventnum;
10300
10301 eventnum = parent;
10302 notdone = eventnum > 0;
10303 }
10304 }
10305 heap[eventnum] = newevent;
10306 newevent->heapposition = eventnum;
10307 }
10308
10309 #endif
10310
10311 #ifndef REDUCED
10312
10313 #ifdef ANSI_DECLARATORS
10314 void eventheapify(struct event **heap, int heapsize, int eventnum)
10315 #else
10316 void eventheapify(heap, heapsize, eventnum)
10317 struct event **heap;
10318 int heapsize;
10319 int eventnum;
10320 #endif
10321
10322 {
10323 struct event *thisevent;
10324 REAL eventx, eventy;
10325 int leftchild, rightchild;
10326 int smallest;
10327 int notdone;
10328
10329 thisevent = heap[eventnum];
10330 eventx = thisevent->xkey;
10331 eventy = thisevent->ykey;
10332 leftchild = 2 * eventnum + 1;
10333 notdone = leftchild < heapsize;
10334 while (notdone) {
10335 if ((heap[leftchild]->ykey < eventy) ||
10336 ((heap[leftchild]->ykey == eventy)
10337 && (heap[leftchild]->xkey < eventx))) {
10338 smallest = leftchild;
10339 } else {
10340 smallest = eventnum;
10341 }
10342 rightchild = leftchild + 1;
10343 if (rightchild < heapsize) {
10344 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10345 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10346 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10347 smallest = rightchild;
10348 }
10349 }
10350 if (smallest == eventnum) {
10351 notdone = 0;
10352 } else {
10353 heap[eventnum] = heap[smallest];
10354 heap[eventnum]->heapposition = eventnum;
10355 heap[smallest] = thisevent;
10356 thisevent->heapposition = smallest;
10357
10358 eventnum = smallest;
10359 leftchild = 2 * eventnum + 1;
10360 notdone = leftchild < heapsize;
10361 }
10362 }
10363 }
10364
10365 #endif
10366
10367 #ifndef REDUCED
10368
10369 #ifdef ANSI_DECLARATORS
10370 void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10371 #else
10372 void eventheapdelete(heap, heapsize, eventnum)
10373 struct event **heap;
10374 int heapsize;
10375 int eventnum;
10376 #endif
10377
10378 {
10379 struct event *moveevent;
10380 REAL eventx, eventy;
10381 int parent;
10382 int notdone;
10383
10384 moveevent = heap[heapsize - 1];
10385 if (eventnum > 0) {
10386 eventx = moveevent->xkey;
10387 eventy = moveevent->ykey;
10388 do {
10389 parent = (eventnum - 1) >> 1;
10390 if ((heap[parent]->ykey < eventy) ||
10391 ((heap[parent]->ykey == eventy)
10392 && (heap[parent]->xkey <= eventx))) {
10393 notdone = 0;
10394 } else {
10395 heap[eventnum] = heap[parent];
10396 heap[eventnum]->heapposition = eventnum;
10397
10398 eventnum = parent;
10399 notdone = eventnum > 0;
10400 }
10401 } while (notdone);
10402 }
10403 heap[eventnum] = moveevent;
10404 moveevent->heapposition = eventnum;
10405 eventheapify(heap, heapsize - 1, eventnum);
10406 }
10407
10408 #endif
10409
10410 #ifndef REDUCED
10411
10412 #ifdef ANSI_DECLARATORS
10413 void createeventheap(struct mesh *m, struct event ***eventheap,
10414 struct event **events, struct event **freeevents)
10415 #else
10416 void createeventheap(m, eventheap, events, freeevents)
10417 struct mesh *m;
10418 struct event ***eventheap;
10419 struct event **events;
10420 struct event **freeevents;
10421 #endif
10422
10423 {
10424 vertex thisvertex;
10425 int maxevents;
10426 int i;
10427
10428 maxevents = (3 * m->invertices) / 2;
10429 *eventheap = (struct event **) trimalloc(maxevents *
10430 (int) sizeof(struct event *));
10431 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10432 traversalinit(&m->vertices);
10433 for (i = 0; i < m->invertices; i++) {
10434 thisvertex = vertextraverse(m);
10435 (*events)[i].eventptr = (VOID *) thisvertex;
10436 (*events)[i].xkey = thisvertex[0];
10437 (*events)[i].ykey = thisvertex[1];
10438 eventheapinsert(*eventheap, i, *events + i);
10439 }
10440 *freeevents = (struct event *) NULL;
10441 for (i = maxevents - 1; i >= m->invertices; i--) {
10442 (*events)[i].eventptr = (VOID *) *freeevents;
10443 *freeevents = *events + i;
10444 }
10445 }
10446
10447 #endif
10448
10449 #ifndef REDUCED
10450
10451 #ifdef ANSI_DECLARATORS
10452 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10453 #else
10454 int rightofhyperbola(m, fronttri, newsite)
10455 struct mesh *m;
10456 struct otri *fronttri;
10457 vertex newsite;
10458 #endif
10459
10460 {
10461 vertex leftvertex, rightvertex;
10462 REAL dxa, dya, dxb, dyb;
10463
10464 m->hyperbolacount++;
10465
10466 dest(*fronttri, leftvertex);
10467 apex(*fronttri, rightvertex);
10468 if ((leftvertex[1] < rightvertex[1]) ||
10469 ((leftvertex[1] == rightvertex[1]) &&
10470 (leftvertex[0] < rightvertex[0]))) {
10471 if (newsite[0] >= rightvertex[0]) {
10472 return 1;
10473 }
10474 } else {
10475 if (newsite[0] <= leftvertex[0]) {
10476 return 0;
10477 }
10478 }
10479 dxa = leftvertex[0] - newsite[0];
10480 dya = leftvertex[1] - newsite[1];
10481 dxb = rightvertex[0] - newsite[0];
10482 dyb = rightvertex[1] - newsite[1];
10483 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10484 }
10485
10486 #endif
10487
10488 #ifndef REDUCED
10489
10490 #ifdef ANSI_DECLARATORS
10491 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10492 #else
10493 REAL circletop(m, pa, pb, pc, ccwabc)
10494 struct mesh *m;
10495 vertex pa;
10496 vertex pb;
10497 vertex pc;
10498 REAL ccwabc;
10499 #endif
10500
10501 {
10502 REAL xac, yac, xbc, ybc, xab, yab;
10503 REAL aclen2, bclen2, ablen2;
10504
10505 m->circletopcount++;
10506
10507 xac = pa[0] - pc[0];
10508 yac = pa[1] - pc[1];
10509 xbc = pb[0] - pc[0];
10510 ybc = pb[1] - pc[1];
10511 xab = pa[0] - pb[0];
10512 yab = pa[1] - pb[1];
10513 aclen2 = xac * xac + yac * yac;
10514 bclen2 = xbc * xbc + ybc * ybc;
10515 ablen2 = xab * xab + yab * yab;
10516 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10517 / (2.0 * ccwabc);
10518 }
10519
10520 #endif
10521
10522 #ifndef REDUCED
10523
10524 #ifdef ANSI_DECLARATORS
10525 void check4deadevent(struct otri *checktri, struct event **freeevents,
10526 struct event **eventheap, int *heapsize)
10527 #else
10528 void check4deadevent(checktri, freeevents, eventheap, heapsize)
10529 struct otri *checktri;
10530 struct event **freeevents;
10531 struct event **eventheap;
10532 int *heapsize;
10533 #endif
10534
10535 {
10536 struct event *deadevent;
10537 vertex eventvertex;
10538 int eventnum;
10539
10540 org(*checktri, eventvertex);
10541 if (eventvertex != (vertex) NULL) {
10542 deadevent = (struct event *) eventvertex;
10543 eventnum = deadevent->heapposition;
10544 deadevent->eventptr = (VOID *) *freeevents;
10545 *freeevents = deadevent;
10546 eventheapdelete(eventheap, *heapsize, eventnum);
10547 (*heapsize)--;
10548 setorg(*checktri, NULL);
10549 }
10550 }
10551
10552 #endif
10553
10554 #ifndef REDUCED
10555
10556 #ifdef ANSI_DECLARATORS
10557 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10558 vertex searchpoint, struct otri *searchtri)
10559 #else
10560 struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10561 struct mesh *m;
10562 struct splaynode *splaytree;
10563 vertex searchpoint;
10564 struct otri *searchtri;
10565 #endif
10566
10567 {
10568 struct splaynode *child, *grandchild;
10569 struct splaynode *lefttree, *righttree;
10570 struct splaynode *leftright;
10571 vertex checkvertex;
10572 int rightofroot, rightofchild;
10573
10574 if (splaytree == (struct splaynode *) NULL) {
10575 return (struct splaynode *) NULL;
10576 }
10577 dest(splaytree->keyedge, checkvertex);
10578 if (checkvertex == splaytree->keydest) {
10579 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10580 if (rightofroot) {
10581 otricopy(splaytree->keyedge, *searchtri);
10582 child = splaytree->rchild;
10583 } else {
10584 child = splaytree->lchild;
10585 }
10586 if (child == (struct splaynode *) NULL) {
10587 return splaytree;
10588 }
10589 dest(child->keyedge, checkvertex);
10590 if (checkvertex != child->keydest) {
10591 child = splay(m, child, searchpoint, searchtri);
10592 if (child == (struct splaynode *) NULL) {
10593 if (rightofroot) {
10594 splaytree->rchild = (struct splaynode *) NULL;
10595 } else {
10596 splaytree->lchild = (struct splaynode *) NULL;
10597 }
10598 return splaytree;
10599 }
10600 }
10601 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10602 if (rightofchild) {
10603 otricopy(child->keyedge, *searchtri);
10604 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10605 child->rchild = grandchild;
10606 } else {
10607 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10608 child->lchild = grandchild;
10609 }
10610 if (grandchild == (struct splaynode *) NULL) {
10611 if (rightofroot) {
10612 splaytree->rchild = child->lchild;
10613 child->lchild = splaytree;
10614 } else {
10615 splaytree->lchild = child->rchild;
10616 child->rchild = splaytree;
10617 }
10618 return child;
10619 }
10620 if (rightofchild) {
10621 if (rightofroot) {
10622 splaytree->rchild = child->lchild;
10623 child->lchild = splaytree;
10624 } else {
10625 splaytree->lchild = grandchild->rchild;
10626 grandchild->rchild = splaytree;
10627 }
10628 child->rchild = grandchild->lchild;
10629 grandchild->lchild = child;
10630 } else {
10631 if (rightofroot) {
10632 splaytree->rchild = grandchild->lchild;
10633 grandchild->lchild = splaytree;
10634 } else {
10635 splaytree->lchild = child->rchild;
10636 child->rchild = splaytree;
10637 }
10638 child->lchild = grandchild->rchild;
10639 grandchild->rchild = child;
10640 }
10641 return grandchild;
10642 } else {
10643 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10644 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10645
10646 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10647 if (lefttree == (struct splaynode *) NULL) {
10648 return righttree;
10649 } else if (righttree == (struct splaynode *) NULL) {
10650 return lefttree;
10651 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10652 lefttree->rchild = righttree->lchild;
10653 righttree->lchild = lefttree;
10654 return righttree;
10655 } else if (righttree->lchild == (struct splaynode *) NULL) {
10656 righttree->lchild = lefttree->rchild;
10657 lefttree->rchild = righttree;
10658 return lefttree;
10659 } else {
10660
10661 leftright = lefttree->rchild;
10662 while (leftright->rchild != (struct splaynode *) NULL) {
10663 leftright = leftright->rchild;
10664 }
10665 leftright->rchild = righttree;
10666 return lefttree;
10667 }
10668 }
10669 }
10670
10671 #endif
10672
10673 #ifndef REDUCED
10674
10675 #ifdef ANSI_DECLARATORS
10676 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10677 struct otri *newkey, vertex searchpoint)
10678 #else
10679 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10680 struct mesh *m;
10681 struct splaynode *splayroot;
10682 struct otri *newkey;
10683 vertex searchpoint;
10684 #endif
10685
10686 {
10687 struct splaynode *newsplaynode;
10688
10689 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10690 otricopy(*newkey, newsplaynode->keyedge);
10691 dest(*newkey, newsplaynode->keydest);
10692 if (splayroot == (struct splaynode *) NULL) {
10693 newsplaynode->lchild = (struct splaynode *) NULL;
10694 newsplaynode->rchild = (struct splaynode *) NULL;
10695 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10696 newsplaynode->lchild = splayroot;
10697 newsplaynode->rchild = splayroot->rchild;
10698 splayroot->rchild = (struct splaynode *) NULL;
10699 } else {
10700 newsplaynode->lchild = splayroot->lchild;
10701 newsplaynode->rchild = splayroot;
10702 splayroot->lchild = (struct splaynode *) NULL;
10703 }
10704 return newsplaynode;
10705 }
10706
10707 #endif
10708
10709 #ifndef REDUCED
10710
10711 #ifdef ANSI_DECLARATORS
10712 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10713 struct splaynode *splayroot,
10714 struct otri *newkey,
10715 vertex pa, vertex pb, vertex pc, REAL topy)
10716 #else
10717 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10718 struct mesh *m;
10719 struct behavior *b;
10720 struct splaynode *splayroot;
10721 struct otri *newkey;
10722 vertex pa;
10723 vertex pb;
10724 vertex pc;
10725 REAL topy;
10726 #endif
10727
10728 {
10729 REAL ccwabc;
10730 REAL xac, yac, xbc, ybc;
10731 REAL aclen2, bclen2;
10732 REAL searchpoint[2];
10733 struct otri dummytri;
10734
10735 ccwabc = counterclockwise(m, b, pa, pb, pc);
10736 xac = pa[0] - pc[0];
10737 yac = pa[1] - pc[1];
10738 xbc = pb[0] - pc[0];
10739 ybc = pb[1] - pc[1];
10740 aclen2 = xac * xac + yac * yac;
10741 bclen2 = xbc * xbc + ybc * ybc;
10742 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10743 searchpoint[1] = topy;
10744 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10745 newkey, (vertex) searchpoint);
10746 }
10747
10748 #endif
10749
10750 #ifndef REDUCED
10751
10752 #ifdef ANSI_DECLARATORS
10753 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10754 struct otri *bottommost, vertex searchvertex,
10755 struct otri *searchtri, int *farright)
10756 #else
10757 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10758 searchtri, farright)
10759 struct mesh *m;
10760 struct splaynode *splayroot;
10761 struct otri *bottommost;
10762 vertex searchvertex;
10763 struct otri *searchtri;
10764 int *farright;
10765 #endif
10766
10767 {
10768 int farrightflag;
10769 triangle ptr;
10770
10771 otricopy(*bottommost, *searchtri);
10772 splayroot = splay(m, splayroot, searchvertex, searchtri);
10773
10774 farrightflag = 0;
10775 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10776 onextself(*searchtri);
10777 farrightflag = otriequal(*searchtri, *bottommost);
10778 }
10779 *farright = farrightflag;
10780 return splayroot;
10781 }
10782
10783 #endif
10784
10785 #ifndef REDUCED
10786
10787 #ifdef ANSI_DECLARATORS
10788 long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10789 #else
10790 long sweeplinedelaunay(m, b)
10791 struct mesh *m;
10792 struct behavior *b;
10793 #endif
10794
10795 {
10796 struct event **eventheap;
10797 struct event *events;
10798 struct event *freeevents;
10799 struct event *nextevent;
10800 struct event *newevent;
10801 struct splaynode *splayroot;
10802 struct otri bottommost;
10803 struct otri searchtri;
10804 struct otri fliptri;
10805 struct otri lefttri, righttri, farlefttri, farrighttri;
10806 struct otri inserttri;
10807 vertex firstvertex, secondvertex;
10808 vertex nextvertex, lastvertex;
10809 vertex connectvertex;
10810 vertex leftvertex, midvertex, rightvertex;
10811 REAL lefttest, righttest;
10812 int heapsize;
10813 int check4events, farrightflag;
10814 triangle ptr;
10815
10816 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10817 SPLAYNODEPERBLOCK, 0);
10818 splayroot = (struct splaynode *) NULL;
10819
10820 if (b->verbose) {
10821 printf(" Placing vertices in event heap.\n");
10822 }
10823 createeventheap(m, &eventheap, &events, &freeevents);
10824 heapsize = m->invertices;
10825
10826 if (b->verbose) {
10827 printf(" Forming triangulation.\n");
10828 }
10829 maketriangle(m, b, &lefttri);
10830 maketriangle(m, b, &righttri);
10831 bond(lefttri, righttri);
10832 lnextself(lefttri);
10833 lprevself(righttri);
10834 bond(lefttri, righttri);
10835 lnextself(lefttri);
10836 lprevself(righttri);
10837 bond(lefttri, righttri);
10838 firstvertex = (vertex) eventheap[0]->eventptr;
10839 eventheap[0]->eventptr = (VOID *) freeevents;
10840 freeevents = eventheap[0];
10841 eventheapdelete(eventheap, heapsize, 0);
10842 heapsize--;
10843 do {
10844 if (heapsize == 0) {
10845 printf("Error: Input vertices are all identical.\n");
10846 triexit(1);
10847 }
10848 secondvertex = (vertex) eventheap[0]->eventptr;
10849 eventheap[0]->eventptr = (VOID *) freeevents;
10850 freeevents = eventheap[0];
10851 eventheapdelete(eventheap, heapsize, 0);
10852 heapsize--;
10853 if ((firstvertex[0] == secondvertex[0]) &&
10854 (firstvertex[1] == secondvertex[1])) {
10855 if (!b->quiet) {
10856 printf(
10857 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10858 secondvertex[0], secondvertex[1]);
10859 }
10860 setvertextype(secondvertex, UNDEADVERTEX);
10861 m->undeads++;
10862 }
10863 } while ((firstvertex[0] == secondvertex[0]) &&
10864 (firstvertex[1] == secondvertex[1]));
10865 setorg(lefttri, firstvertex);
10866 setdest(lefttri, secondvertex);
10867 setorg(righttri, secondvertex);
10868 setdest(righttri, firstvertex);
10869 lprev(lefttri, bottommost);
10870 lastvertex = secondvertex;
10871 while (heapsize > 0) {
10872 nextevent = eventheap[0];
10873 eventheapdelete(eventheap, heapsize, 0);
10874 heapsize--;
10875 check4events = 1;
10876 if (nextevent->xkey < m->xmin) {
10877 decode(nextevent->eventptr, fliptri);
10878 oprev(fliptri, farlefttri);
10879 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10880 onext(fliptri, farrighttri);
10881 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10882
10883 if (otriequal(farlefttri, bottommost)) {
10884 lprev(fliptri, bottommost);
10885 }
10886 flip(m, b, &fliptri);
10887 setapex(fliptri, NULL);
10888 lprev(fliptri, lefttri);
10889 lnext(fliptri, righttri);
10890 sym(lefttri, farlefttri);
10891
10892 if (randomnation(SAMPLERATE) == 0) {
10893 symself(fliptri);
10894 dest(fliptri, leftvertex);
10895 apex(fliptri, midvertex);
10896 org(fliptri, rightvertex);
10897 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10898 midvertex, rightvertex, nextevent->ykey);
10899 }
10900 } else {
10901 nextvertex = (vertex) nextevent->eventptr;
10902 if ((nextvertex[0] == lastvertex[0]) &&
10903 (nextvertex[1] == lastvertex[1])) {
10904 if (!b->quiet) {
10905 printf(
10906 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10907 nextvertex[0], nextvertex[1]);
10908 }
10909 setvertextype(nextvertex, UNDEADVERTEX);
10910 m->undeads++;
10911 check4events = 0;
10912 } else {
10913 lastvertex = nextvertex;
10914
10915 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10916 &searchtri, &farrightflag);
10917
10918
10919
10920
10921
10922
10923
10924
10925
10926 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10927
10928 otricopy(searchtri, farrighttri);
10929 sym(searchtri, farlefttri);
10930 maketriangle(m, b, &lefttri);
10931 maketriangle(m, b, &righttri);
10932 dest(farrighttri, connectvertex);
10933 setorg(lefttri, connectvertex);
10934 setdest(lefttri, nextvertex);
10935 setorg(righttri, nextvertex);
10936 setdest(righttri, connectvertex);
10937 bond(lefttri, righttri);
10938 lnextself(lefttri);
10939 lprevself(righttri);
10940 bond(lefttri, righttri);
10941 lnextself(lefttri);
10942 lprevself(righttri);
10943 bond(lefttri, farlefttri);
10944 bond(righttri, farrighttri);
10945 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10946 otricopy(lefttri, bottommost);
10947 }
10948
10949 if (randomnation(SAMPLERATE) == 0) {
10950 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10951 } else if (randomnation(SAMPLERATE) == 0) {
10952 lnext(righttri, inserttri);
10953 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10954 }
10955 }
10956 }
10957 nextevent->eventptr = (VOID *) freeevents;
10958 freeevents = nextevent;
10959
10960 if (check4events) {
10961 apex(farlefttri, leftvertex);
10962 dest(lefttri, midvertex);
10963 apex(lefttri, rightvertex);
10964 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10965 if (lefttest > 0.0) {
10966 newevent = freeevents;
10967 freeevents = (struct event *) freeevents->eventptr;
10968 newevent->xkey = m->xminextreme;
10969 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10970 lefttest);
10971 newevent->eventptr = (VOID *) encode(lefttri);
10972 eventheapinsert(eventheap, heapsize, newevent);
10973 heapsize++;
10974 setorg(lefttri, newevent);
10975 }
10976 apex(righttri, leftvertex);
10977 org(righttri, midvertex);
10978 apex(farrighttri, rightvertex);
10979 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10980 if (righttest > 0.0) {
10981 newevent = freeevents;
10982 freeevents = (struct event *) freeevents->eventptr;
10983 newevent->xkey = m->xminextreme;
10984 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10985 righttest);
10986 newevent->eventptr = (VOID *) encode(farrighttri);
10987 eventheapinsert(eventheap, heapsize, newevent);
10988 heapsize++;
10989 setorg(farrighttri, newevent);
10990 }
10991 }
10992 }
10993
10994 pooldeinit(&m->splaynodes);
10995 lprevself(bottommost);
10996 return removeghosts(m, b, &bottommost);
10997 }
10998
10999 #endif
11000
11003
11004
11005
11009
11010
11011
11012
11013
11014
11015 #ifdef ANSI_DECLARATORS
11016 long delaunay(struct mesh *m, struct behavior *b)
11017 #else
11018 long delaunay(m, b)
11019 struct mesh *m;
11020 struct behavior *b;
11021 #endif
11022
11023 {
11024 long hulledges;
11025
11026 m->eextras = 0;
11027 initializetrisubpools(m, b);
11028
11029 #ifdef REDUCED
11030 if (!b->quiet) {
11031 printf(
11032 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11033 }
11034 hulledges = divconqdelaunay(m, b);
11035 #else
11036 if (!b->quiet) {
11037 printf("Constructing Delaunay triangulation ");
11038 if (b->incremental) {
11039 printf("by incremental method.\n");
11040 } else if (b->sweepline) {
11041 printf("by sweepline method.\n");
11042 } else {
11043 printf("by divide-and-conquer method.\n");
11044 }
11045 }
11046 if (b->incremental) {
11047 hulledges = incrementaldelaunay(m, b);
11048 } else if (b->sweepline) {
11049 hulledges = sweeplinedelaunay(m, b);
11050 } else {
11051 hulledges = divconqdelaunay(m, b);
11052 }
11053 #endif
11054
11055 if (m->triangles.items == 0) {
11056
11057 return 0l;
11058 } else {
11059 return hulledges;
11060 }
11061 }
11062
11063
11064
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088 #ifndef CDT_ONLY
11089
11090 #ifdef TRILIBRARY
11091
11092 #ifdef ANSI_DECLARATORS
11093 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11094 REAL *triangleattriblist, REAL *trianglearealist,
11095 int elements, int corners, int attribs,
11096 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11097 #else
11098 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11099 elements, corners, attribs, segmentlist, segmentmarkerlist,
11100 numberofsegments)
11101 struct mesh *m;
11102 struct behavior *b;
11103 int *trianglelist;
11104 REAL *triangleattriblist;
11105 REAL *trianglearealist;
11106 int elements;
11107 int corners;
11108 int attribs;
11109 int *segmentlist;
11110 int *segmentmarkerlist;
11111 int numberofsegments;
11112 #endif
11113
11114 #else
11115
11116 #ifdef ANSI_DECLARATORS
11117 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11118 char *areafilename, char *polyfilename, FILE *polyfile)
11119 #else
11120 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11121 struct mesh *m;
11122 struct behavior *b;
11123 char *elefilename;
11124 char *areafilename;
11125 char *polyfilename;
11126 FILE *polyfile;
11127 #endif
11128
11129 #endif
11130
11131 {
11132 #ifdef TRILIBRARY
11133 int vertexindex;
11134 int attribindex;
11135 #else
11136 FILE *elefile;
11137 FILE *areafile;
11138 char inputline[INPUTLINESIZE];
11139 char *stringptr;
11140 int areaelements;
11141 #endif
11142 struct otri triangleloop;
11143 struct otri triangleleft;
11144 struct otri checktri;
11145 struct otri checkleft;
11146 struct otri checkneighbor;
11147 struct osub subsegloop;
11148 triangle *vertexarray;
11149 triangle *prevlink;
11150 triangle nexttri;
11151 vertex tdest, tapex;
11152 vertex checkdest, checkapex;
11153 vertex shorg;
11154 vertex killvertex;
11155 vertex segmentorg, segmentdest;
11156 REAL area;
11157 int corner[3];
11158 int end[2];
11159 int killvertexindex;
11160 int incorners;
11161 int segmentmarkers;
11162 int boundmarker;
11163 int aroundvertex;
11164 long hullsize;
11165 int notfound;
11166 long elementnumber, segmentnumber;
11167 int i, j;
11168 triangle ptr;
11169
11170 #ifdef TRILIBRARY
11171 m->inelements = elements;
11172 incorners = corners;
11173 if (incorners < 3) {
11174 printf("Error: Triangles must have at least 3 vertices.\n");
11175 triexit(1);
11176 }
11177 m->eextras = attribs;
11178 #else
11179
11180 if (!b->quiet) {
11181 printf("Opening %s.\n", elefilename);
11182 }
11183 elefile = fopen(elefilename, "r");
11184 if (elefile == (FILE *) NULL) {
11185 printf(" Error: Cannot access file %s.\n", elefilename);
11186 triexit(1);
11187 }
11188
11189
11190 stringptr = readline(inputline, elefile, elefilename);
11191 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11192 stringptr = findfield(stringptr);
11193 if (*stringptr == '\0') {
11194 incorners = 3;
11195 } else {
11196 incorners = (int) strtol(stringptr, &stringptr, 0);
11197 if (incorners < 3) {
11198 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11199 elefilename);
11200 triexit(1);
11201 }
11202 }
11203 stringptr = findfield(stringptr);
11204 if (*stringptr == '\0') {
11205 m->eextras = 0;
11206 } else {
11207 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11208 }
11209 #endif
11210
11211 initializetrisubpools(m, b);
11212
11213
11214 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11215 maketriangle(m, b, &triangleloop);
11216
11217 triangleloop.tri[3] = (triangle) triangleloop.tri;
11218 }
11219
11220 segmentmarkers = 0;
11221 if (b->poly) {
11222 #ifdef TRILIBRARY
11223 m->insegments = numberofsegments;
11224 segmentmarkers = segmentmarkerlist != (int *) NULL;
11225 #else
11226
11227
11228 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11229 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11230 stringptr = findfield(stringptr);
11231 if (*stringptr != '\0') {
11232 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11233 }
11234 #endif
11235
11236
11237 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11238 makesubseg(m, &subsegloop);
11239
11240 subsegloop.ss[2] = (subseg) subsegloop.ss;
11241 }
11242 }
11243
11244 #ifdef TRILIBRARY
11245 vertexindex = 0;
11246 attribindex = 0;
11247 #else
11248 if (b->vararea) {
11249
11250 if (!b->quiet) {
11251 printf("Opening %s.\n", areafilename);
11252 }
11253 areafile = fopen(areafilename, "r");
11254 if (areafile == (FILE *) NULL) {
11255 printf(" Error: Cannot access file %s.\n", areafilename);
11256 triexit(1);
11257 }
11258 stringptr = readline(inputline, areafile, areafilename);
11259 areaelements = (int) strtol(stringptr, &stringptr, 0);
11260 if (areaelements != m->inelements) {
11261 printf("Error: %s and %s disagree on number of triangles.\n",
11262 elefilename, areafilename);
11263 triexit(1);
11264 }
11265 }
11266 #endif
11267
11268 if (!b->quiet) {
11269 printf("Reconstructing mesh.\n");
11270 }
11271
11272
11273
11274 vertexarray = (triangle *) trimalloc(m->vertices.items *
11275 (int) sizeof(triangle));
11276
11277 for (i = 0; i < m->vertices.items; i++) {
11278 vertexarray[i] = (triangle) m->dummytri;
11279 }
11280
11281 if (b->verbose) {
11282 printf(" Assembling triangles.\n");
11283 }
11284
11285
11286 traversalinit(&m->triangles);
11287 triangleloop.tri = triangletraverse(m);
11288 elementnumber = b->firstnumber;
11289 while (triangleloop.tri != (triangle *) NULL) {
11290 #ifdef TRILIBRARY
11291
11292 for (j = 0; j < 3; j++) {
11293 corner[j] = trianglelist[vertexindex++];
11294 if ((corner[j] < b->firstnumber) ||
11295 (corner[j] >= b->firstnumber + m->invertices)) {
11296 printf("Error: Triangle %ld has an invalid vertex index.\n",
11297 elementnumber);
11298 triexit(1);
11299 }
11300 }
11301 #else
11302
11303 stringptr = readline(inputline, elefile, elefilename);
11304 for (j = 0; j < 3; j++) {
11305 stringptr = findfield(stringptr);
11306 if (*stringptr == '\0') {
11307 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11308 elementnumber, j + 1, elefilename);
11309 triexit(1);
11310 } else {
11311 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11312 if ((corner[j] < b->firstnumber) ||
11313 (corner[j] >= b->firstnumber + m->invertices)) {
11314 printf("Error: Triangle %ld has an invalid vertex index.\n",
11315 elementnumber);
11316 triexit(1);
11317 }
11318 }
11319 }
11320 #endif
11321
11322
11323 for (j = 3; j < incorners; j++) {
11324 #ifdef TRILIBRARY
11325 killvertexindex = trianglelist[vertexindex++];
11326 #else
11327 stringptr = findfield(stringptr);
11328 if (*stringptr != '\0') {
11329 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11330 #endif
11331 if ((killvertexindex >= b->firstnumber) &&
11332 (killvertexindex < b->firstnumber + m->invertices)) {
11333
11334 killvertex = getvertex(m, b, killvertexindex);
11335 if (vertextype(killvertex) != DEADVERTEX) {
11336 vertexdealloc(m, killvertex);
11337 }
11338 }
11339 #ifndef TRILIBRARY
11340 }
11341 #endif
11342 }
11343
11344
11345 for (j = 0; j < m->eextras; j++) {
11346 #ifdef TRILIBRARY
11347 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11348 #else
11349 stringptr = findfield(stringptr);
11350 if (*stringptr == '\0') {
11351 setelemattribute(triangleloop, j, 0);
11352 } else {
11353 setelemattribute(triangleloop, j,
11354 (REAL) strtod(stringptr, &stringptr));
11355 }
11356 #endif
11357 }
11358
11359 if (b->vararea) {
11360 #ifdef TRILIBRARY
11361 area = trianglearealist[elementnumber - b->firstnumber];
11362 #else
11363
11364 stringptr = readline(inputline, areafile, areafilename);
11365 stringptr = findfield(stringptr);
11366 if (*stringptr == '\0') {
11367 area = -1.0;
11368 } else {
11369 area = (REAL) strtod(stringptr, &stringptr);
11370 }
11371 #endif
11372 setareabound(triangleloop, area);
11373 }
11374
11375
11376 triangleloop.orient = 0;
11377 setorg(triangleloop, getvertex(m, b, corner[0]));
11378 setdest(triangleloop, getvertex(m, b, corner[1]));
11379 setapex(triangleloop, getvertex(m, b, corner[2]));
11380
11381 for (triangleloop.orient = 0; triangleloop.orient < 3;
11382 triangleloop.orient++) {
11383
11384 aroundvertex = corner[triangleloop.orient];
11385
11386 nexttri = vertexarray[aroundvertex - b->firstnumber];
11387
11388 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11389
11390 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11391 decode(nexttri, checktri);
11392 if (checktri.tri != m->dummytri) {
11393 dest(triangleloop, tdest);
11394 apex(triangleloop, tapex);
11395
11396 do {
11397 dest(checktri, checkdest);
11398 apex(checktri, checkapex);
11399 if (tapex == checkdest) {
11400
11401 lprev(triangleloop, triangleleft);
11402 bond(triangleleft, checktri);
11403 }
11404 if (tdest == checkapex) {
11405
11406 lprev(checktri, checkleft);
11407 bond(triangleloop, checkleft);
11408 }
11409
11410 nexttri = checktri.tri[6 + checktri.orient];
11411 decode(nexttri, checktri);
11412 } while (checktri.tri != m->dummytri);
11413 }
11414 }
11415 triangleloop.tri = triangletraverse(m);
11416 elementnumber++;
11417 }
11418
11419 #ifdef TRILIBRARY
11420 vertexindex = 0;
11421 #else
11422 fclose(elefile);
11423 if (b->vararea) {
11424 fclose(areafile);
11425 }
11426 #endif
11427
11428 hullsize = 0;
11429 if (b->poly) {
11430 if (b->verbose) {
11431 printf(" Marking segments in triangulation.\n");
11432 }
11433
11434
11435 boundmarker = 0;
11436 traversalinit(&m->subsegs);
11437 subsegloop.ss = subsegtraverse(m);
11438 segmentnumber = b->firstnumber;
11439 while (subsegloop.ss != (subseg *) NULL) {
11440 #ifdef TRILIBRARY
11441 end[0] = segmentlist[vertexindex++];
11442 end[1] = segmentlist[vertexindex++];
11443 if (segmentmarkers) {
11444 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11445 }
11446 #else
11447
11448 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11449
11450 stringptr = findfield(stringptr);
11451 if (*stringptr == '\0') {
11452 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11453 polyfilename);
11454 triexit(1);
11455 } else {
11456 end[0] = (int) strtol(stringptr, &stringptr, 0);
11457 }
11458 stringptr = findfield(stringptr);
11459 if (*stringptr == '\0') {
11460 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11461 segmentnumber, polyfilename);
11462 triexit(1);
11463 } else {
11464 end[1] = (int) strtol(stringptr, &stringptr, 0);
11465 }
11466 if (segmentmarkers) {
11467 stringptr = findfield(stringptr);
11468 if (*stringptr == '\0') {
11469 boundmarker = 0;
11470 } else {
11471 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11472 }
11473 }
11474 #endif
11475 for (j = 0; j < 2; j++) {
11476 if ((end[j] < b->firstnumber) ||
11477 (end[j] >= b->firstnumber + m->invertices)) {
11478 printf("Error: Segment %ld has an invalid vertex index.\n",
11479 segmentnumber);
11480 triexit(1);
11481 }
11482 }
11483
11484
11485 subsegloop.ssorient = 0;
11486 segmentorg = getvertex(m, b, end[0]);
11487 segmentdest = getvertex(m, b, end[1]);
11488 setsorg(subsegloop, segmentorg);
11489 setsdest(subsegloop, segmentdest);
11490 setsegorg(subsegloop, segmentorg);
11491 setsegdest(subsegloop, segmentdest);
11492 setmark(subsegloop, boundmarker);
11493
11494 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11495 subsegloop.ssorient++) {
11496
11497 aroundvertex = end[1 - subsegloop.ssorient];
11498
11499 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11500 nexttri = vertexarray[aroundvertex - b->firstnumber];
11501 decode(nexttri, checktri);
11502 sorg(subsegloop, shorg);
11503 notfound = 1;
11504
11505
11506
11507
11508
11509
11510
11511 while (notfound && (checktri.tri != m->dummytri)) {
11512 dest(checktri, checkdest);
11513 if (shorg == checkdest) {
11514
11515 *prevlink = checktri.tri[6 + checktri.orient];
11516
11517 tsbond(checktri, subsegloop);
11518
11519 sym(checktri, checkneighbor);
11520 if (checkneighbor.tri == m->dummytri) {
11521
11522
11523
11524 insertsubseg(m, b, &checktri, 1);
11525 hullsize++;
11526 }
11527 notfound = 0;
11528 }
11529
11530 prevlink = &checktri.tri[6 + checktri.orient];
11531 nexttri = checktri.tri[6 + checktri.orient];
11532 decode(nexttri, checktri);
11533 }
11534 }
11535 subsegloop.ss = subsegtraverse(m);
11536 segmentnumber++;
11537 }
11538 }
11539
11540
11541
11542 for (i = 0; i < m->vertices.items; i++) {
11543
11544 nexttri = vertexarray[i];
11545 decode(nexttri, checktri);
11546 while (checktri.tri != m->dummytri) {
11547
11548
11549 nexttri = checktri.tri[6 + checktri.orient];
11550
11551 tsdissolve(checktri);
11552 sym(checktri, checkneighbor);
11553 if (checkneighbor.tri == m->dummytri) {
11554 insertsubseg(m, b, &checktri, 1);
11555 hullsize++;
11556 }
11557 decode(nexttri, checktri);
11558 }
11559 }
11560
11561 trifree((VOID *) vertexarray);
11562 return hullsize;
11563 }
11564
11565 #endif
11566
11569
11570
11571
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592 #ifdef ANSI_DECLARATORS
11593 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11594 struct otri *searchtri,
11595 vertex searchpoint)
11596 #else
11597 enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11598 struct mesh *m;
11599 struct behavior *b;
11600 struct otri *searchtri;
11601 vertex searchpoint;
11602 #endif
11603
11604 {
11605 struct otri checktri;
11606 vertex startvertex;
11607 vertex leftvertex, rightvertex;
11608 REAL leftccw, rightccw;
11609 int leftflag, rightflag;
11610 triangle ptr;
11611
11612 org(*searchtri, startvertex);
11613 dest(*searchtri, rightvertex);
11614 apex(*searchtri, leftvertex);
11615
11616 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11617 leftflag = leftccw > 0.0;
11618
11619 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11620 rightflag = rightccw > 0.0;
11621 if (leftflag && rightflag) {
11622
11623
11624 onext(*searchtri, checktri);
11625 if (checktri.tri == m->dummytri) {
11626 leftflag = 0;
11627 } else {
11628 rightflag = 0;
11629 }
11630 }
11631 while (leftflag) {
11632
11633 onextself(*searchtri);
11634 if (searchtri->tri == m->dummytri) {
11635 printf("Internal error in finddirection(): Unable to find a\n");
11636 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11637 startvertex[1]);
11638 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11639 internalerror();
11640 }
11641 apex(*searchtri, leftvertex);
11642 rightccw = leftccw;
11643 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11644 leftflag = leftccw > 0.0;
11645 }
11646 while (rightflag) {
11647
11648 oprevself(*searchtri);
11649 if (searchtri->tri == m->dummytri) {
11650 printf("Internal error in finddirection(): Unable to find a\n");
11651 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11652 startvertex[1]);
11653 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11654 internalerror();
11655 }
11656 dest(*searchtri, rightvertex);
11657 leftccw = rightccw;
11658 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11659 rightflag = rightccw > 0.0;
11660 }
11661 if (leftccw == 0.0) {
11662 return LEFTCOLLINEAR;
11663 } else if (rightccw == 0.0) {
11664 return RIGHTCOLLINEAR;
11665 } else {
11666 return WITHIN;
11667 }
11668 }
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687 #ifdef ANSI_DECLARATORS
11688 void segmentintersection(struct mesh *m, struct behavior *b,
11689 struct otri *splittri, struct osub *splitsubseg,
11690 vertex endpoint2)
11691 #else
11692 void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11693 struct mesh *m;
11694 struct behavior *b;
11695 struct otri *splittri;
11696 struct osub *splitsubseg;
11697 vertex endpoint2;
11698 #endif
11699
11700 {
11701 struct osub opposubseg;
11702 vertex endpoint1;
11703 vertex torg, tdest;
11704 vertex leftvertex, rightvertex;
11705 vertex newvertex;
11706 enum insertvertexresult success;
11707 enum finddirectionresult collinear;
11708 REAL ex, ey;
11709 REAL tx, ty;
11710 REAL etx, ety;
11711 REAL split, denom;
11712 int i;
11713 triangle ptr;
11714 subseg sptr;
11715
11716
11717 apex(*splittri, endpoint1);
11718 org(*splittri, torg);
11719 dest(*splittri, tdest);
11720
11721 tx = tdest[0] - torg[0];
11722 ty = tdest[1] - torg[1];
11723 ex = endpoint2[0] - endpoint1[0];
11724 ey = endpoint2[1] - endpoint1[1];
11725 etx = torg[0] - endpoint2[0];
11726 ety = torg[1] - endpoint2[1];
11727 denom = ty * ex - tx * ey;
11728 if (denom == 0.0) {
11729 printf("Internal error in segmentintersection():");
11730 printf(" Attempt to find intersection of parallel segments.\n");
11731 internalerror();
11732 }
11733 split = (ey * etx - ex * ety) / denom;
11734
11735 newvertex = (vertex) poolalloc(&m->vertices);
11736
11737 for (i = 0; i < 2 + m->nextras; i++) {
11738 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11739 }
11740 setvertexmark(newvertex, mark(*splitsubseg));
11741 setvertextype(newvertex, INPUTVERTEX);
11742 if (b->verbose > 1) {
11743 printf(
11744 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11745 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11746 }
11747
11748 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11749 if (success != SUCCESSFULVERTEX) {
11750 printf("Internal error in segmentintersection():\n");
11751 printf(" Failure to split a segment.\n");
11752 internalerror();
11753 }
11754
11755 setvertex2tri(newvertex, encode(*splittri));
11756 if (m->steinerleft > 0) {
11757 m->steinerleft--;
11758 }
11759
11760
11761 ssymself(*splitsubseg);
11762 spivot(*splitsubseg, opposubseg);
11763 sdissolve(*splitsubseg);
11764 sdissolve(opposubseg);
11765 do {
11766 setsegorg(*splitsubseg, newvertex);
11767 snextself(*splitsubseg);
11768 } while (splitsubseg->ss != m->dummysub);
11769 do {
11770 setsegorg(opposubseg, newvertex);
11771 snextself(opposubseg);
11772 } while (opposubseg.ss != m->dummysub);
11773
11774
11775
11776 collinear = finddirection(m, b, splittri, endpoint1);
11777 dest(*splittri, rightvertex);
11778 apex(*splittri, leftvertex);
11779 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11780 onextself(*splittri);
11781 } else if ((rightvertex[0] != endpoint1[0]) ||
11782 (rightvertex[1] != endpoint1[1])) {
11783 printf("Internal error in segmentintersection():\n");
11784 printf(" Topological inconsistency after splitting a segment.\n");
11785 internalerror();
11786 }
11787
11788 }
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814 #ifdef ANSI_DECLARATORS
11815 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11816 vertex endpoint2, int newmark)
11817 #else
11818 int scoutsegment(m, b, searchtri, endpoint2, newmark)
11819 struct mesh *m;
11820 struct behavior *b;
11821 struct otri *searchtri;
11822 vertex endpoint2;
11823 int newmark;
11824 #endif
11825
11826 {
11827 struct otri crosstri;
11828 struct osub crosssubseg;
11829 vertex leftvertex, rightvertex;
11830 enum finddirectionresult collinear;
11831 subseg sptr;
11832
11833 collinear = finddirection(m, b, searchtri, endpoint2);
11834 dest(*searchtri, rightvertex);
11835 apex(*searchtri, leftvertex);
11836 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11837 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11838
11839 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11840 lprevself(*searchtri);
11841 }
11842
11843 insertsubseg(m, b, searchtri, newmark);
11844 return 1;
11845 } else if (collinear == LEFTCOLLINEAR) {
11846
11847
11848 lprevself(*searchtri);
11849 insertsubseg(m, b, searchtri, newmark);
11850
11851 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11852 } else if (collinear == RIGHTCOLLINEAR) {
11853
11854 insertsubseg(m, b, searchtri, newmark);
11855
11856 lnextself(*searchtri);
11857
11858 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11859 } else {
11860 lnext(*searchtri, crosstri);
11861 tspivot(crosstri, crosssubseg);
11862
11863 if (crosssubseg.ss == m->dummysub) {
11864 return 0;
11865 } else {
11866
11867 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11868 otricopy(crosstri, *searchtri);
11869 insertsubseg(m, b, searchtri, newmark);
11870
11871 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11872 }
11873 }
11874 }
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895 #ifndef REDUCED
11896 #ifndef CDT_ONLY
11897
11898 #ifdef ANSI_DECLARATORS
11899 void conformingedge(struct mesh *m, struct behavior *b,
11900 vertex endpoint1, vertex endpoint2, int newmark)
11901 #else
11902 void conformingedge(m, b, endpoint1, endpoint2, newmark)
11903 struct mesh *m;
11904 struct behavior *b;
11905 vertex endpoint1;
11906 vertex endpoint2;
11907 int newmark;
11908 #endif
11909
11910 {
11911 struct otri searchtri1, searchtri2;
11912 struct osub brokensubseg;
11913 vertex newvertex;
11914 vertex midvertex1, midvertex2;
11915 enum insertvertexresult success;
11916 int i;
11917 subseg sptr;
11918
11919 if (b->verbose > 2) {
11920 printf("Forcing segment into triangulation by recursive splitting:\n");
11921 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11922 endpoint2[0], endpoint2[1]);
11923 }
11924
11925 newvertex = (vertex) poolalloc(&m->vertices);
11926
11927 for (i = 0; i < 2 + m->nextras; i++) {
11928 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11929 }
11930 setvertexmark(newvertex, newmark);
11931 setvertextype(newvertex, SEGMENTVERTEX);
11932
11933 searchtri1.tri = m->dummytri;
11934
11935 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11936 0, 0);
11937 if (success == DUPLICATEVERTEX) {
11938 if (b->verbose > 2) {
11939 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11940 newvertex[0], newvertex[1]);
11941 }
11942
11943 vertexdealloc(m, newvertex);
11944 org(searchtri1, newvertex);
11945 } else {
11946 if (success == VIOLATINGVERTEX) {
11947 if (b->verbose > 2) {
11948 printf(" Two segments intersect at (%.12g, %.12g).\n",
11949 newvertex[0], newvertex[1]);
11950 }
11951
11952 tspivot(searchtri1, brokensubseg);
11953 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11954 0, 0);
11955 if (success != SUCCESSFULVERTEX) {
11956 printf("Internal error in conformingedge():\n");
11957 printf(" Failure to split a segment.\n");
11958 internalerror();
11959 }
11960 }
11961
11962 if (m->steinerleft > 0) {
11963 m->steinerleft--;
11964 }
11965 }
11966 otricopy(searchtri1, searchtri2);
11967
11968
11969
11970
11971
11972 finddirection(m, b, &searchtri2, endpoint2);
11973 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11974
11975
11976 org(searchtri1, midvertex1);
11977 conformingedge(m, b, midvertex1, endpoint1, newmark);
11978 }
11979 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11980
11981
11982 org(searchtri2, midvertex2);
11983 conformingedge(m, b, midvertex2, endpoint2, newmark);
11984 }
11985 }
11986
11987 #endif
11988 #endif
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028 #ifdef ANSI_DECLARATORS
12029 void delaunayfixup(struct mesh *m, struct behavior *b,
12030 struct otri *fixuptri, int leftside)
12031 #else
12032 void delaunayfixup(m, b, fixuptri, leftside)
12033 struct mesh *m;
12034 struct behavior *b;
12035 struct otri *fixuptri;
12036 int leftside;
12037 #endif
12038
12039 {
12040 struct otri neartri;
12041 struct otri fartri;
12042 struct osub faredge;
12043 vertex nearvertex, leftvertex, rightvertex, farvertex;
12044 triangle ptr;
12045 subseg sptr;
12046
12047 lnext(*fixuptri, neartri);
12048 sym(neartri, fartri);
12049
12050 if (fartri.tri == m->dummytri) {
12051 return;
12052 }
12053 tspivot(neartri, faredge);
12054 if (faredge.ss != m->dummysub) {
12055 return;
12056 }
12057
12058 apex(neartri, nearvertex);
12059 org(neartri, leftvertex);
12060 dest(neartri, rightvertex);
12061 apex(fartri, farvertex);
12062
12063 if (leftside) {
12064 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12065
12066
12067 return;
12068 }
12069 } else {
12070 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12071
12072
12073 return;
12074 }
12075 }
12076 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12077
12078
12079
12080
12081 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12082 0.0) {
12083 return;
12084 }
12085
12086 }
12087 flip(m, b, &neartri);
12088 lprevself(*fixuptri);
12089
12090 delaunayfixup(m, b, fixuptri, leftside);
12091 delaunayfixup(m, b, &fartri, leftside);
12092 }
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148 #ifdef ANSI_DECLARATORS
12149 void constrainededge(struct mesh *m, struct behavior *b,
12150 struct otri *starttri, vertex endpoint2, int newmark)
12151 #else
12152 void constrainededge(m, b, starttri, endpoint2, newmark)
12153 struct mesh *m;
12154 struct behavior *b;
12155 struct otri *starttri;
12156 vertex endpoint2;
12157 int newmark;
12158 #endif
12159
12160 {
12161 struct otri fixuptri, fixuptri2;
12162 struct osub crosssubseg;
12163 vertex endpoint1;
12164 vertex farvertex;
12165 REAL area;
12166 int collision;
12167 int done;
12168 triangle ptr;
12169 subseg sptr;
12170
12171 org(*starttri, endpoint1);
12172 lnext(*starttri, fixuptri);
12173 flip(m, b, &fixuptri);
12174
12175
12176 collision = 0;
12177 done = 0;
12178 do {
12179 org(fixuptri, farvertex);
12180
12181
12182 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12183 oprev(fixuptri, fixuptri2);
12184
12185 delaunayfixup(m, b, &fixuptri, 0);
12186 delaunayfixup(m, b, &fixuptri2, 1);
12187 done = 1;
12188 } else {
12189
12190
12191
12192 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12193 if (area == 0.0) {
12194
12195 collision = 1;
12196 oprev(fixuptri, fixuptri2);
12197
12198 delaunayfixup(m, b, &fixuptri, 0);
12199 delaunayfixup(m, b, &fixuptri2, 1);
12200 done = 1;
12201 } else {
12202 if (area > 0.0) {
12203 oprev(fixuptri, fixuptri2);
12204
12205
12206 delaunayfixup(m, b, &fixuptri2, 1);
12207
12208
12209
12210 lprevself(fixuptri);
12211 } else {
12212 delaunayfixup(m, b, &fixuptri, 0);
12213
12214
12215
12216 oprevself(fixuptri);
12217 }
12218
12219 tspivot(fixuptri, crosssubseg);
12220 if (crosssubseg.ss == m->dummysub) {
12221 flip(m, b, &fixuptri);
12222 } else {
12223
12224 collision = 1;
12225
12226 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12227 done = 1;
12228 }
12229 }
12230 }
12231 } while (!done);
12232
12233 insertsubseg(m, b, &fixuptri, newmark);
12234
12235
12236 if (collision) {
12237
12238 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12239 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12240 }
12241 }
12242 }
12243
12244
12245
12246
12247
12248
12249
12250 #ifdef ANSI_DECLARATORS
12251 void insertsegment(struct mesh *m, struct behavior *b,
12252 vertex endpoint1, vertex endpoint2, int newmark)
12253 #else
12254 void insertsegment(m, b, endpoint1, endpoint2, newmark)
12255 struct mesh *m;
12256 struct behavior *b;
12257 vertex endpoint1;
12258 vertex endpoint2;
12259 int newmark;
12260 #endif
12261
12262 {
12263 struct otri searchtri1, searchtri2;
12264 triangle encodedtri;
12265 vertex checkvertex;
12266 triangle ptr;
12267
12268 if (b->verbose > 1) {
12269 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12270 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12271 }
12272
12273
12274 checkvertex = (vertex) NULL;
12275 encodedtri = vertex2tri(endpoint1);
12276 if (encodedtri != (triangle) NULL) {
12277 decode(encodedtri, searchtri1);
12278 org(searchtri1, checkvertex);
12279 }
12280 if (checkvertex != endpoint1) {
12281
12282 searchtri1.tri = m->dummytri;
12283 searchtri1.orient = 0;
12284 symself(searchtri1);
12285
12286 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12287 printf(
12288 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12289 printf(" (%.12g, %.12g) in triangulation.\n",
12290 endpoint1[0], endpoint1[1]);
12291 internalerror();
12292 }
12293 }
12294
12295 otricopy(searchtri1, m->recenttri);
12296
12297
12298 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12299
12300 return;
12301 }
12302
12303
12304 org(searchtri1, endpoint1);
12305
12306
12307 checkvertex = (vertex) NULL;
12308 encodedtri = vertex2tri(endpoint2);
12309 if (encodedtri != (triangle) NULL) {
12310 decode(encodedtri, searchtri2);
12311 org(searchtri2, checkvertex);
12312 }
12313 if (checkvertex != endpoint2) {
12314
12315 searchtri2.tri = m->dummytri;
12316 searchtri2.orient = 0;
12317 symself(searchtri2);
12318
12319 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12320 printf(
12321 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12322 printf(" (%.12g, %.12g) in triangulation.\n",
12323 endpoint2[0], endpoint2[1]);
12324 internalerror();
12325 }
12326 }
12327
12328 otricopy(searchtri2, m->recenttri);
12329
12330
12331 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12332
12333 return;
12334 }
12335
12336
12337 org(searchtri2, endpoint2);
12338
12339 #ifndef REDUCED
12340 #ifndef CDT_ONLY
12341 if (b->splitseg) {
12342
12343 conformingedge(m, b, endpoint1, endpoint2, newmark);
12344 } else {
12345 #endif
12346 #endif
12347
12348 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12349 #ifndef REDUCED
12350 #ifndef CDT_ONLY
12351 }
12352 #endif
12353 #endif
12354 }
12355
12356
12357
12358
12359
12360
12361
12362 #ifdef ANSI_DECLARATORS
12363 void markhull(struct mesh *m, struct behavior *b)
12364 #else
12365 void markhull(m, b)
12366 struct mesh *m;
12367 struct behavior *b;
12368 #endif
12369
12370 {
12371 struct otri hulltri;
12372 struct otri nexttri;
12373 struct otri starttri;
12374 triangle ptr;
12375
12376
12377 hulltri.tri = m->dummytri;
12378 hulltri.orient = 0;
12379 symself(hulltri);
12380
12381 otricopy(hulltri, starttri);
12382
12383 do {
12384
12385 insertsubseg(m, b, &hulltri, 1);
12386
12387 lnextself(hulltri);
12388 oprev(hulltri, nexttri);
12389 while (nexttri.tri != m->dummytri) {
12390 otricopy(nexttri, hulltri);
12391 oprev(hulltri, nexttri);
12392 }
12393 } while (!otriequal(hulltri, starttri));
12394 }
12395
12396
12397
12398
12399
12400
12401
12402
12403
12404
12405
12406 #ifdef TRILIBRARY
12407
12408 #ifdef ANSI_DECLARATORS
12409 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12410 int *segmentmarkerlist, int numberofsegments)
12411 #else
12412 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12413 struct mesh *m;
12414 struct behavior *b;
12415 int *segmentlist;
12416 int *segmentmarkerlist;
12417 int numberofsegments;
12418 #endif
12419
12420 #else
12421
12422 #ifdef ANSI_DECLARATORS
12423 void formskeleton(struct mesh *m, struct behavior *b,
12424 FILE *polyfile, char *polyfilename)
12425 #else
12426 void formskeleton(m, b, polyfile, polyfilename)
12427 struct mesh *m;
12428 struct behavior *b;
12429 FILE *polyfile;
12430 char *polyfilename;
12431 #endif
12432
12433 #endif
12434
12435 {
12436 #ifdef TRILIBRARY
12437 char polyfilename[6];
12438 int index;
12439 #else
12440 char inputline[INPUTLINESIZE];
12441 char *stringptr;
12442 #endif
12443 vertex endpoint1, endpoint2;
12444 int segmentmarkers;
12445 int end1, end2;
12446 int boundmarker;
12447 int i;
12448
12449 if (b->poly) {
12450 if (!b->quiet) {
12451 printf("Recovering segments in Delaunay triangulation.\n");
12452 }
12453 #ifdef TRILIBRARY
12454 strcpy(polyfilename, "input");
12455 m->insegments = numberofsegments;
12456 segmentmarkers = segmentmarkerlist != (int *) NULL;
12457 index = 0;
12458 #else
12459
12460
12461 stringptr = readline(inputline, polyfile, polyfilename);
12462 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12463 stringptr = findfield(stringptr);
12464 if (*stringptr == '\0') {
12465 segmentmarkers = 0;
12466 } else {
12467 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12468 }
12469 #endif
12470
12471
12472 if (m->triangles.items == 0) {
12473 return;
12474 }
12475
12476
12477
12478 if (m->insegments > 0) {
12479 makevertexmap(m, b);
12480 if (b->verbose) {
12481 printf(" Recovering PSLG segments.\n");
12482 }
12483 }
12484
12485 boundmarker = 0;
12486
12487 for (i = 0; i < m->insegments; i++) {
12488 #ifdef TRILIBRARY
12489 end1 = segmentlist[index++];
12490 end2 = segmentlist[index++];
12491 if (segmentmarkers) {
12492 boundmarker = segmentmarkerlist[i];
12493 }
12494 #else
12495 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12496 stringptr = findfield(stringptr);
12497 if (*stringptr == '\0') {
12498 printf("Error: Segment %d has no endpoints in %s.\n",
12499 b->firstnumber + i, polyfilename);
12500 triexit(1);
12501 } else {
12502 end1 = (int) strtol(stringptr, &stringptr, 0);
12503 }
12504 stringptr = findfield(stringptr);
12505 if (*stringptr == '\0') {
12506 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12507 b->firstnumber + i, polyfilename);
12508 triexit(1);
12509 } else {
12510 end2 = (int) strtol(stringptr, &stringptr, 0);
12511 }
12512 if (segmentmarkers) {
12513 stringptr = findfield(stringptr);
12514 if (*stringptr == '\0') {
12515 boundmarker = 0;
12516 } else {
12517 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12518 }
12519 }
12520 #endif
12521 if ((end1 < b->firstnumber) ||
12522 (end1 >= b->firstnumber + m->invertices)) {
12523 if (!b->quiet) {
12524 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12525 b->firstnumber + i, polyfilename);
12526 }
12527 } else if ((end2 < b->firstnumber) ||
12528 (end2 >= b->firstnumber + m->invertices)) {
12529 if (!b->quiet) {
12530 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12531 b->firstnumber + i, polyfilename);
12532 }
12533 } else {
12534
12535 endpoint1 = getvertex(m, b, end1);
12536 endpoint2 = getvertex(m, b, end2);
12537 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12538 if (!b->quiet) {
12539 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12540 b->firstnumber + i, polyfilename);
12541 }
12542 } else {
12543 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12544 }
12545 }
12546 }
12547 } else {
12548 m->insegments = 0;
12549 }
12550 if (b->convex || !b->poly) {
12551
12552 if (b->verbose) {
12553 printf(" Enclosing convex hull with segments.\n");
12554 }
12555 markhull(m, b);
12556 }
12557 }
12558
12561
12562
12563
12567
12568
12569
12570
12571
12572
12573
12574
12575 #ifdef ANSI_DECLARATORS
12576 void infecthull(struct mesh *m, struct behavior *b)
12577 #else
12578 void infecthull(m, b)
12579 struct mesh *m;
12580 struct behavior *b;
12581 #endif
12582
12583 {
12584 struct otri hulltri;
12585 struct otri nexttri;
12586 struct otri starttri;
12587 struct osub hullsubseg;
12588 triangle **deadtriangle;
12589 vertex horg, hdest;
12590 triangle ptr;
12591 subseg sptr;
12592
12593 if (b->verbose) {
12594 printf(" Marking concavities (external triangles) for elimination.\n");
12595 }
12596
12597 hulltri.tri = m->dummytri;
12598 hulltri.orient = 0;
12599 symself(hulltri);
12600
12601 otricopy(hulltri, starttri);
12602
12603 do {
12604
12605 if (!infected(hulltri)) {
12606
12607 tspivot(hulltri, hullsubseg);
12608 if (hullsubseg.ss == m->dummysub) {
12609
12610 if (!infected(hulltri)) {
12611 infect(hulltri);
12612 deadtriangle = (triangle **) poolalloc(&m->viri);
12613 *deadtriangle = hulltri.tri;
12614 }
12615 } else {
12616
12617 if (mark(hullsubseg) == 0) {
12618 setmark(hullsubseg, 1);
12619 org(hulltri, horg);
12620 dest(hulltri, hdest);
12621 if (vertexmark(horg) == 0) {
12622 setvertexmark(horg, 1);
12623 }
12624 if (vertexmark(hdest) == 0) {
12625 setvertexmark(hdest, 1);
12626 }
12627 }
12628 }
12629 }
12630
12631 lnextself(hulltri);
12632 oprev(hulltri, nexttri);
12633 while (nexttri.tri != m->dummytri) {
12634 otricopy(nexttri, hulltri);
12635 oprev(hulltri, nexttri);
12636 }
12637 } while (!otriequal(hulltri, starttri));
12638 }
12639
12640
12641
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657 #ifdef ANSI_DECLARATORS
12658 void plague(struct mesh *m, struct behavior *b)
12659 #else
12660 void plague(m, b)
12661 struct mesh *m;
12662 struct behavior *b;
12663 #endif
12664
12665 {
12666 struct otri testtri;
12667 struct otri neighbor;
12668 triangle **virusloop;
12669 triangle **deadtriangle;
12670 struct osub neighborsubseg;
12671 vertex testvertex;
12672 vertex norg, ndest;
12673 vertex deadorg, deaddest, deadapex;
12674 int killorg;
12675 triangle ptr;
12676 subseg sptr;
12677
12678 if (b->verbose) {
12679 printf(" Marking neighbors of marked triangles.\n");
12680 }
12681
12682
12683 traversalinit(&m->viri);
12684 virusloop = (triangle **) traverse(&m->viri);
12685 while (virusloop != (triangle **) NULL) {
12686 testtri.tri = *virusloop;
12687
12688
12689
12690
12691 uninfect(testtri);
12692 if (b->verbose > 2) {
12693
12694
12695 testtri.orient = 0;
12696 org(testtri, deadorg);
12697 dest(testtri, deaddest);
12698 apex(testtri, deadapex);
12699 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12700 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12701 deadapex[0], deadapex[1]);
12702 }
12703
12704 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12705
12706 sym(testtri, neighbor);
12707
12708 tspivot(testtri, neighborsubseg);
12709
12710 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12711 if (neighborsubseg.ss != m->dummysub) {
12712
12713
12714
12715 subsegdealloc(m, neighborsubseg.ss);
12716 if (neighbor.tri != m->dummytri) {
12717
12718
12719 uninfect(neighbor);
12720 tsdissolve(neighbor);
12721 infect(neighbor);
12722 }
12723 }
12724 } else {
12725 if (neighborsubseg.ss == m->dummysub) {
12726
12727
12728 if (b->verbose > 2) {
12729 org(neighbor, deadorg);
12730 dest(neighbor, deaddest);
12731 apex(neighbor, deadapex);
12732 printf(
12733 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12734 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12735 deadapex[0], deadapex[1]);
12736 }
12737 infect(neighbor);
12738
12739 deadtriangle = (triangle **) poolalloc(&m->viri);
12740 *deadtriangle = neighbor.tri;
12741 } else {
12742
12743 stdissolve(neighborsubseg);
12744
12745 if (mark(neighborsubseg) == 0) {
12746 setmark(neighborsubseg, 1);
12747 }
12748 org(neighbor, norg);
12749 dest(neighbor, ndest);
12750 if (vertexmark(norg) == 0) {
12751 setvertexmark(norg, 1);
12752 }
12753 if (vertexmark(ndest) == 0) {
12754 setvertexmark(ndest, 1);
12755 }
12756 }
12757 }
12758 }
12759
12760
12761 infect(testtri);
12762 virusloop = (triangle **) traverse(&m->viri);
12763 }
12764
12765 if (b->verbose) {
12766 printf(" Deleting marked triangles.\n");
12767 }
12768
12769 traversalinit(&m->viri);
12770 virusloop = (triangle **) traverse(&m->viri);
12771 while (virusloop != (triangle **) NULL) {
12772 testtri.tri = *virusloop;
12773
12774
12775
12776
12777 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12778 org(testtri, testvertex);
12779
12780 if (testvertex != (vertex) NULL) {
12781 killorg = 1;
12782
12783 setorg(testtri, NULL);
12784
12785 onext(testtri, neighbor);
12786
12787 while ((neighbor.tri != m->dummytri) &&
12788 (!otriequal(neighbor, testtri))) {
12789 if (infected(neighbor)) {
12790
12791 setorg(neighbor, NULL);
12792 } else {
12793
12794 killorg = 0;
12795 }
12796
12797 onextself(neighbor);
12798 }
12799
12800 if (neighbor.tri == m->dummytri) {
12801
12802 oprev(testtri, neighbor);
12803
12804 while (neighbor.tri != m->dummytri) {
12805 if (infected(neighbor)) {
12806
12807 setorg(neighbor, NULL);
12808 } else {
12809
12810 killorg = 0;
12811 }
12812
12813 oprevself(neighbor);
12814 }
12815 }
12816 if (killorg) {
12817 if (b->verbose > 1) {
12818 printf(" Deleting vertex (%.12g, %.12g)\n",
12819 testvertex[0], testvertex[1]);
12820 }
12821 setvertextype(testvertex, UNDEADVERTEX);
12822 m->undeads++;
12823 }
12824 }
12825 }
12826
12827
12828
12829 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12830 sym(testtri, neighbor);
12831 if (neighbor.tri == m->dummytri) {
12832
12833
12834
12835 m->hullsize--;
12836 } else {
12837
12838 dissolve(neighbor);
12839
12840
12841 m->hullsize++;
12842 }
12843 }
12844
12845 triangledealloc(m, testtri.tri);
12846 virusloop = (triangle **) traverse(&m->viri);
12847 }
12848
12849 poolrestart(&m->viri);
12850 }
12851
12852
12853
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867 #ifdef ANSI_DECLARATORS
12868 void regionplague(struct mesh *m, struct behavior *b,
12869 REAL attribute, REAL area)
12870 #else
12871 void regionplague(m, b, attribute, area)
12872 struct mesh *m;
12873 struct behavior *b;
12874 REAL attribute;
12875 REAL area;
12876 #endif
12877
12878 {
12879 struct otri testtri;
12880 struct otri neighbor;
12881 triangle **virusloop;
12882 triangle **regiontri;
12883 struct osub neighborsubseg;
12884 vertex regionorg, regiondest, regionapex;
12885 triangle ptr;
12886 subseg sptr;
12887
12888 if (b->verbose > 1) {
12889 printf(" Marking neighbors of marked triangles.\n");
12890 }
12891
12892
12893
12894 traversalinit(&m->viri);
12895 virusloop = (triangle **) traverse(&m->viri);
12896 while (virusloop != (triangle **) NULL) {
12897 testtri.tri = *virusloop;
12898
12899
12900
12901
12902 uninfect(testtri);
12903 if (b->regionattrib) {
12904
12905 setelemattribute(testtri, m->eextras, attribute);
12906 }
12907 if (b->vararea) {
12908
12909 setareabound(testtri, area);
12910 }
12911 if (b->verbose > 2) {
12912
12913
12914 testtri.orient = 0;
12915 org(testtri, regionorg);
12916 dest(testtri, regiondest);
12917 apex(testtri, regionapex);
12918 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12919 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12920 regionapex[0], regionapex[1]);
12921 }
12922
12923 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12924
12925 sym(testtri, neighbor);
12926
12927 tspivot(testtri, neighborsubseg);
12928
12929
12930 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12931 && (neighborsubseg.ss == m->dummysub)) {
12932 if (b->verbose > 2) {
12933 org(neighbor, regionorg);
12934 dest(neighbor, regiondest);
12935 apex(neighbor, regionapex);
12936 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12937 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12938 regionapex[0], regionapex[1]);
12939 }
12940
12941 infect(neighbor);
12942
12943 regiontri = (triangle **) poolalloc(&m->viri);
12944 *regiontri = neighbor.tri;
12945 }
12946 }
12947
12948
12949 infect(testtri);
12950 virusloop = (triangle **) traverse(&m->viri);
12951 }
12952
12953
12954 if (b->verbose > 1) {
12955 printf(" Unmarking marked triangles.\n");
12956 }
12957 traversalinit(&m->viri);
12958 virusloop = (triangle **) traverse(&m->viri);
12959 while (virusloop != (triangle **) NULL) {
12960 testtri.tri = *virusloop;
12961 uninfect(testtri);
12962 virusloop = (triangle **) traverse(&m->viri);
12963 }
12964
12965 poolrestart(&m->viri);
12966 }
12967
12968
12969
12970
12971
12972
12973
12974
12975
12976
12977
12978
12979
12980 #ifdef ANSI_DECLARATORS
12981 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12982 REAL *regionlist, int regions)
12983 #else
12984 void carveholes(m, b, holelist, holes, regionlist, regions)
12985 struct mesh *m;
12986 struct behavior *b;
12987 REAL *holelist;
12988 int holes;
12989 REAL *regionlist;
12990 int regions;
12991 #endif
12992
12993 {
12994 struct otri searchtri;
12995 struct otri triangleloop;
12996 struct otri *regiontris;
12997 triangle **holetri;
12998 triangle **regiontri;
12999 vertex searchorg, searchdest;
13000 enum locateresult intersect;
13001 int i;
13002 triangle ptr;
13003
13004 if (!(b->quiet || (b->noholes && b->convex))) {
13005 printf("Removing unwanted triangles.\n");
13006 if (b->verbose && (holes > 0)) {
13007 printf(" Marking holes for elimination.\n");
13008 }
13009 }
13010
13011 if (regions > 0) {
13012
13013 regiontris = (struct otri *) trimalloc(regions *
13014 (int) sizeof(struct otri));
13015 } else {
13016 regiontris = (struct otri *) NULL;
13017 }
13018
13019 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13020
13021
13022 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13023 }
13024
13025 if (!b->convex) {
13026
13027
13028 infecthull(m, b);
13029 }
13030
13031 if ((holes > 0) && !b->noholes) {
13032
13033 for (i = 0; i < 2 * holes; i += 2) {
13034
13035 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13036 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13037
13038 searchtri.tri = m->dummytri;
13039 searchtri.orient = 0;
13040 symself(searchtri);
13041
13042
13043
13044 org(searchtri, searchorg);
13045 dest(searchtri, searchdest);
13046 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13047 0.0) {
13048
13049 intersect = locate(m, b, &holelist[i], &searchtri);
13050 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13051
13052
13053 infect(searchtri);
13054 holetri = (triangle **) poolalloc(&m->viri);
13055 *holetri = searchtri.tri;
13056 }
13057 }
13058 }
13059 }
13060 }
13061
13062
13063
13064
13065
13066
13067
13068 if (regions > 0) {
13069
13070 for (i = 0; i < regions; i++) {
13071 regiontris[i].tri = m->dummytri;
13072
13073 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13074 (regionlist[4 * i + 1] >= m->ymin) &&
13075 (regionlist[4 * i + 1] <= m->ymax)) {
13076
13077 searchtri.tri = m->dummytri;
13078 searchtri.orient = 0;
13079 symself(searchtri);
13080
13081
13082
13083 org(searchtri, searchorg);
13084 dest(searchtri, searchdest);
13085 if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) >
13086 0.0) {
13087
13088 intersect = locate(m, b, ®ionlist[4 * i], &searchtri);
13089 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13090
13091
13092 otricopy(searchtri, regiontris[i]);
13093 }
13094 }
13095 }
13096 }
13097 }
13098
13099 if (m->viri.items > 0) {
13100
13101 plague(m, b);
13102 }
13103
13104
13105 if (regions > 0) {
13106 if (!b->quiet) {
13107 if (b->regionattrib) {
13108 if (b->vararea) {
13109 printf("Spreading regional attributes and area constraints.\n");
13110 } else {
13111 printf("Spreading regional attributes.\n");
13112 }
13113 } else {
13114 printf("Spreading regional area constraints.\n");
13115 }
13116 }
13117 if (b->regionattrib && !b->refine) {
13118
13119 traversalinit(&m->triangles);
13120 triangleloop.orient = 0;
13121 triangleloop.tri = triangletraverse(m);
13122 while (triangleloop.tri != (triangle *) NULL) {
13123 setelemattribute(triangleloop, m->eextras, 0.0);
13124 triangleloop.tri = triangletraverse(m);
13125 }
13126 }
13127 for (i = 0; i < regions; i++) {
13128 if (regiontris[i].tri != m->dummytri) {
13129
13130
13131 if (!deadtri(regiontris[i].tri)) {
13132
13133 infect(regiontris[i]);
13134 regiontri = (triangle **) poolalloc(&m->viri);
13135 *regiontri = regiontris[i].tri;
13136
13137 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13138
13139 }
13140 }
13141 }
13142 if (b->regionattrib && !b->refine) {
13143
13144 m->eextras++;
13145 }
13146 }
13147
13148
13149 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13150 pooldeinit(&m->viri);
13151 }
13152 if (regions > 0) {
13153 trifree((VOID *) regiontris);
13154 }
13155 }
13156
13159
13160
13161
13165
13166
13167
13168
13169
13170
13171
13172 #ifndef CDT_ONLY
13173
13174 #ifdef ANSI_DECLARATORS
13175 void tallyencs(struct mesh *m, struct behavior *b)
13176 #else
13177 void tallyencs(m, b)
13178 struct mesh *m;
13179 struct behavior *b;
13180 #endif
13181
13182 {
13183 struct osub subsegloop;
13184 int dummy;
13185
13186 traversalinit(&m->subsegs);
13187 subsegloop.ssorient = 0;
13188 subsegloop.ss = subsegtraverse(m);
13189 while (subsegloop.ss != (subseg *) NULL) {
13190
13191 dummy = checkseg4encroach(m, b, &subsegloop);
13192 subsegloop.ss = subsegtraverse(m);
13193 }
13194 }
13195
13196 #endif
13197
13198
13199
13200
13201
13202
13203
13204 #ifndef CDT_ONLY
13205
13206 void precisionerror()
13207 {
13208 printf("Try increasing the area criterion and/or reducing the minimum\n");
13209 printf(" allowable angle so that tiny triangles are not created.\n");
13210 #ifdef SINGLE
13211 printf("Alternatively, try recompiling me with double precision\n");
13212 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13213 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13214 #endif
13215 }
13216
13217 #endif
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233 #ifndef CDT_ONLY
13234
13235 #ifdef ANSI_DECLARATORS
13236 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13237 #else
13238 void splitencsegs(m, b, triflaws)
13239 struct mesh *m;
13240 struct behavior *b;
13241 int triflaws;
13242 #endif
13243
13244 {
13245 struct otri enctri;
13246 struct otri testtri;
13247 struct osub testsh;
13248 struct osub currentenc;
13249 struct badsubseg *encloop;
13250 vertex eorg, edest, eapex;
13251 vertex newvertex;
13252 enum insertvertexresult success;
13253 REAL segmentlength, nearestpoweroftwo;
13254 REAL split;
13255 REAL multiplier, divisor;
13256 int acuteorg, acuteorg2, acutedest, acutedest2;
13257 int dummy;
13258 int i;
13259 triangle ptr;
13260 subseg sptr;
13261
13262
13263
13264 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13265 traversalinit(&m->badsubsegs);
13266 encloop = badsubsegtraverse(m);
13267 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13268 sdecode(encloop->encsubseg, currentenc);
13269 sorg(currentenc, eorg);
13270 sdest(currentenc, edest);
13271
13272
13273
13274
13275 if (!deadsubseg(currentenc.ss) &&
13276 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293 stpivot(currentenc, enctri);
13294 lnext(enctri, testtri);
13295 tspivot(testtri, testsh);
13296 acuteorg = testsh.ss != m->dummysub;
13297
13298 lnextself(testtri);
13299 tspivot(testtri, testsh);
13300 acutedest = testsh.ss != m->dummysub;
13301
13302
13303
13304
13305 if (!b->conformdel && !acuteorg && !acutedest) {
13306 apex(enctri, eapex);
13307 while ((vertextype(eapex) == FREEVERTEX) &&
13308 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13309 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13310 deletevertex(m, b, &testtri);
13311 stpivot(currentenc, enctri);
13312 apex(enctri, eapex);
13313 lprev(enctri, testtri);
13314 }
13315 }
13316
13317
13318
13319 sym(enctri, testtri);
13320 if (testtri.tri != m->dummytri) {
13321
13322 lnextself(testtri);
13323 tspivot(testtri, testsh);
13324 acutedest2 = testsh.ss != m->dummysub;
13325 acutedest = acutedest || acutedest2;
13326
13327 lnextself(testtri);
13328 tspivot(testtri, testsh);
13329 acuteorg2 = testsh.ss != m->dummysub;
13330 acuteorg = acuteorg || acuteorg2;
13331
13332
13333 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13334 org(testtri, eapex);
13335 while ((vertextype(eapex) == FREEVERTEX) &&
13336 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13337 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13338 deletevertex(m, b, &testtri);
13339 sym(enctri, testtri);
13340 apex(testtri, eapex);
13341 lprevself(testtri);
13342 }
13343 }
13344 }
13345
13346
13347
13348 if (acuteorg || acutedest) {
13349 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13350 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13351
13352
13353 nearestpoweroftwo = 1.0;
13354 while (segmentlength > 3.0 * nearestpoweroftwo) {
13355 nearestpoweroftwo *= 2.0;
13356 }
13357 while (segmentlength < 1.5 * nearestpoweroftwo) {
13358 nearestpoweroftwo *= 0.5;
13359 }
13360
13361 split = nearestpoweroftwo / segmentlength;
13362 if (acutedest) {
13363 split = 1.0 - split;
13364 }
13365 } else {
13366
13367
13368 split = 0.5;
13369 }
13370
13371
13372 newvertex = (vertex) poolalloc(&m->vertices);
13373
13374 for (i = 0; i < 2 + m->nextras; i++) {
13375 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13376 }
13377
13378 if (!b->noexact) {
13379
13380
13381
13382 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13383 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13384 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13385 if ((multiplier != 0.0) && (divisor != 0.0)) {
13386 multiplier = multiplier / divisor;
13387
13388 if (multiplier == multiplier) {
13389 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13390 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13391 }
13392 }
13393 }
13394
13395 setvertexmark(newvertex, mark(currentenc));
13396 setvertextype(newvertex, SEGMENTVERTEX);
13397 if (b->verbose > 1) {
13398 printf(
13399 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13400 eorg[0], eorg[1], edest[0], edest[1],
13401 newvertex[0], newvertex[1]);
13402 }
13403
13404 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13405 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13406 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13407 newvertex[0], newvertex[1]);
13408 printf("I attempted to split a segment to a smaller size than\n");
13409 printf(" can be accommodated by the finite precision of\n");
13410 printf(" floating point arithmetic.\n");
13411 precisionerror();
13412 triexit(1);
13413 }
13414
13415 success = insertvertex(m, b, newvertex, &enctri, ¤tenc,
13416 1, triflaws);
13417 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13418 printf("Internal error in splitencsegs():\n");
13419 printf(" Failure to split a segment.\n");
13420 internalerror();
13421 }
13422 if (m->steinerleft > 0) {
13423 m->steinerleft--;
13424 }
13425
13426 dummy = checkseg4encroach(m, b, ¤tenc);
13427 snextself(currentenc);
13428 dummy = checkseg4encroach(m, b, ¤tenc);
13429 }
13430
13431 badsubsegdealloc(m, encloop);
13432 encloop = badsubsegtraverse(m);
13433 }
13434 }
13435 }
13436
13437 #endif
13438
13439
13440
13441
13442
13443
13444
13445 #ifndef CDT_ONLY
13446
13447 #ifdef ANSI_DECLARATORS
13448 void tallyfaces(struct mesh *m, struct behavior *b)
13449 #else
13450 void tallyfaces(m, b)
13451 struct mesh *m;
13452 struct behavior *b;
13453 #endif
13454
13455 {
13456 struct otri triangleloop;
13457
13458 if (b->verbose) {
13459 printf(" Making a list of bad triangles.\n");
13460 }
13461 traversalinit(&m->triangles);
13462 triangleloop.orient = 0;
13463 triangleloop.tri = triangletraverse(m);
13464 while (triangleloop.tri != (triangle *) NULL) {
13465
13466 testtriangle(m, b, &triangleloop);
13467 triangleloop.tri = triangletraverse(m);
13468 }
13469 }
13470
13471 #endif
13472
13473
13474
13475
13476
13477
13478
13479
13480
13481 #ifndef CDT_ONLY
13482
13483 #ifdef ANSI_DECLARATORS
13484 void splittriangle(struct mesh *m, struct behavior *b,
13485 struct badtriang *badtri)
13486 #else
13487 void splittriangle(m, b, badtri)
13488 struct mesh *m;
13489 struct behavior *b;
13490 struct badtriang *badtri;
13491 #endif
13492
13493 {
13494 struct otri badotri;
13495 vertex borg, bdest, bapex;
13496 vertex newvertex;
13497 REAL xi, eta;
13498 enum insertvertexresult success;
13499 int errorflag;
13500 int i;
13501
13502 decode(badtri->poortri, badotri);
13503 org(badotri, borg);
13504 dest(badotri, bdest);
13505 apex(badotri, bapex);
13506
13507
13508
13509 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13510 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13511 if (b->verbose > 1) {
13512 printf(" Splitting this triangle at its circumcenter:\n");
13513 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13514 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13515 }
13516
13517 errorflag = 0;
13518
13519 newvertex = (vertex) poolalloc(&m->vertices);
13520 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13521
13522
13523 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13524 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13525 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13526 if (!b->quiet) {
13527 printf(
13528 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13529 newvertex[0], newvertex[1]);
13530 errorflag = 1;
13531 }
13532 vertexdealloc(m, newvertex);
13533 } else {
13534 for (i = 2; i < 2 + m->nextras; i++) {
13535
13536 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13537 + eta * (bapex[i] - borg[i]);
13538 }
13539
13540
13541 setvertexmark(newvertex, 0);
13542 setvertextype(newvertex, FREEVERTEX);
13543
13544
13545
13546
13547
13548
13549
13550
13551 if (eta < xi) {
13552 lprevself(badotri);
13553 }
13554
13555
13556
13557 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13558 1, 1);
13559 if (success == SUCCESSFULVERTEX) {
13560 if (m->steinerleft > 0) {
13561 m->steinerleft--;
13562 }
13563 } else if (success == ENCROACHINGVERTEX) {
13564
13565
13566 undovertex(m, b);
13567 if (b->verbose > 1) {
13568 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13569 }
13570 vertexdealloc(m, newvertex);
13571 } else if (success == VIOLATINGVERTEX) {
13572
13573
13574 vertexdealloc(m, newvertex);
13575 } else {
13576
13577 if (!b->quiet) {
13578 printf(
13579 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13580 newvertex[0], newvertex[1]);
13581 errorflag = 1;
13582 }
13583 vertexdealloc(m, newvertex);
13584 }
13585 }
13586 if (errorflag) {
13587 if (b->verbose) {
13588 printf(" The new vertex is at the circumcenter of triangle\n");
13589 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13590 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13591 }
13592 printf("This probably means that I am trying to refine triangles\n");
13593 printf(" to a smaller size than can be accommodated by the finite\n");
13594 printf(" precision of floating point arithmetic. (You can be\n");
13595 printf(" sure of this if I fail to terminate.)\n");
13596 precisionerror();
13597 }
13598 }
13599 }
13600
13601 #endif
13602
13603
13604
13605
13606
13607
13608
13609
13610 #ifndef CDT_ONLY
13611
13612 #ifdef ANSI_DECLARATORS
13613 void enforcequality(struct mesh *m, struct behavior *b)
13614 #else
13615 void enforcequality(m, b)
13616 struct mesh *m;
13617 struct behavior *b;
13618 #endif
13619
13620 {
13621 struct badtriang *badtri;
13622 int i;
13623
13624 if (!b->quiet) {
13625 printf("Adding Steiner points to enforce quality.\n");
13626 }
13627
13628 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13629 BADSUBSEGPERBLOCK, 0);
13630 if (b->verbose) {
13631 printf(" Looking for encroached subsegments.\n");
13632 }
13633
13634 tallyencs(m, b);
13635 if (b->verbose && (m->badsubsegs.items > 0)) {
13636 printf(" Splitting encroached subsegments.\n");
13637 }
13638
13639 splitencsegs(m, b, 0);
13640
13641
13642
13643
13644 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13645
13646 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13647 BADTRIPERBLOCK, 0);
13648
13649 for (i = 0; i < 4096; i++) {
13650 m->queuefront[i] = (struct badtriang *) NULL;
13651 }
13652 m->firstnonemptyq = -1;
13653
13654 tallyfaces(m, b);
13655
13656 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13657 FLIPSTACKERPERBLOCK, 0);
13658 m->checkquality = 1;
13659 if (b->verbose) {
13660 printf(" Splitting bad triangles.\n");
13661 }
13662 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13663
13664 badtri = dequeuebadtriang(m);
13665 splittriangle(m, b, badtri);
13666 if (m->badsubsegs.items > 0) {
13667
13668 enqueuebadtriang(m, b, badtri);
13669
13670
13671 splitencsegs(m, b, 1);
13672 } else {
13673
13674 pooldealloc(&m->badtriangles, (VOID *) badtri);
13675 }
13676 }
13677 }
13678
13679
13680
13681
13682
13683 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13684 (m->steinerleft == 0)) {
13685 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13686 if (m->badsubsegs.items == 1) {
13687 printf(" one encroached subsegment, and therefore might not be truly\n"
13688 );
13689 } else {
13690 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13691 , m->badsubsegs.items);
13692 }
13693 printf(" Delaunay. If the Delaunay property is important to you,\n");
13694 printf(" try increasing the number of Steiner points (controlled by\n");
13695 printf(" the -S switch) slightly and try again.\n\n");
13696 }
13697 }
13698
13699 #endif
13700
13703
13704
13705
13706
13707
13708
13709
13710
13711 #ifdef ANSI_DECLARATORS
13712 void highorder(struct mesh *m, struct behavior *b)
13713 #else
13714 void highorder(m, b)
13715 struct mesh *m;
13716 struct behavior *b;
13717 #endif
13718
13719 {
13720 struct otri triangleloop, trisym;
13721 struct osub checkmark;
13722 vertex newvertex;
13723 vertex torg, tdest;
13724 int i;
13725 triangle ptr;
13726 subseg sptr;
13727
13728 if (!b->quiet) {
13729 printf("Adding vertices for second-order triangles.\n");
13730 }
13731
13732
13733
13734
13735
13736 m->vertices.deaditemstack = (VOID *) NULL;
13737
13738 traversalinit(&m->triangles);
13739 triangleloop.tri = triangletraverse(m);
13740
13741
13742
13743
13744
13745
13746 while (triangleloop.tri != (triangle *) NULL) {
13747 for (triangleloop.orient = 0; triangleloop.orient < 3;
13748 triangleloop.orient++) {
13749 sym(triangleloop, trisym);
13750 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13751 org(triangleloop, torg);
13752 dest(triangleloop, tdest);
13753
13754
13755 newvertex = (vertex) poolalloc(&m->vertices);
13756 for (i = 0; i < 2 + m->nextras; i++) {
13757 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13758 }
13759
13760
13761 setvertexmark(newvertex, trisym.tri == m->dummytri);
13762 setvertextype(newvertex,
13763 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13764 if (b->usesegments) {
13765 tspivot(triangleloop, checkmark);
13766
13767 if (checkmark.ss != m->dummysub) {
13768 setvertexmark(newvertex, mark(checkmark));
13769 setvertextype(newvertex, SEGMENTVERTEX);
13770 }
13771 }
13772 if (b->verbose > 1) {
13773 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13774 }
13775
13776 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13777 (triangle) newvertex;
13778 if (trisym.tri != m->dummytri) {
13779 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13780 }
13781 }
13782 }
13783 triangleloop.tri = triangletraverse(m);
13784 }
13785 }
13786
13787
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800 #ifndef TRILIBRARY
13801
13802 #ifdef ANSI_DECLARATORS
13803 char *readline(char *string, FILE *infile, char *infilename)
13804 #else
13805 char *readline(string, infile, infilename)
13806 char *string;
13807 FILE *infile;
13808 char *infilename;
13809 #endif
13810
13811 {
13812 char *result;
13813
13814
13815 do {
13816 result = fgets(string, INPUTLINESIZE, infile);
13817 if (result == (char *) NULL) {
13818 printf(" Error: Unexpected end of file in %s.\n", infilename);
13819 triexit(1);
13820 }
13821
13822
13823 while ((*result != '\0') && (*result != '#')
13824 && (*result != '.') && (*result != '+') && (*result != '-')
13825 && ((*result < '0') || (*result > '9'))) {
13826 result++;
13827 }
13828
13829 } while ((*result == '#') || (*result == '\0'));
13830 return result;
13831 }
13832
13833 #endif
13834
13835
13836
13837
13838
13839
13840
13841
13842
13843
13844 #ifndef TRILIBRARY
13845
13846 #ifdef ANSI_DECLARATORS
13847 char *findfield(char *string)
13848 #else
13849 char *findfield(string)
13850 char *string;
13851 #endif
13852
13853 {
13854 char *result;
13855
13856 result = string;
13857
13858 while ((*result != '\0') && (*result != '#')
13859 && (*result != ' ') && (*result != '\t')) {
13860 result++;
13861 }
13862
13863
13864 while ((*result != '\0') && (*result != '#')
13865 && (*result != '.') && (*result != '+') && (*result != '-')
13866 && ((*result < '0') || (*result > '9'))) {
13867 result++;
13868 }
13869
13870 if (*result == '#') {
13871 *result = '\0';
13872 }
13873 return result;
13874 }
13875
13876 #endif
13877
13878
13879
13880
13881
13882
13883
13884
13885 #ifndef TRILIBRARY
13886
13887 #ifdef ANSI_DECLARATORS
13888 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13889 char *polyfilename, FILE **polyfile)
13890 #else
13891 void readnodes(m, b, nodefilename, polyfilename, polyfile)
13892 struct mesh *m;
13893 struct behavior *b;
13894 char *nodefilename;
13895 char *polyfilename;
13896 FILE **polyfile;
13897 #endif
13898
13899 {
13900 FILE *infile;
13901 vertex vertexloop;
13902 char inputline[INPUTLINESIZE];
13903 char *stringptr;
13904 char *infilename;
13905 REAL x, y;
13906 int firstnode;
13907 int nodemarkers;
13908 int currentmarker;
13909 int i, j;
13910
13911 if (b->poly) {
13912
13913 if (!b->quiet) {
13914 printf("Opening %s.\n", polyfilename);
13915 }
13916 *polyfile = fopen(polyfilename, "r");
13917 if (*polyfile == (FILE *) NULL) {
13918 printf(" Error: Cannot access file %s.\n", polyfilename);
13919 triexit(1);
13920 }
13921
13922
13923 stringptr = readline(inputline, *polyfile, polyfilename);
13924 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13925 stringptr = findfield(stringptr);
13926 if (*stringptr == '\0') {
13927 m->mesh_dim = 2;
13928 } else {
13929 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13930 }
13931 stringptr = findfield(stringptr);
13932 if (*stringptr == '\0') {
13933 m->nextras = 0;
13934 } else {
13935 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13936 }
13937 stringptr = findfield(stringptr);
13938 if (*stringptr == '\0') {
13939 nodemarkers = 0;
13940 } else {
13941 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13942 }
13943 if (m->invertices > 0) {
13944 infile = *polyfile;
13945 infilename = polyfilename;
13946 m->readnodefile = 0;
13947 } else {
13948
13949
13950 m->readnodefile = 1;
13951 infilename = nodefilename;
13952 }
13953 } else {
13954 m->readnodefile = 1;
13955 infilename = nodefilename;
13956 *polyfile = (FILE *) NULL;
13957 }
13958
13959 if (m->readnodefile) {
13960
13961 if (!b->quiet) {
13962 printf("Opening %s.\n", nodefilename);
13963 }
13964 infile = fopen(nodefilename, "r");
13965 if (infile == (FILE *) NULL) {
13966 printf(" Error: Cannot access file %s.\n", nodefilename);
13967 triexit(1);
13968 }
13969
13970
13971 stringptr = readline(inputline, infile, nodefilename);
13972 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13973 stringptr = findfield(stringptr);
13974 if (*stringptr == '\0') {
13975 m->mesh_dim = 2;
13976 } else {
13977 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13978 }
13979 stringptr = findfield(stringptr);
13980 if (*stringptr == '\0') {
13981 m->nextras = 0;
13982 } else {
13983 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13984 }
13985 stringptr = findfield(stringptr);
13986 if (*stringptr == '\0') {
13987 nodemarkers = 0;
13988 } else {
13989 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13990 }
13991 }
13992
13993 if (m->invertices < 3) {
13994 printf("Error: Input must have at least three input vertices.\n");
13995 triexit(1);
13996 }
13997 if (m->mesh_dim != 2) {
13998 printf("Error: Triangle only works with two-dimensional meshes.\n");
13999 triexit(1);
14000 }
14001 if (m->nextras == 0) {
14002 b->weighted = 0;
14003 }
14004
14005 initializevertexpool(m, b);
14006
14007
14008 for (i = 0; i < m->invertices; i++) {
14009 vertexloop = (vertex) poolalloc(&m->vertices);
14010 stringptr = readline(inputline, infile, infilename);
14011 if (i == 0) {
14012 firstnode = (int) strtol(stringptr, &stringptr, 0);
14013 if ((firstnode == 0) || (firstnode == 1)) {
14014 b->firstnumber = firstnode;
14015 }
14016 }
14017 stringptr = findfield(stringptr);
14018 if (*stringptr == '\0') {
14019 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14020 triexit(1);
14021 }
14022 x = (REAL) strtod(stringptr, &stringptr);
14023 stringptr = findfield(stringptr);
14024 if (*stringptr == '\0') {
14025 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14026 triexit(1);
14027 }
14028 y = (REAL) strtod(stringptr, &stringptr);
14029 vertexloop[0] = x;
14030 vertexloop[1] = y;
14031
14032 for (j = 2; j < 2 + m->nextras; j++) {
14033 stringptr = findfield(stringptr);
14034 if (*stringptr == '\0') {
14035 vertexloop[j] = 0.0;
14036 } else {
14037 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14038 }
14039 }
14040 if (nodemarkers) {
14041
14042 stringptr = findfield(stringptr);
14043 if (*stringptr == '\0') {
14044 setvertexmark(vertexloop, 0);
14045 } else {
14046 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14047 setvertexmark(vertexloop, currentmarker);
14048 }
14049 } else {
14050
14051 setvertexmark(vertexloop, 0);
14052 }
14053 setvertextype(vertexloop, INPUTVERTEX);
14054
14055 if (i == 0) {
14056 m->xmin = m->xmax = x;
14057 m->ymin = m->ymax = y;
14058 } else {
14059 m->xmin = (x < m->xmin) ? x : m->xmin;
14060 m->xmax = (x > m->xmax) ? x : m->xmax;
14061 m->ymin = (y < m->ymin) ? y : m->ymin;
14062 m->ymax = (y > m->ymax) ? y : m->ymax;
14063 }
14064 }
14065 if (m->readnodefile) {
14066 fclose(infile);
14067 }
14068
14069
14070
14071 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14072 }
14073
14074 #endif
14075
14076
14077
14078
14079
14080
14081
14082 #ifdef TRILIBRARY
14083
14084 #ifdef ANSI_DECLARATORS
14085 void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14086 REAL *pointattriblist, int *pointmarkerlist,
14087 int numberofpoints, int numberofpointattribs)
14088 #else
14089 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14090 numberofpoints, numberofpointattribs)
14091 struct mesh *m;
14092 struct behavior *b;
14093 REAL *pointlist;
14094 REAL *pointattriblist;
14095 int *pointmarkerlist;
14096 int numberofpoints;
14097 int numberofpointattribs;
14098 #endif
14099
14100 {
14101 vertex vertexloop;
14102 REAL x, y;
14103 int i, j;
14104 int coordindex;
14105 int attribindex;
14106
14107 m->invertices = numberofpoints;
14108 m->mesh_dim = 2;
14109 m->nextras = numberofpointattribs;
14110 m->readnodefile = 0;
14111 if (m->invertices < 3) {
14112 printf("Error: Input must have at least three input vertices.\n");
14113 triexit(1);
14114 }
14115 if (m->nextras == 0) {
14116 b->weighted = 0;
14117 }
14118
14119 initializevertexpool(m, b);
14120
14121
14122 coordindex = 0;
14123 attribindex = 0;
14124 for (i = 0; i < m->invertices; i++) {
14125 vertexloop = (vertex) poolalloc(&m->vertices);
14126
14127 x = vertexloop[0] = pointlist[coordindex++];
14128 y = vertexloop[1] = pointlist[coordindex++];
14129
14130 for (j = 0; j < numberofpointattribs; j++) {
14131 vertexloop[2 + j] = pointattriblist[attribindex++];
14132 }
14133 if (pointmarkerlist != (int *) NULL) {
14134
14135 setvertexmark(vertexloop, pointmarkerlist[i]);
14136 } else {
14137
14138 setvertexmark(vertexloop, 0);
14139 }
14140 setvertextype(vertexloop, INPUTVERTEX);
14141
14142 if (i == 0) {
14143 m->xmin = m->xmax = x;
14144 m->ymin = m->ymax = y;
14145 } else {
14146 m->xmin = (x < m->xmin) ? x : m->xmin;
14147 m->xmax = (x > m->xmax) ? x : m->xmax;
14148 m->ymin = (y < m->ymin) ? y : m->ymin;
14149 m->ymax = (y > m->ymax) ? y : m->ymax;
14150 }
14151 }
14152
14153
14154
14155 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14156 }
14157
14158 #endif
14159
14160
14161
14162
14163
14164
14165
14166
14167 #ifndef TRILIBRARY
14168
14169 #ifdef ANSI_DECLARATORS
14170 void readholes(struct mesh *m, struct behavior *b,
14171 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14172 REAL **rlist, int *regions)
14173 #else
14174 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14175 struct mesh *m;
14176 struct behavior *b;
14177 FILE *polyfile;
14178 char *polyfilename;
14179 REAL **hlist;
14180 int *holes;
14181 REAL **rlist;
14182 int *regions;
14183 #endif
14184
14185 {
14186 REAL *holelist;
14187 REAL *regionlist;
14188 char inputline[INPUTLINESIZE];
14189 char *stringptr;
14190 int index;
14191 int i;
14192
14193
14194 stringptr = readline(inputline, polyfile, polyfilename);
14195 *holes = (int) strtol(stringptr, &stringptr, 0);
14196 if (*holes > 0) {
14197 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14198 *hlist = holelist;
14199 for (i = 0; i < 2 * *holes; i += 2) {
14200 stringptr = readline(inputline, polyfile, polyfilename);
14201 stringptr = findfield(stringptr);
14202 if (*stringptr == '\0') {
14203 printf("Error: Hole %d has no x coordinate.\n",
14204 b->firstnumber + (i >> 1));
14205 triexit(1);
14206 } else {
14207 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14208 }
14209 stringptr = findfield(stringptr);
14210 if (*stringptr == '\0') {
14211 printf("Error: Hole %d has no y coordinate.\n",
14212 b->firstnumber + (i >> 1));
14213 triexit(1);
14214 } else {
14215 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14216 }
14217 }
14218 } else {
14219 *hlist = (REAL *) NULL;
14220 }
14221
14222 #ifndef CDT_ONLY
14223 if ((b->regionattrib || b->vararea) && !b->refine) {
14224
14225 stringptr = readline(inputline, polyfile, polyfilename);
14226 *regions = (int) strtol(stringptr, &stringptr, 0);
14227 if (*regions > 0) {
14228 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14229 *rlist = regionlist;
14230 index = 0;
14231 for (i = 0; i < *regions; i++) {
14232 stringptr = readline(inputline, polyfile, polyfilename);
14233 stringptr = findfield(stringptr);
14234 if (*stringptr == '\0') {
14235 printf("Error: Region %d has no x coordinate.\n",
14236 b->firstnumber + i);
14237 triexit(1);
14238 } else {
14239 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14240 }
14241 stringptr = findfield(stringptr);
14242 if (*stringptr == '\0') {
14243 printf("Error: Region %d has no y coordinate.\n",
14244 b->firstnumber + i);
14245 triexit(1);
14246 } else {
14247 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14248 }
14249 stringptr = findfield(stringptr);
14250 if (*stringptr == '\0') {
14251 printf(
14252 "Error: Region %d has no region attribute or area constraint.\n",
14253 b->firstnumber + i);
14254 triexit(1);
14255 } else {
14256 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14257 }
14258 stringptr = findfield(stringptr);
14259 if (*stringptr == '\0') {
14260 regionlist[index] = regionlist[index - 1];
14261 } else {
14262 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14263 }
14264 index++;
14265 }
14266 }
14267 } else {
14268
14269 *regions = 0;
14270 *rlist = (REAL *) NULL;
14271 }
14272 #endif
14273
14274 fclose(polyfile);
14275 }
14276
14277 #endif
14278
14279
14280
14281
14282
14283
14284
14285
14286 #ifndef TRILIBRARY
14287
14288 #ifdef ANSI_DECLARATORS
14289 void finishfile(FILE *outfile, int argc, char **argv)
14290 #else
14291 void finishfile(outfile, argc, argv)
14292 FILE *outfile;
14293 int argc;
14294 char **argv;
14295 #endif
14296
14297 {
14298 int i;
14299
14300 fprintf(outfile, "# Generated by");
14301 for (i = 0; i < argc; i++) {
14302 fprintf(outfile, " ");
14303 fputs(argv[i], outfile);
14304 }
14305 fprintf(outfile, "\n");
14306 fclose(outfile);
14307 }
14308
14309 #endif
14310
14311
14312
14313
14314
14315
14316
14317
14318
14319
14320 #ifdef TRILIBRARY
14321
14322 #ifdef ANSI_DECLARATORS
14323 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14324 REAL **pointattriblist, int **pointmarkerlist)
14325 #else
14326 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14327 struct mesh *m;
14328 struct behavior *b;
14329 REAL **pointlist;
14330 REAL **pointattriblist;
14331 int **pointmarkerlist;
14332 #endif
14333
14334 #else
14335
14336 #ifdef ANSI_DECLARATORS
14337 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14338 int argc, char **argv)
14339 #else
14340 void writenodes(m, b, nodefilename, argc, argv)
14341 struct mesh *m;
14342 struct behavior *b;
14343 char *nodefilename;
14344 int argc;
14345 char **argv;
14346 #endif
14347
14348 #endif
14349
14350 {
14351 #ifdef TRILIBRARY
14352 REAL *plist;
14353 REAL *palist;
14354 int *pmlist;
14355 int coordindex;
14356 int attribindex;
14357 #else
14358 FILE *outfile;
14359 #endif
14360 vertex vertexloop;
14361 long outvertices;
14362 int vertexnumber;
14363 int i;
14364
14365 if (b->jettison) {
14366 outvertices = m->vertices.items - m->undeads;
14367 } else {
14368 outvertices = m->vertices.items;
14369 }
14370
14371 #ifdef TRILIBRARY
14372 if (!b->quiet) {
14373 printf("Writing vertices.\n");
14374 }
14375
14376 if (*pointlist == (REAL *) NULL) {
14377 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14378 }
14379
14380 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14381 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14382 sizeof(REAL)));
14383 }
14384
14385 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14386 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14387 }
14388 plist = *pointlist;
14389 palist = *pointattriblist;
14390 pmlist = *pointmarkerlist;
14391 coordindex = 0;
14392 attribindex = 0;
14393 #else
14394 if (!b->quiet) {
14395 printf("Writing %s.\n", nodefilename);
14396 }
14397 outfile = fopen(nodefilename, "w");
14398 if (outfile == (FILE *) NULL) {
14399 printf(" Error: Cannot create file %s.\n", nodefilename);
14400 triexit(1);
14401 }
14402
14403
14404 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14405 m->nextras, 1 - b->nobound);
14406 #endif
14407
14408 traversalinit(&m->vertices);
14409 vertexnumber = b->firstnumber;
14410 vertexloop = vertextraverse(m);
14411 while (vertexloop != (vertex) NULL) {
14412 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14413 #ifdef TRILIBRARY
14414
14415 plist[coordindex++] = vertexloop[0];
14416 plist[coordindex++] = vertexloop[1];
14417
14418 for (i = 0; i < m->nextras; i++) {
14419 palist[attribindex++] = vertexloop[2 + i];
14420 }
14421 if (!b->nobound) {
14422
14423 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14424 }
14425 #else
14426
14427 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14428 vertexloop[1]);
14429 for (i = 0; i < m->nextras; i++) {
14430
14431 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14432 }
14433 if (b->nobound) {
14434 fprintf(outfile, "\n");
14435 } else {
14436
14437 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14438 }
14439 #endif
14440
14441 setvertexmark(vertexloop, vertexnumber);
14442 vertexnumber++;
14443 }
14444 vertexloop = vertextraverse(m);
14445 }
14446
14447 #ifndef TRILIBRARY
14448 finishfile(outfile, argc, argv);
14449 #endif
14450 }
14451
14452
14453
14454
14455
14456
14457
14458
14459
14460
14461
14462 #ifdef ANSI_DECLARATORS
14463 void numbernodes(struct mesh *m, struct behavior *b)
14464 #else
14465 void numbernodes(m, b)
14466 struct mesh *m;
14467 struct behavior *b;
14468 #endif
14469
14470 {
14471 vertex vertexloop;
14472 int vertexnumber;
14473
14474 traversalinit(&m->vertices);
14475 vertexnumber = b->firstnumber;
14476 vertexloop = vertextraverse(m);
14477 while (vertexloop != (vertex) NULL) {
14478 setvertexmark(vertexloop, vertexnumber);
14479 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14480 vertexnumber++;
14481 }
14482 vertexloop = vertextraverse(m);
14483 }
14484 }
14485
14486
14487
14488
14489
14490
14491
14492 #ifdef TRILIBRARY
14493
14494 #ifdef ANSI_DECLARATORS
14495 void writeelements(struct mesh *m, struct behavior *b,
14496 int **trianglelist, REAL **triangleattriblist)
14497 #else
14498 void writeelements(m, b, trianglelist, triangleattriblist)
14499 struct mesh *m;
14500 struct behavior *b;
14501 int **trianglelist;
14502 REAL **triangleattriblist;
14503 #endif
14504
14505 #else
14506
14507 #ifdef ANSI_DECLARATORS
14508 void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14509 int argc, char **argv)
14510 #else
14511 void writeelements(m, b, elefilename, argc, argv)
14512 struct mesh *m;
14513 struct behavior *b;
14514 char *elefilename;
14515 int argc;
14516 char **argv;
14517 #endif
14518
14519 #endif
14520
14521 {
14522 #ifdef TRILIBRARY
14523 int *tlist;
14524 REAL *talist;
14525 int vertexindex;
14526 int attribindex;
14527 #else
14528 FILE *outfile;
14529 #endif
14530 struct otri triangleloop;
14531 vertex p1, p2, p3;
14532 vertex mid1, mid2, mid3;
14533 long elementnumber;
14534 int i;
14535
14536 #ifdef TRILIBRARY
14537 if (!b->quiet) {
14538 printf("Writing triangles.\n");
14539 }
14540
14541 if (*trianglelist == (int *) NULL) {
14542 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14543 ((b->order + 1) * (b->order + 2) /
14544 2) * sizeof(int)));
14545 }
14546
14547 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14548 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14549 m->eextras *
14550 sizeof(REAL)));
14551 }
14552 tlist = *trianglelist;
14553 talist = *triangleattriblist;
14554 vertexindex = 0;
14555 attribindex = 0;
14556 #else
14557 if (!b->quiet) {
14558 printf("Writing %s.\n", elefilename);
14559 }
14560 outfile = fopen(elefilename, "w");
14561 if (outfile == (FILE *) NULL) {
14562 printf(" Error: Cannot create file %s.\n", elefilename);
14563 triexit(1);
14564 }
14565
14566 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14567 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14568 #endif
14569
14570 traversalinit(&m->triangles);
14571 triangleloop.tri = triangletraverse(m);
14572 triangleloop.orient = 0;
14573 elementnumber = b->firstnumber;
14574 while (triangleloop.tri != (triangle *) NULL) {
14575 org(triangleloop, p1);
14576 dest(triangleloop, p2);
14577 apex(triangleloop, p3);
14578 if (b->order == 1) {
14579 #ifdef TRILIBRARY
14580 tlist[vertexindex++] = vertexmark(p1);
14581 tlist[vertexindex++] = vertexmark(p2);
14582 tlist[vertexindex++] = vertexmark(p3);
14583 #else
14584
14585 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14586 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14587 #endif
14588 } else {
14589 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14590 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14591 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14592 #ifdef TRILIBRARY
14593 tlist[vertexindex++] = vertexmark(p1);
14594 tlist[vertexindex++] = vertexmark(p2);
14595 tlist[vertexindex++] = vertexmark(p3);
14596 tlist[vertexindex++] = vertexmark(mid1);
14597 tlist[vertexindex++] = vertexmark(mid2);
14598 tlist[vertexindex++] = vertexmark(mid3);
14599 #else
14600
14601 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14602 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14603 vertexmark(mid2), vertexmark(mid3));
14604 #endif
14605 }
14606
14607 #ifdef TRILIBRARY
14608 for (i = 0; i < m->eextras; i++) {
14609 talist[attribindex++] = elemattribute(triangleloop, i);
14610 }
14611 #else
14612 for (i = 0; i < m->eextras; i++) {
14613 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14614 }
14615 fprintf(outfile, "\n");
14616 #endif
14617
14618 triangleloop.tri = triangletraverse(m);
14619 elementnumber++;
14620 }
14621
14622 #ifndef TRILIBRARY
14623 finishfile(outfile, argc, argv);
14624 #endif
14625 }
14626
14627
14628
14629
14630
14631
14632
14633 #ifdef TRILIBRARY
14634
14635 #ifdef ANSI_DECLARATORS
14636 void writepoly(struct mesh *m, struct behavior *b,
14637 int **segmentlist, int **segmentmarkerlist)
14638 #else
14639 void writepoly(m, b, segmentlist, segmentmarkerlist)
14640 struct mesh *m;
14641 struct behavior *b;
14642 int **segmentlist;
14643 int **segmentmarkerlist;
14644 #endif
14645
14646 #else
14647
14648 #ifdef ANSI_DECLARATORS
14649 void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14650 REAL *holelist, int holes, REAL *regionlist, int regions,
14651 int argc, char **argv)
14652 #else
14653 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14654 argc, argv)
14655 struct mesh *m;
14656 struct behavior *b;
14657 char *polyfilename;
14658 REAL *holelist;
14659 int holes;
14660 REAL *regionlist;
14661 int regions;
14662 int argc;
14663 char **argv;
14664 #endif
14665
14666 #endif
14667
14668 {
14669 #ifdef TRILIBRARY
14670 int *slist;
14671 int *smlist;
14672 int index;
14673 #else
14674 FILE *outfile;
14675 long holenumber, regionnumber;
14676 #endif
14677 struct osub subsegloop;
14678 vertex endpoint1, endpoint2;
14679 long subsegnumber;
14680
14681 #ifdef TRILIBRARY
14682 if (!b->quiet) {
14683 printf("Writing segments.\n");
14684 }
14685
14686 if (*segmentlist == (int *) NULL) {
14687 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14688 sizeof(int)));
14689 }
14690
14691 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14692 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14693 sizeof(int)));
14694 }
14695 slist = *segmentlist;
14696 smlist = *segmentmarkerlist;
14697 index = 0;
14698 #else
14699 if (!b->quiet) {
14700 printf("Writing %s.\n", polyfilename);
14701 }
14702 outfile = fopen(polyfilename, "w");
14703 if (outfile == (FILE *) NULL) {
14704 printf(" Error: Cannot create file %s.\n", polyfilename);
14705 triexit(1);
14706 }
14707
14708
14709
14710 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14711 1 - b->nobound);
14712
14713 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14714 #endif
14715
14716 traversalinit(&m->subsegs);
14717 subsegloop.ss = subsegtraverse(m);
14718 subsegloop.ssorient = 0;
14719 subsegnumber = b->firstnumber;
14720 while (subsegloop.ss != (subseg *) NULL) {
14721 sorg(subsegloop, endpoint1);
14722 sdest(subsegloop, endpoint2);
14723 #ifdef TRILIBRARY
14724
14725 slist[index++] = vertexmark(endpoint1);
14726 slist[index++] = vertexmark(endpoint2);
14727 if (!b->nobound) {
14728
14729 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14730 }
14731 #else
14732
14733 if (b->nobound) {
14734 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14735 vertexmark(endpoint1), vertexmark(endpoint2));
14736 } else {
14737 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14738 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14739 }
14740 #endif
14741
14742 subsegloop.ss = subsegtraverse(m);
14743 subsegnumber++;
14744 }
14745
14746 #ifndef TRILIBRARY
14747 #ifndef CDT_ONLY
14748 fprintf(outfile, "%d\n", holes);
14749 if (holes > 0) {
14750 for (holenumber = 0; holenumber < holes; holenumber++) {
14751
14752 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14753 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14754 }
14755 }
14756 if (regions > 0) {
14757 fprintf(outfile, "%d\n", regions);
14758 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14759
14760 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14761 b->firstnumber + regionnumber,
14762 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14763 regionlist[4 * regionnumber + 2],
14764 regionlist[4 * regionnumber + 3]);
14765 }
14766 }
14767 #endif
14768
14769 finishfile(outfile, argc, argv);
14770 #endif
14771 }
14772
14773
14774
14775
14776
14777
14778
14779 #ifdef TRILIBRARY
14780
14781 #ifdef ANSI_DECLARATORS
14782 void writeedges(struct mesh *m, struct behavior *b,
14783 int **edgelist, int **edgemarkerlist)
14784 #else
14785 void writeedges(m, b, edgelist, edgemarkerlist)
14786 struct mesh *m;
14787 struct behavior *b;
14788 int **edgelist;
14789 int **edgemarkerlist;
14790 #endif
14791
14792 #else
14793
14794 #ifdef ANSI_DECLARATORS
14795 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14796 int argc, char **argv)
14797 #else
14798 void writeedges(m, b, edgefilename, argc, argv)
14799 struct mesh *m;
14800 struct behavior *b;
14801 char *edgefilename;
14802 int argc;
14803 char **argv;
14804 #endif
14805
14806 #endif
14807
14808 {
14809 #ifdef TRILIBRARY
14810 int *elist;
14811 int *emlist;
14812 int index;
14813 #else
14814 FILE *outfile;
14815 #endif
14816 struct otri triangleloop, trisym;
14817 struct osub checkmark;
14818 vertex p1, p2;
14819 long edgenumber;
14820 triangle ptr;
14821 subseg sptr;
14822
14823 #ifdef TRILIBRARY
14824 if (!b->quiet) {
14825 printf("Writing edges.\n");
14826 }
14827
14828 if (*edgelist == (int *) NULL) {
14829 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14830 }
14831
14832 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14833 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14834 }
14835 elist = *edgelist;
14836 emlist = *edgemarkerlist;
14837 index = 0;
14838 #else
14839 if (!b->quiet) {
14840 printf("Writing %s.\n", edgefilename);
14841 }
14842 outfile = fopen(edgefilename, "w");
14843 if (outfile == (FILE *) NULL) {
14844 printf(" Error: Cannot create file %s.\n", edgefilename);
14845 triexit(1);
14846 }
14847
14848 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14849 #endif
14850
14851 traversalinit(&m->triangles);
14852 triangleloop.tri = triangletraverse(m);
14853 edgenumber = b->firstnumber;
14854
14855
14856
14857
14858
14859
14860 while (triangleloop.tri != (triangle *) NULL) {
14861 for (triangleloop.orient = 0; triangleloop.orient < 3;
14862 triangleloop.orient++) {
14863 sym(triangleloop, trisym);
14864 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14865 org(triangleloop, p1);
14866 dest(triangleloop, p2);
14867 #ifdef TRILIBRARY
14868 elist[index++] = vertexmark(p1);
14869 elist[index++] = vertexmark(p2);
14870 #endif
14871 if (b->nobound) {
14872 #ifndef TRILIBRARY
14873
14874 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14875 vertexmark(p1), vertexmark(p2));
14876 #endif
14877 } else {
14878
14879
14880 if (b->usesegments) {
14881 tspivot(triangleloop, checkmark);
14882 if (checkmark.ss == m->dummysub) {
14883 #ifdef TRILIBRARY
14884 emlist[edgenumber - b->firstnumber] = 0;
14885 #else
14886 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14887 vertexmark(p1), vertexmark(p2), 0);
14888 #endif
14889 } else {
14890 #ifdef TRILIBRARY
14891 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14892 #else
14893 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14894 vertexmark(p1), vertexmark(p2), mark(checkmark));
14895 #endif
14896 }
14897 } else {
14898 #ifdef TRILIBRARY
14899 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14900 #else
14901 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14902 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14903 #endif
14904 }
14905 }
14906 edgenumber++;
14907 }
14908 }
14909 triangleloop.tri = triangletraverse(m);
14910 }
14911
14912 #ifndef TRILIBRARY
14913 finishfile(outfile, argc, argv);
14914 #endif
14915 }
14916
14917
14918
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933 #ifdef TRILIBRARY
14934
14935 #ifdef ANSI_DECLARATORS
14936 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14937 REAL **vpointattriblist, int **vpointmarkerlist,
14938 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14939 #else
14940 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14941 vedgelist, vedgemarkerlist, vnormlist)
14942 struct mesh *m;
14943 struct behavior *b;
14944 REAL **vpointlist;
14945 REAL **vpointattriblist;
14946 int **vpointmarkerlist;
14947 int **vedgelist;
14948 int **vedgemarkerlist;
14949 REAL **vnormlist;
14950 #endif
14951
14952 #else
14953
14954 #ifdef ANSI_DECLARATORS
14955 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14956 char *vedgefilename, int argc, char **argv)
14957 #else
14958 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14959 struct mesh *m;
14960 struct behavior *b;
14961 char *vnodefilename;
14962 char *vedgefilename;
14963 int argc;
14964 char **argv;
14965 #endif
14966
14967 #endif
14968
14969 {
14970 #ifdef TRILIBRARY
14971 REAL *plist;
14972 REAL *palist;
14973 int *elist;
14974 REAL *normlist;
14975 int coordindex;
14976 int attribindex;
14977 #else
14978 FILE *outfile;
14979 #endif
14980 struct otri triangleloop, trisym;
14981 vertex torg, tdest, tapex;
14982 REAL circumcenter[2];
14983 REAL xi, eta;
14984 long vnodenumber, vedgenumber;
14985 int p1, p2;
14986 int i;
14987 triangle ptr;
14988
14989 #ifdef TRILIBRARY
14990 if (!b->quiet) {
14991 printf("Writing Voronoi vertices.\n");
14992 }
14993
14994 if (*vpointlist == (REAL *) NULL) {
14995 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14996 sizeof(REAL)));
14997 }
14998
14999 if (*vpointattriblist == (REAL *) NULL) {
15000 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15001 m->nextras * sizeof(REAL)));
15002 }
15003 *vpointmarkerlist = (int *) NULL;
15004 plist = *vpointlist;
15005 palist = *vpointattriblist;
15006 coordindex = 0;
15007 attribindex = 0;
15008 #else
15009 if (!b->quiet) {
15010 printf("Writing %s.\n", vnodefilename);
15011 }
15012 outfile = fopen(vnodefilename, "w");
15013 if (outfile == (FILE *) NULL) {
15014 printf(" Error: Cannot create file %s.\n", vnodefilename);
15015 triexit(1);
15016 }
15017
15018
15019 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15020 #endif
15021
15022 traversalinit(&m->triangles);
15023 triangleloop.tri = triangletraverse(m);
15024 triangleloop.orient = 0;
15025 vnodenumber = b->firstnumber;
15026 while (triangleloop.tri != (triangle *) NULL) {
15027 org(triangleloop, torg);
15028 dest(triangleloop, tdest);
15029 apex(triangleloop, tapex);
15030 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15031 #ifdef TRILIBRARY
15032
15033 plist[coordindex++] = circumcenter[0];
15034 plist[coordindex++] = circumcenter[1];
15035 for (i = 2; i < 2 + m->nextras; i++) {
15036
15037 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15038 + eta * (tapex[i] - torg[i]);
15039 }
15040 #else
15041
15042 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15043 circumcenter[1]);
15044 for (i = 2; i < 2 + m->nextras; i++) {
15045
15046 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15047 + eta * (tapex[i] - torg[i]));
15048 }
15049 fprintf(outfile, "\n");
15050 #endif
15051
15052 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15053 triangleloop.tri = triangletraverse(m);
15054 vnodenumber++;
15055 }
15056
15057 #ifndef TRILIBRARY
15058 finishfile(outfile, argc, argv);
15059 #endif
15060
15061 #ifdef TRILIBRARY
15062 if (!b->quiet) {
15063 printf("Writing Voronoi edges.\n");
15064 }
15065
15066 if (*vedgelist == (int *) NULL) {
15067 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15068 }
15069 *vedgemarkerlist = (int *) NULL;
15070
15071 if (*vnormlist == (REAL *) NULL) {
15072 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15073 }
15074 elist = *vedgelist;
15075 normlist = *vnormlist;
15076 coordindex = 0;
15077 #else
15078 if (!b->quiet) {
15079 printf("Writing %s.\n", vedgefilename);
15080 }
15081 outfile = fopen(vedgefilename, "w");
15082 if (outfile == (FILE *) NULL) {
15083 printf(" Error: Cannot create file %s.\n", vedgefilename);
15084 triexit(1);
15085 }
15086
15087 fprintf(outfile, "%ld %d\n", m->edges, 0);
15088 #endif
15089
15090 traversalinit(&m->triangles);
15091 triangleloop.tri = triangletraverse(m);
15092 vedgenumber = b->firstnumber;
15093
15094
15095
15096
15097
15098
15099 while (triangleloop.tri != (triangle *) NULL) {
15100 for (triangleloop.orient = 0; triangleloop.orient < 3;
15101 triangleloop.orient++) {
15102 sym(triangleloop, trisym);
15103 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15104
15105 p1 = * (int *) (triangleloop.tri + 6);
15106 if (trisym.tri == m->dummytri) {
15107 org(triangleloop, torg);
15108 dest(triangleloop, tdest);
15109 #ifdef TRILIBRARY
15110
15111 elist[coordindex] = p1;
15112 normlist[coordindex++] = tdest[1] - torg[1];
15113 elist[coordindex] = -1;
15114 normlist[coordindex++] = torg[0] - tdest[0];
15115 #else
15116
15117
15118
15119 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15120 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15121 #endif
15122 } else {
15123
15124 p2 = * (int *) (trisym.tri + 6);
15125
15126 #ifdef TRILIBRARY
15127 elist[coordindex] = p1;
15128 normlist[coordindex++] = 0.0;
15129 elist[coordindex] = p2;
15130 normlist[coordindex++] = 0.0;
15131 #else
15132 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15133 #endif
15134 }
15135 vedgenumber++;
15136 }
15137 }
15138 triangleloop.tri = triangletraverse(m);
15139 }
15140
15141 #ifndef TRILIBRARY
15142 finishfile(outfile, argc, argv);
15143 #endif
15144 }
15145
15146 #ifdef TRILIBRARY
15147
15148 #ifdef ANSI_DECLARATORS
15149 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15150 #else
15151 void writeneighbors(m, b, neighborlist)
15152 struct mesh *m;
15153 struct behavior *b;
15154 int **neighborlist;
15155 #endif
15156
15157 #else
15158
15159 #ifdef ANSI_DECLARATORS
15160 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15161 int argc, char **argv)
15162 #else
15163 void writeneighbors(m, b, neighborfilename, argc, argv)
15164 struct mesh *m;
15165 struct behavior *b;
15166 char *neighborfilename;
15167 int argc;
15168 char **argv;
15169 #endif
15170
15171 #endif
15172
15173 {
15174 #ifdef TRILIBRARY
15175 int *nlist;
15176 int index;
15177 #else
15178 FILE *outfile;
15179 #endif
15180 struct otri triangleloop, trisym;
15181 long elementnumber;
15182 int neighbor1, neighbor2, neighbor3;
15183 triangle ptr;
15184
15185 #ifdef TRILIBRARY
15186 if (!b->quiet) {
15187 printf("Writing neighbors.\n");
15188 }
15189
15190 if (*neighborlist == (int *) NULL) {
15191 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15192 sizeof(int)));
15193 }
15194 nlist = *neighborlist;
15195 index = 0;
15196 #else
15197 if (!b->quiet) {
15198 printf("Writing %s.\n", neighborfilename);
15199 }
15200 outfile = fopen(neighborfilename, "w");
15201 if (outfile == (FILE *) NULL) {
15202 printf(" Error: Cannot create file %s.\n", neighborfilename);
15203 triexit(1);
15204 }
15205
15206 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15207 #endif
15208
15209 traversalinit(&m->triangles);
15210 triangleloop.tri = triangletraverse(m);
15211 triangleloop.orient = 0;
15212 elementnumber = b->firstnumber;
15213 while (triangleloop.tri != (triangle *) NULL) {
15214 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15215 triangleloop.tri = triangletraverse(m);
15216 elementnumber++;
15217 }
15218 * (int *) (m->dummytri + 6) = -1;
15219
15220 traversalinit(&m->triangles);
15221 triangleloop.tri = triangletraverse(m);
15222 elementnumber = b->firstnumber;
15223 while (triangleloop.tri != (triangle *) NULL) {
15224 triangleloop.orient = 1;
15225 sym(triangleloop, trisym);
15226 neighbor1 = * (int *) (trisym.tri + 6);
15227 triangleloop.orient = 2;
15228 sym(triangleloop, trisym);
15229 neighbor2 = * (int *) (trisym.tri + 6);
15230 triangleloop.orient = 0;
15231 sym(triangleloop, trisym);
15232 neighbor3 = * (int *) (trisym.tri + 6);
15233 #ifdef TRILIBRARY
15234 nlist[index++] = neighbor1;
15235 nlist[index++] = neighbor2;
15236 nlist[index++] = neighbor3;
15237 #else
15238
15239 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15240 neighbor1, neighbor2, neighbor3);
15241 #endif
15242
15243 triangleloop.tri = triangletraverse(m);
15244 elementnumber++;
15245 }
15246
15247 #ifndef TRILIBRARY
15248 finishfile(outfile, argc, argv);
15249 #endif
15250 }
15251
15252
15253
15254
15255
15256
15257
15258
15259
15260
15261 #ifndef TRILIBRARY
15262
15263 #ifdef ANSI_DECLARATORS
15264 void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15265 int argc, char **argv)
15266 #else
15267 void writeoff(m, b, offfilename, argc, argv)
15268 struct mesh *m;
15269 struct behavior *b;
15270 char *offfilename;
15271 int argc;
15272 char **argv;
15273 #endif
15274
15275 {
15276 FILE *outfile;
15277 struct otri triangleloop;
15278 vertex vertexloop;
15279 vertex p1, p2, p3;
15280 long outvertices;
15281
15282 if (!b->quiet) {
15283 printf("Writing %s.\n", offfilename);
15284 }
15285
15286 if (b->jettison) {
15287 outvertices = m->vertices.items - m->undeads;
15288 } else {
15289 outvertices = m->vertices.items;
15290 }
15291
15292 outfile = fopen(offfilename, "w");
15293 if (outfile == (FILE *) NULL) {
15294 printf(" Error: Cannot create file %s.\n", offfilename);
15295 triexit(1);
15296 }
15297
15298 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15299 m->edges);
15300
15301
15302 traversalinit(&m->vertices);
15303 vertexloop = vertextraverse(m);
15304 while (vertexloop != (vertex) NULL) {
15305 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15306
15307 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15308 0.0);
15309 }
15310 vertexloop = vertextraverse(m);
15311 }
15312
15313
15314 traversalinit(&m->triangles);
15315 triangleloop.tri = triangletraverse(m);
15316 triangleloop.orient = 0;
15317 while (triangleloop.tri != (triangle *) NULL) {
15318 org(triangleloop, p1);
15319 dest(triangleloop, p2);
15320 apex(triangleloop, p3);
15321
15322 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15323 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15324 triangleloop.tri = triangletraverse(m);
15325 }
15326 finishfile(outfile, argc, argv);
15327 }
15328
15329 #endif
15330
15333
15334
15335
15336
15337
15338
15339
15340
15341 #ifdef ANSI_DECLARATORS
15342 void quality_statistics(struct mesh *m, struct behavior *b)
15343 #else
15344 void quality_statistics(m, b)
15345 struct mesh *m;
15346 struct behavior *b;
15347 #endif
15348
15349 {
15350 struct otri triangleloop;
15351 vertex p[3];
15352 REAL cossquaretable[8];
15353 REAL ratiotable[16];
15354 REAL dx[3], dy[3];
15355 REAL edgelength[3];
15356 REAL dotproduct;
15357 REAL cossquare;
15358 REAL triarea;
15359 REAL shortest, longest;
15360 REAL trilongest2;
15361 REAL smallestarea, biggestarea;
15362 REAL triminaltitude2;
15363 REAL minaltitude;
15364 REAL triaspect2;
15365 REAL worstaspect;
15366 REAL smallestangle, biggestangle;
15367 REAL radconst, degconst;
15368 int angletable[18];
15369 int aspecttable[16];
15370 int aspectindex;
15371 int tendegree;
15372 int acutebiggest;
15373 int i, ii, j, k;
15374
15375 printf("Mesh quality statistics:\n\n");
15376 radconst = PI / 18.0;
15377 degconst = 180.0 / PI;
15378 for (i = 0; i < 8; i++) {
15379 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15380 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15381 }
15382 for (i = 0; i < 18; i++) {
15383 angletable[i] = 0;
15384 }
15385
15386 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15387 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15388 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15389 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15390 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15391 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15392 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15393 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15394 for (i = 0; i < 16; i++) {
15395 aspecttable[i] = 0;
15396 }
15397
15398 worstaspect = 0.0;
15399 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15400 minaltitude = minaltitude * minaltitude;
15401 shortest = minaltitude;
15402 longest = 0.0;
15403 smallestarea = minaltitude;
15404 biggestarea = 0.0;
15405 worstaspect = 0.0;
15406 smallestangle = 0.0;
15407 biggestangle = 2.0;
15408 acutebiggest = 1;
15409
15410 traversalinit(&m->triangles);
15411 triangleloop.tri = triangletraverse(m);
15412 triangleloop.orient = 0;
15413 while (triangleloop.tri != (triangle *) NULL) {
15414 org(triangleloop, p[0]);
15415 dest(triangleloop, p[1]);
15416 apex(triangleloop, p[2]);
15417 trilongest2 = 0.0;
15418
15419 for (i = 0; i < 3; i++) {
15420 j = plus1mod3[i];
15421 k = minus1mod3[i];
15422 dx[i] = p[j][0] - p[k][0];
15423 dy[i] = p[j][1] - p[k][1];
15424 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15425 if (edgelength[i] > trilongest2) {
15426 trilongest2 = edgelength[i];
15427 }
15428 if (edgelength[i] > longest) {
15429 longest = edgelength[i];
15430 }
15431 if (edgelength[i] < shortest) {
15432 shortest = edgelength[i];
15433 }
15434 }
15435
15436 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15437 if (triarea < smallestarea) {
15438 smallestarea = triarea;
15439 }
15440 if (triarea > biggestarea) {
15441 biggestarea = triarea;
15442 }
15443 triminaltitude2 = triarea * triarea / trilongest2;
15444 if (triminaltitude2 < minaltitude) {
15445 minaltitude = triminaltitude2;
15446 }
15447 triaspect2 = trilongest2 / triminaltitude2;
15448 if (triaspect2 > worstaspect) {
15449 worstaspect = triaspect2;
15450 }
15451 aspectindex = 0;
15452 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15453 && (aspectindex < 15)) {
15454 aspectindex++;
15455 }
15456 aspecttable[aspectindex]++;
15457
15458 for (i = 0; i < 3; i++) {
15459 j = plus1mod3[i];
15460 k = minus1mod3[i];
15461 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15462 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15463 tendegree = 8;
15464 for (ii = 7; ii >= 0; ii--) {
15465 if (cossquare > cossquaretable[ii]) {
15466 tendegree = ii;
15467 }
15468 }
15469 if (dotproduct <= 0.0) {
15470 angletable[tendegree]++;
15471 if (cossquare > smallestangle) {
15472 smallestangle = cossquare;
15473 }
15474 if (acutebiggest && (cossquare < biggestangle)) {
15475 biggestangle = cossquare;
15476 }
15477 } else {
15478 angletable[17 - tendegree]++;
15479 if (acutebiggest || (cossquare > biggestangle)) {
15480 biggestangle = cossquare;
15481 acutebiggest = 0;
15482 }
15483 }
15484 }
15485 triangleloop.tri = triangletraverse(m);
15486 }
15487
15488 shortest = sqrt(shortest);
15489 longest = sqrt(longest);
15490 minaltitude = sqrt(minaltitude);
15491 worstaspect = sqrt(worstaspect);
15492 smallestarea *= 0.5;
15493 biggestarea *= 0.5;
15494 if (smallestangle >= 1.0) {
15495 smallestangle = 0.0;
15496 } else {
15497 smallestangle = degconst * acos(sqrt(smallestangle));
15498 }
15499 if (biggestangle >= 1.0) {
15500 biggestangle = 180.0;
15501 } else {
15502 if (acutebiggest) {
15503 biggestangle = degconst * acos(sqrt(biggestangle));
15504 } else {
15505 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15506 }
15507 }
15508
15509 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15510 smallestarea, biggestarea);
15511 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15512 shortest, longest);
15513 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15514 minaltitude, worstaspect);
15515
15516 printf(" Triangle aspect ratio histogram:\n");
15517 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15518 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15519 aspecttable[8]);
15520 for (i = 1; i < 7; i++) {
15521 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15522 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15523 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15524 }
15525 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15526 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15527 aspecttable[15]);
15528 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15529
15530 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15531 smallestangle, biggestangle);
15532
15533 printf(" Angle histogram:\n");
15534 for (i = 0; i < 9; i++) {
15535 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15536 i * 10, i * 10 + 10, angletable[i],
15537 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15538 }
15539 printf("\n");
15540 }
15541
15542
15543
15544
15545
15546
15547
15548 #ifdef ANSI_DECLARATORS
15549 void statistics(struct mesh *m, struct behavior *b)
15550 #else
15551 void statistics(m, b)
15552 struct mesh *m;
15553 struct behavior *b;
15554 #endif
15555
15556 {
15557 printf("\nStatistics:\n\n");
15558 printf(" Input vertices: %d\n", m->invertices);
15559 if (b->refine) {
15560 printf(" Input triangles: %d\n", m->inelements);
15561 }
15562 if (b->poly) {
15563 printf(" Input segments: %d\n", m->insegments);
15564 if (!b->refine) {
15565 printf(" Input holes: %d\n", m->holes);
15566 }
15567 }
15568
15569 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15570 printf(" Mesh triangles: %ld\n", m->triangles.items);
15571 printf(" Mesh edges: %ld\n", m->edges);
15572 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15573 if (b->poly || b->refine) {
15574 printf(" Mesh interior boundary edges: %ld\n",
15575 m->subsegs.items - m->hullsize);
15576 printf(" Mesh subsegments (constrained edges): %ld\n",
15577 m->subsegs.items);
15578 }
15579 printf("\n");
15580
15581 if (b->verbose) {
15582 quality_statistics(m, b);
15583 printf("Memory allocation statistics:\n\n");
15584 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15585 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15586 if (m->subsegs.maxitems > 0) {
15587 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15588 }
15589 if (m->viri.maxitems > 0) {
15590 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15591 }
15592 if (m->badsubsegs.maxitems > 0) {
15593 printf(" Maximum number of encroached subsegments: %ld\n",
15594 m->badsubsegs.maxitems);
15595 }
15596 if (m->badtriangles.maxitems > 0) {
15597 printf(" Maximum number of bad triangles: %ld\n",
15598 m->badtriangles.maxitems);
15599 }
15600 if (m->flipstackers.maxitems > 0) {
15601 printf(" Maximum number of stacked triangle flips: %ld\n",
15602 m->flipstackers.maxitems);
15603 }
15604 if (m->splaynodes.maxitems > 0) {
15605 printf(" Maximum number of splay tree nodes: %ld\n",
15606 m->splaynodes.maxitems);
15607 }
15608 printf(" Approximate heap memory use (bytes): %ld\n\n",
15609 m->vertices.maxitems * m->vertices.itembytes +
15610 m->triangles.maxitems * m->triangles.itembytes +
15611 m->subsegs.maxitems * m->subsegs.itembytes +
15612 m->viri.maxitems * m->viri.itembytes +
15613 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15614 m->badtriangles.maxitems * m->badtriangles.itembytes +
15615 m->flipstackers.maxitems * m->flipstackers.itembytes +
15616 m->splaynodes.maxitems * m->splaynodes.itembytes);
15617
15618 printf("Algorithmic statistics:\n\n");
15619 if (!b->weighted) {
15620 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15621 } else {
15622 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15623 }
15624 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15625 if (m->hyperbolacount > 0) {
15626 printf(" Number of right-of-hyperbola tests: %ld\n",
15627 m->hyperbolacount);
15628 }
15629 if (m->circletopcount > 0) {
15630 printf(" Number of circle top computations: %ld\n",
15631 m->circletopcount);
15632 }
15633 if (m->circumcentercount > 0) {
15634 printf(" Number of triangle circumcenter computations: %ld\n",
15635 m->circumcentercount);
15636 }
15637 printf("\n");
15638 }
15639 }
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659
15660
15661
15662
15663
15664
15665
15666 #ifdef TRILIBRARY
15667
15668 #ifdef ANSI_DECLARATORS
15669 void triangulate(char *triswitches, struct triangulateio *in,
15670 struct triangulateio *out, struct triangulateio *vorout)
15671 #else
15672 void triangulate(triswitches, in, out, vorout)
15673 char *triswitches;
15674 struct triangulateio *in;
15675 struct triangulateio *out;
15676 struct triangulateio *vorout;
15677 #endif
15678
15679 #else
15680
15681 #ifdef ANSI_DECLARATORS
15682 int main(int argc, char **argv)
15683 #else
15684 int main(argc, argv)
15685 int argc;
15686 char **argv;
15687 #endif
15688
15689 #endif
15690
15691 {
15692 struct mesh m;
15693 struct behavior b;
15694 REAL *holearray;
15695 REAL *regionarray;
15696 #ifndef TRILIBRARY
15697 FILE *polyfile;
15698 #endif
15699 #ifndef NO_TIMER
15700
15701
15702 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15703 struct timezone tz;
15704 #endif
15705
15706 #ifndef NO_TIMER
15707 gettimeofday(&tv0, &tz);
15708 #endif
15709
15710 triangleinit(&m);
15711 #ifdef TRILIBRARY
15712 parsecommandline(1, &triswitches, &b);
15713 #else
15714 parsecommandline(argc, argv, &b);
15715 #endif
15716 m.steinerleft = b.steiner;
15717
15718 #ifdef TRILIBRARY
15719 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15720 in->pointmarkerlist, in->numberofpoints,
15721 in->numberofpointattributes);
15722 #else
15723 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15724 #endif
15725
15726 #ifndef NO_TIMER
15727 if (!b.quiet) {
15728 gettimeofday(&tv1, &tz);
15729 }
15730 #endif
15731
15732 #ifdef CDT_ONLY
15733 m.hullsize = delaunay(&m, &b);
15734 #else
15735 if (b.refine) {
15736
15737 #ifdef TRILIBRARY
15738 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15739 in->triangleattributelist, in->trianglearealist,
15740 in->numberoftriangles, in->numberofcorners,
15741 in->numberoftriangleattributes,
15742 in->segmentlist, in->segmentmarkerlist,
15743 in->numberofsegments);
15744 #else
15745 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15746 b.inpolyfilename, polyfile);
15747 #endif
15748 } else {
15749 m.hullsize = delaunay(&m, &b);
15750 }
15751 #endif
15752
15753 #ifndef NO_TIMER
15754 if (!b.quiet) {
15755 gettimeofday(&tv2, &tz);
15756 if (b.refine) {
15757 printf("Mesh reconstruction");
15758 } else {
15759 printf("Delaunay");
15760 }
15761 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15762 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15763 }
15764 #endif
15765
15766
15767
15768 m.infvertex1 = (vertex) NULL;
15769 m.infvertex2 = (vertex) NULL;
15770 m.infvertex3 = (vertex) NULL;
15771
15772 if (b.usesegments) {
15773 m.checksegments = 1;
15774 if (!b.refine) {
15775
15776 #ifdef TRILIBRARY
15777 formskeleton(&m, &b, in->segmentlist,
15778 in->segmentmarkerlist, in->numberofsegments);
15779 #else
15780 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15781 #endif
15782 }
15783 }
15784
15785 #ifndef NO_TIMER
15786 if (!b.quiet) {
15787 gettimeofday(&tv3, &tz);
15788 if (b.usesegments && !b.refine) {
15789 printf("Segment milliseconds: %ld\n",
15790 1000l * (tv3.tv_sec - tv2.tv_sec) +
15791 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15792 }
15793 }
15794 #endif
15795
15796 if (b.poly && (m.triangles.items > 0)) {
15797 #ifdef TRILIBRARY
15798 holearray = in->holelist;
15799 m.holes = in->numberofholes;
15800 regionarray = in->regionlist;
15801 m.regions = in->numberofregions;
15802 #else
15803 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15804 ®ionarray, &m.regions);
15805 #endif
15806 if (!b.refine) {
15807
15808 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15809 }
15810 } else {
15811
15812
15813
15814 m.holes = 0;
15815 m.regions = 0;
15816 }
15817
15818 #ifndef NO_TIMER
15819 if (!b.quiet) {
15820 gettimeofday(&tv4, &tz);
15821 if (b.poly && !b.refine) {
15822 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15823 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15824 }
15825 }
15826 #endif
15827
15828 #ifndef CDT_ONLY
15829 if (b.quality && (m.triangles.items > 0)) {
15830 enforcequality(&m, &b);
15831 }
15832 #endif
15833
15834 #ifndef NO_TIMER
15835 if (!b.quiet) {
15836 gettimeofday(&tv5, &tz);
15837 #ifndef CDT_ONLY
15838 if (b.quality) {
15839 printf("Quality milliseconds: %ld\n",
15840 1000l * (tv5.tv_sec - tv4.tv_sec) +
15841 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15842 }
15843 #endif
15844 }
15845 #endif
15846
15847
15848 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15849
15850 if (b.order > 1) {
15851 highorder(&m, &b);
15852 }
15853 if (!b.quiet) {
15854 printf("\n");
15855 }
15856
15857 #ifdef TRILIBRARY
15858 if (b.jettison) {
15859 out->numberofpoints = m.vertices.items - m.undeads;
15860 } else {
15861 out->numberofpoints = m.vertices.items;
15862 }
15863 out->numberofpointattributes = m.nextras;
15864 out->numberoftriangles = m.triangles.items;
15865 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15866 out->numberoftriangleattributes = m.eextras;
15867 out->numberofedges = m.edges;
15868 if (b.usesegments) {
15869 out->numberofsegments = m.subsegs.items;
15870 } else {
15871 out->numberofsegments = m.hullsize;
15872 }
15873 if (vorout != (struct triangulateio *) NULL) {
15874 vorout->numberofpoints = m.triangles.items;
15875 vorout->numberofpointattributes = m.nextras;
15876 vorout->numberofedges = m.edges;
15877 }
15878 #endif
15879
15880
15881 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15882 if (!b.quiet) {
15883 #ifdef TRILIBRARY
15884 printf("NOT writing vertices.\n");
15885 #else
15886 printf("NOT writing a .node file.\n");
15887 #endif
15888 }
15889 numbernodes(&m, &b);
15890 } else {
15891
15892 #ifdef TRILIBRARY
15893 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15894 &out->pointmarkerlist);
15895 #else
15896 writenodes(&m, &b, b.outnodefilename, argc, argv);
15897 #endif
15898 }
15899 if (b.noelewritten) {
15900 if (!b.quiet) {
15901 #ifdef TRILIBRARY
15902 printf("NOT writing triangles.\n");
15903 #else
15904 printf("NOT writing an .ele file.\n");
15905 #endif
15906 }
15907 } else {
15908 #ifdef TRILIBRARY
15909 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15910 #else
15911 writeelements(&m, &b, b.outelefilename, argc, argv);
15912 #endif
15913 }
15914
15915
15916 if (b.poly || b.convex) {
15917
15918 if (b.nopolywritten || b.noiterationnum) {
15919 if (!b.quiet) {
15920 #ifdef TRILIBRARY
15921 printf("NOT writing segments.\n");
15922 #else
15923 printf("NOT writing a .poly file.\n");
15924 #endif
15925 }
15926 } else {
15927 #ifdef TRILIBRARY
15928 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15929 out->numberofholes = m.holes;
15930 out->numberofregions = m.regions;
15931 if (b.poly) {
15932 out->holelist = in->holelist;
15933 out->regionlist = in->regionlist;
15934 } else {
15935 out->holelist = (REAL *) NULL;
15936 out->regionlist = (REAL *) NULL;
15937 }
15938 #else
15939 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15940 m.regions, argc, argv);
15941 #endif
15942 }
15943 }
15944 #ifndef TRILIBRARY
15945 #ifndef CDT_ONLY
15946 if (m.regions > 0) {
15947 trifree((VOID *) regionarray);
15948 }
15949 #endif
15950 if (m.holes > 0) {
15951 trifree((VOID *) holearray);
15952 }
15953 if (b.geomview) {
15954 writeoff(&m, &b, b.offfilename, argc, argv);
15955 }
15956 #endif
15957 if (b.edgesout) {
15958 #ifdef TRILIBRARY
15959 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15960 #else
15961 writeedges(&m, &b, b.edgefilename, argc, argv);
15962 #endif
15963 }
15964 if (b.voronoi) {
15965 #ifdef TRILIBRARY
15966 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15967 &vorout->pointmarkerlist, &vorout->edgelist,
15968 &vorout->edgemarkerlist, &vorout->normlist);
15969 #else
15970 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15971 #endif
15972 }
15973 if (b.neighbors) {
15974 #ifdef TRILIBRARY
15975 writeneighbors(&m, &b, &out->neighborlist);
15976 #else
15977 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15978 #endif
15979 }
15980
15981 if (!b.quiet) {
15982 #ifndef NO_TIMER
15983 gettimeofday(&tv6, &tz);
15984 printf("\nOutput milliseconds: %ld\n",
15985 1000l * (tv6.tv_sec - tv5.tv_sec) +
15986 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15987 printf("Total running milliseconds: %ld\n",
15988 1000l * (tv6.tv_sec - tv0.tv_sec) +
15989 (tv6.tv_usec - tv0.tv_usec) / 1000l);
15990 #endif
15991
15992 statistics(&m, &b);
15993 }
15994
15995 #ifndef REDUCED
15996 if (b.docheck) {
15997 checkmesh(&m, &b);
15998 checkdelaunay(&m, &b);
15999 }
16000 #endif
16001
16002 triangledeinit(&m, &b);
16003 #ifndef TRILIBRARY
16004 return 0;
16005 #endif
16006 }