00001 #ifndef ANSI_DECLARATORS
00002 #define ANSI_DECLARATORS
00003 #endif
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 #ifdef SINGLE
00217 #define REAL float
00218 #else
00219 #define REAL double
00220 #endif
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 #define INEXACT
00276
00277
00278
00279
00280 #define FILENAMESIZE 2048
00281
00282
00283
00284
00285 #define INPUTLINESIZE 1024
00286
00287
00288
00289
00290
00291 #define TRIPERBLOCK 4092
00292 #define SUBSEGPERBLOCK 508
00293 #define VERTEXPERBLOCK 4092
00294 #define VIRUSPERBLOCK 1020
00295
00296 #define BADSUBSEGPERBLOCK 252
00297
00298 #define BADTRIPERBLOCK 4092
00299
00300 #define FLIPSTACKERPERBLOCK 252
00301
00302 #define SPLAYNODEPERBLOCK 508
00303
00304
00305
00306
00307
00308 #define INPUTVERTEX 0
00309 #define SEGMENTVERTEX 1
00310 #define FREEVERTEX 2
00311 #define DEADVERTEX -32768
00312 #define UNDEADVERTEX -32767
00313
00314
00315
00316
00317
00318 #define VOID int
00319
00320
00321
00322
00323
00324
00325
00326 #define SAMPLEFACTOR 11
00327
00328
00329
00330
00331
00332 #define SAMPLERATE 10
00333
00334
00335
00336 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
00337
00338
00339
00340 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
00341
00342
00343
00344 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
00345
00346 #include <stdio.h>
00347 #include <stdlib.h>
00348 #include <string.h>
00349 #include <math.h>
00350 #ifndef NO_TIMER
00351 #include <sys/time.h>
00352 #endif
00353 #ifdef CPU86
00354 #include <float.h>
00355 #endif
00356 #ifdef LINUX
00357 #include <fpu_control.h>
00358 #endif
00359 #ifdef TRILIBRARY
00360 #include "triangle.h"
00361 #endif
00362
00363
00364
00365 #ifndef TRILIBRARY
00366 char *readline(char *string, FILE *infile, char *infilename);
00367 char *findfield(char *string);
00368 #endif
00369
00370
00371
00372
00373
00374 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
00375
00376
00377
00378
00379
00380
00381
00382 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
00383 DUPLICATEVERTEX};
00384
00385
00386
00387
00388
00389
00390 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 typedef REAL **triangle;
00510
00511
00512
00513
00514
00515
00516 struct otri {
00517 triangle *tri;
00518 int orient;
00519 };
00520
00521
00522
00523
00524
00525
00526 typedef REAL **subseg;
00527
00528
00529
00530
00531
00532
00533 struct osub {
00534 subseg *ss;
00535 int ssorient;
00536 };
00537
00538
00539
00540
00541
00542
00543 typedef REAL *vertex;
00544
00545
00546
00547
00548 struct badsubseg {
00549 subseg encsubseg;
00550 vertex subsegorg, subsegdest;
00551 };
00552
00553
00554
00555
00556
00557 struct badtriang {
00558 triangle poortri;
00559 REAL key;
00560 vertex triangorg, triangdest, triangapex;
00561 struct badtriang *nexttriang;
00562 };
00563
00564
00565
00566
00567
00568 struct flipstacker {
00569 triangle flippedtri;
00570 struct flipstacker *prevflip;
00571 };
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 struct event {
00584 REAL xkey, ykey;
00585 VOID *eventptr;
00586 int heapposition;
00587 };
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600 struct splaynode {
00601 struct otri keyedge;
00602 vertex keydest;
00603 struct splaynode *lchild, *rchild;
00604 };
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 struct memorypool {
00630 VOID **firstblock, **nowblock;
00631 VOID *nextitem;
00632 VOID *deaditemstack;
00633 VOID **pathblock;
00634 VOID *pathitem;
00635 int alignbytes;
00636 int itembytes;
00637 int itemsperblock;
00638 int itemsfirstblock;
00639 long items, maxitems;
00640 int unallocateditems;
00641 int pathitemsleft;
00642 };
00643
00644
00645
00646
00647 REAL splitter;
00648 REAL epsilon;
00649 REAL resulterrbound;
00650 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00651 REAL iccerrboundA, iccerrboundB, iccerrboundC;
00652 REAL o3derrboundA, o3derrboundB, o3derrboundC;
00653
00654
00655
00656 unsigned long randomseed;
00657
00658
00659
00660
00661
00662 struct mesh {
00663
00664
00665
00666
00667
00668 struct memorypool triangles;
00669 struct memorypool subsegs;
00670 struct memorypool vertices;
00671 struct memorypool viri;
00672 struct memorypool badsubsegs;
00673 struct memorypool badtriangles;
00674 struct memorypool flipstackers;
00675 struct memorypool splaynodes;
00676
00677
00678
00679
00680 struct badtriang *queuefront[4096];
00681 struct badtriang *queuetail[4096];
00682 int nextnonemptyq[4096];
00683 int firstnonemptyq;
00684
00685
00686
00687 struct flipstacker *lastflip;
00688
00689
00690
00691 REAL xmin, xmax, ymin, ymax;
00692 REAL xminextreme;
00693 int invertices;
00694 int inelements;
00695 int insegments;
00696 int holes;
00697 int regions;
00698 int undeads;
00699 long edges;
00700 int mesh_dim;
00701 int nextras;
00702 int eextras;
00703 long hullsize;
00704 int steinerleft;
00705 int vertexmarkindex;
00706 int vertex2triindex;
00707 int highorderindex;
00708 int elemattribindex;
00709 int areaboundindex;
00710 int checksegments;
00711 int checkquality;
00712 int readnodefile;
00713 long samples;
00714
00715 long incirclecount;
00716 long counterclockcount;
00717 long orient3dcount;
00718 long hyperbolacount;
00719 long circumcentercount;
00720 long circletopcount;
00721
00722
00723
00724 vertex infvertex1, infvertex2, infvertex3;
00725
00726
00727
00728 triangle *dummytri;
00729 triangle *dummytribase;
00730
00731
00732
00733
00734
00735 subseg *dummysub;
00736 subseg *dummysubbase;
00737
00738
00739
00740
00741 struct otri recenttri;
00742
00743 };
00744
00745
00746
00747
00748
00749 struct behavior {
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784 int poly, refine, quality, vararea, fixedarea, usertest;
00785 int regionattrib, convex, weighted, jettison;
00786 int firstnumber;
00787 int edgesout, voronoi, neighbors, geomview;
00788 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
00789 int noholes, noexact, conformdel;
00790 int incremental, sweepline, dwyer;
00791 int splitseg;
00792 int docheck;
00793 int quiet, verbose;
00794 int usesegments;
00795 int order;
00796 int nobisect;
00797 int steiner;
00798 REAL minangle, goodangle, offconstant;
00799 REAL maxarea;
00800
00801
00802
00803 #ifndef TRILIBRARY
00804 char innodefilename[FILENAMESIZE];
00805 char inelefilename[FILENAMESIZE];
00806 char inpolyfilename[FILENAMESIZE];
00807 char areafilename[FILENAMESIZE];
00808 char outnodefilename[FILENAMESIZE];
00809 char outelefilename[FILENAMESIZE];
00810 char outpolyfilename[FILENAMESIZE];
00811 char edgefilename[FILENAMESIZE];
00812 char vnodefilename[FILENAMESIZE];
00813 char vedgefilename[FILENAMESIZE];
00814 char neighborfilename[FILENAMESIZE];
00815 char offfilename[FILENAMESIZE];
00816 #endif
00817
00818 };
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00931
00932
00933 int plus1mod3[3] = {1, 2, 0};
00934 int minus1mod3[3] = {2, 0, 1};
00935
00936
00937
00938
00939
00940
00941
00942
00943 #define decode(ptr, otri) \
00944 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
00945 (otri).tri = (triangle *) \
00946 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
00947
00948
00949
00950
00951
00952 #define encode(otri) \
00953 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 #define sym(otri1, otri2) \
00964 ptr = (otri1).tri[(otri1).orient]; \
00965 decode(ptr, otri2);
00966
00967 #define symself(otri) \
00968 ptr = (otri).tri[(otri).orient]; \
00969 decode(ptr, otri);
00970
00971
00972
00973 #define lnext(otri1, otri2) \
00974 (otri2).tri = (otri1).tri; \
00975 (otri2).orient = plus1mod3[(otri1).orient]
00976
00977 #define lnextself(otri) \
00978 (otri).orient = plus1mod3[(otri).orient]
00979
00980
00981
00982 #define lprev(otri1, otri2) \
00983 (otri2).tri = (otri1).tri; \
00984 (otri2).orient = minus1mod3[(otri1).orient]
00985
00986 #define lprevself(otri) \
00987 (otri).orient = minus1mod3[(otri).orient]
00988
00989
00990
00991
00992
00993 #define onext(otri1, otri2) \
00994 lprev(otri1, otri2); \
00995 symself(otri2);
00996
00997 #define onextself(otri) \
00998 lprevself(otri); \
00999 symself(otri);
01000
01001
01002
01003
01004
01005 #define oprev(otri1, otri2) \
01006 sym(otri1, otri2); \
01007 lnextself(otri2);
01008
01009 #define oprevself(otri) \
01010 symself(otri); \
01011 lnextself(otri);
01012
01013
01014
01015
01016
01017 #define dnext(otri1, otri2) \
01018 sym(otri1, otri2); \
01019 lprevself(otri2);
01020
01021 #define dnextself(otri) \
01022 symself(otri); \
01023 lprevself(otri);
01024
01025
01026
01027
01028
01029 #define dprev(otri1, otri2) \
01030 lnext(otri1, otri2); \
01031 symself(otri2);
01032
01033 #define dprevself(otri) \
01034 lnextself(otri); \
01035 symself(otri);
01036
01037
01038
01039
01040
01041 #define rnext(otri1, otri2) \
01042 sym(otri1, otri2); \
01043 lnextself(otri2); \
01044 symself(otri2);
01045
01046 #define rnextself(otri) \
01047 symself(otri); \
01048 lnextself(otri); \
01049 symself(otri);
01050
01051
01052
01053
01054
01055 #define rprev(otri1, otri2) \
01056 sym(otri1, otri2); \
01057 lprevself(otri2); \
01058 symself(otri2);
01059
01060 #define rprevself(otri) \
01061 symself(otri); \
01062 lprevself(otri); \
01063 symself(otri);
01064
01065
01066
01067
01068 #define org(otri, vertexptr) \
01069 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
01070
01071 #define dest(otri, vertexptr) \
01072 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
01073
01074 #define apex(otri, vertexptr) \
01075 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
01076
01077 #define setorg(otri, vertexptr) \
01078 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01079
01080 #define setdest(otri, vertexptr) \
01081 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01082
01083 #define setapex(otri, vertexptr) \
01084 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
01085
01086
01087
01088 #define bond(otri1, otri2) \
01089 (otri1).tri[(otri1).orient] = encode(otri2); \
01090 (otri2).tri[(otri2).orient] = encode(otri1)
01091
01092
01093
01094
01095
01096
01097 #define dissolve(otri) \
01098 (otri).tri[(otri).orient] = (triangle) m->dummytri
01099
01100
01101
01102 #define otricopy(otri1, otri2) \
01103 (otri2).tri = (otri1).tri; \
01104 (otri2).orient = (otri1).orient
01105
01106
01107
01108 #define otriequal(otri1, otri2) \
01109 (((otri1).tri == (otri2).tri) && \
01110 ((otri1).orient == (otri2).orient))
01111
01112
01113
01114
01115 #define infect(otri) \
01116 (otri).tri[6] = (triangle) \
01117 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
01118
01119 #define uninfect(otri) \
01120 (otri).tri[6] = (triangle) \
01121 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
01122
01123
01124
01125 #define infected(otri) \
01126 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
01127
01128
01129
01130 #define elemattribute(otri, attnum) \
01131 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
01132
01133 #define setelemattribute(otri, attnum, value) \
01134 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
01135
01136
01137
01138 #define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
01139
01140 #define setareabound(otri, value) \
01141 ((REAL *) (otri).tri)[m->areaboundindex] = value
01142
01143
01144
01145
01146
01147
01148 #define deadtri(tria) ((tria)[1] == (triangle) NULL)
01149
01150 #define killtri(tria) \
01151 (tria)[1] = (triangle) NULL; \
01152 (tria)[3] = (triangle) NULL
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 #define sdecode(sptr, osub) \
01164 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
01165 (osub).ss = (subseg *) \
01166 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
01167
01168
01169
01170
01171
01172 #define sencode(osub) \
01173 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
01174
01175
01176
01177 #define ssym(osub1, osub2) \
01178 (osub2).ss = (osub1).ss; \
01179 (osub2).ssorient = 1 - (osub1).ssorient
01180
01181 #define ssymself(osub) \
01182 (osub).ssorient = 1 - (osub).ssorient
01183
01184
01185
01186
01187 #define spivot(osub1, osub2) \
01188 sptr = (osub1).ss[(osub1).ssorient]; \
01189 sdecode(sptr, osub2)
01190
01191 #define spivotself(osub) \
01192 sptr = (osub).ss[(osub).ssorient]; \
01193 sdecode(sptr, osub)
01194
01195
01196
01197
01198 #define snext(osub1, osub2) \
01199 sptr = (osub1).ss[1 - (osub1).ssorient]; \
01200 sdecode(sptr, osub2)
01201
01202 #define snextself(osub) \
01203 sptr = (osub).ss[1 - (osub).ssorient]; \
01204 sdecode(sptr, osub)
01205
01206
01207
01208
01209 #define sorg(osub, vertexptr) \
01210 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
01211
01212 #define sdest(osub, vertexptr) \
01213 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
01214
01215 #define setsorg(osub, vertexptr) \
01216 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
01217
01218 #define setsdest(osub, vertexptr) \
01219 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
01220
01221 #define segorg(osub, vertexptr) \
01222 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
01223
01224 #define segdest(osub, vertexptr) \
01225 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
01226
01227 #define setsegorg(osub, vertexptr) \
01228 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
01229
01230 #define setsegdest(osub, vertexptr) \
01231 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
01232
01233
01234
01235
01236
01237 #define mark(osub) (* (int *) ((osub).ss + 8))
01238
01239 #define setmark(osub, value) \
01240 * (int *) ((osub).ss + 8) = value
01241
01242
01243
01244 #define sbond(osub1, osub2) \
01245 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
01246 (osub2).ss[(osub2).ssorient] = sencode(osub1)
01247
01248
01249
01250
01251 #define sdissolve(osub) \
01252 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
01253
01254
01255
01256 #define subsegcopy(osub1, osub2) \
01257 (osub2).ss = (osub1).ss; \
01258 (osub2).ssorient = (osub1).ssorient
01259
01260
01261
01262 #define subsegequal(osub1, osub2) \
01263 (((osub1).ss == (osub2).ss) && \
01264 ((osub1).ssorient == (osub2).ssorient))
01265
01266
01267
01268
01269
01270
01271 #define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
01272
01273 #define killsubseg(sub) \
01274 (sub)[1] = (subseg) NULL; \
01275 (sub)[2] = (subseg) NULL
01276
01277
01278
01279
01280
01281
01282
01283 #define tspivot(otri, osub) \
01284 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
01285 sdecode(sptr, osub)
01286
01287
01288
01289
01290 #define stpivot(osub, otri) \
01291 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
01292 decode(ptr, otri)
01293
01294
01295
01296 #define tsbond(otri, osub) \
01297 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
01298 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
01299
01300
01301
01302 #define tsdissolve(otri) \
01303 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
01304
01305
01306
01307 #define stdissolve(osub) \
01308 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
01309
01310
01311
01312
01313
01314 #define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
01315
01316 #define setvertexmark(vx, value) \
01317 ((int *) (vx))[m->vertexmarkindex] = value
01318
01319 #define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
01320
01321 #define setvertextype(vx, value) \
01322 ((int *) (vx))[m->vertexmarkindex + 1] = value
01323
01324 #define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
01325
01326 #define setvertex2tri(vx, value) \
01327 ((triangle *) (vx))[m->vertex2triindex] = value
01328
01331
01332
01333
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 #ifdef EXTERNAL_TEST
01361
01362 int triunsuitable();
01363
01364 #else
01365
01366 #ifdef ANSI_DECLARATORS
01367 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
01368 #else
01369 int triunsuitable(triorg, tridest, triapex, area)
01370 vertex triorg;
01371 vertex tridest;
01372 vertex triapex;
01373 REAL area;
01374 #endif
01375
01376 {
01377 REAL dxoa, dxda, dxod;
01378 REAL dyoa, dyda, dyod;
01379 REAL oalen, dalen, odlen;
01380 REAL maxlen;
01381
01382 dxoa = triorg[0] - triapex[0];
01383 dyoa = triorg[1] - triapex[1];
01384 dxda = tridest[0] - triapex[0];
01385 dyda = tridest[1] - triapex[1];
01386 dxod = triorg[0] - tridest[0];
01387 dyod = triorg[1] - tridest[1];
01388
01389 oalen = dxoa * dxoa + dyoa * dyoa;
01390 dalen = dxda * dxda + dyda * dyda;
01391 odlen = dxod * dxod + dyod * dyod;
01392
01393 maxlen = (dalen > oalen) ? dalen : oalen;
01394 maxlen = (odlen > maxlen) ? odlen : maxlen;
01395
01396 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
01397 return 1;
01398 } else {
01399 return 0;
01400 }
01401 }
01402
01403 #endif
01404
01407
01408
01409
01413 #ifdef ANSI_DECLARATORS
01414 void triexit(int status)
01415 #else
01416 void triexit(status)
01417 int status;
01418 #endif
01419
01420 {
01421 exit(status);
01422 }
01423
01424 #ifdef ANSI_DECLARATORS
01425 VOID *trimalloc(int size)
01426 #else
01427 VOID *trimalloc(size)
01428 int size;
01429 #endif
01430
01431 {
01432 VOID *memptr;
01433
01434 memptr = (VOID *) malloc((unsigned int) size);
01435 if (memptr == (VOID *) NULL) {
01436 printf("Error: Out of memory.\n");
01437 triexit(1);
01438 }
01439 return(memptr);
01440 }
01441
01442 #ifdef ANSI_DECLARATORS
01443 void trifree(VOID *memptr)
01444 #else
01445 void trifree(memptr)
01446 VOID *memptr;
01447 #endif
01448
01449 {
01450 free(memptr);
01451 }
01452
01455
01456
01457
01461
01462
01463
01464
01465
01466
01467 #ifndef TRILIBRARY
01468
01469 void syntax()
01470 {
01471 #ifdef CDT_ONLY
01472 #ifdef REDUCED
01473 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
01474 #else
01475 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
01476 #endif
01477 #else
01478 #ifdef REDUCED
01479 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
01480 #else
01481 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
01482 #endif
01483 #endif
01484
01485 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
01486 #ifndef CDT_ONLY
01487 printf(" -r Refines a previously generated mesh.\n");
01488 printf(
01489 " -q Quality mesh generation. A minimum angle may be specified.\n");
01490 printf(" -a Applies a maximum triangle area constraint.\n");
01491 printf(" -u Applies a user-defined triangle constraint.\n");
01492 #endif
01493 printf(
01494 " -A Applies attributes to identify triangles in certain regions.\n");
01495 printf(" -c Encloses the convex hull with segments.\n");
01496 #ifndef CDT_ONLY
01497 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
01498 #endif
01499
01500
01501
01502
01503 printf(" -j Jettison unused vertices from output .node file.\n");
01504 printf(" -e Generates an edge list.\n");
01505 printf(" -v Generates a Voronoi diagram.\n");
01506 printf(" -n Generates a list of triangle neighbors.\n");
01507 printf(" -g Generates an .off file for Geomview.\n");
01508 printf(" -B Suppresses output of boundary information.\n");
01509 printf(" -P Suppresses output of .poly file.\n");
01510 printf(" -N Suppresses output of .node file.\n");
01511 printf(" -E Suppresses output of .ele file.\n");
01512 printf(" -I Suppresses mesh iteration numbers.\n");
01513 printf(" -O Ignores holes in .poly file.\n");
01514 printf(" -X Suppresses use of exact arithmetic.\n");
01515 printf(" -z Numbers all items starting from zero (rather than one).\n");
01516 printf(" -o2 Generates second-order subparametric elements.\n");
01517 #ifndef CDT_ONLY
01518 printf(" -Y Suppresses boundary segment splitting.\n");
01519 printf(" -S Specifies maximum number of added Steiner points.\n");
01520 #endif
01521 #ifndef REDUCED
01522 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
01523 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
01524 #endif
01525 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
01526 #ifndef REDUCED
01527 #ifndef CDT_ONLY
01528 printf(
01529 " -s Force segments into mesh by splitting (instead of using CDT).\n");
01530 #endif
01531 printf(" -C Check consistency of final mesh.\n");
01532 #endif
01533 printf(" -Q Quiet: No terminal output except errors.\n");
01534 printf(" -V Verbose: Detailed information on what I'm doing.\n");
01535 printf(" -h Help: Detailed instructions for Triangle.\n");
01536 triexit(0);
01537 }
01538
01539 #endif
01540
01541
01542
01543
01544
01545
01546
01547 #ifndef TRILIBRARY
01548
01549 void info()
01550 {
01551 printf("Triangle\n");
01552 printf(
01553 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
01554 printf("Version 1.6\n\n");
01555 printf(
01556 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
01557 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
01558 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
01559 printf(
01560 "Created as part of the Quake project (tools for earthquake simulation).\n");
01561 printf(
01562 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
01563 printf("There is no warranty whatsoever. Use at your own risk.\n");
01564 #ifdef SINGLE
01565 printf("This executable is compiled for single precision arithmetic.\n\n\n");
01566 #else
01567 printf("This executable is compiled for double precision arithmetic.\n\n\n");
01568 #endif
01569 printf(
01570 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
01571 printf(
01572 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
01573 printf(
01574 "high-quality triangular meshes. The latter can be generated with no small\n"
01575 );
01576 printf(
01577 "or large angles, and are thus suitable for finite element analysis. If no\n"
01578 );
01579 printf(
01580 "command line switch is specified, your .node input file is read, and the\n");
01581 printf(
01582 "Delaunay triangulation is returned in .node and .ele output files. The\n");
01583 printf("command syntax is:\n\n");
01584 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
01585 printf(
01586 "Underscores indicate that numbers may optionally follow certain switches.\n");
01587 printf(
01588 "Do not leave any space between a switch and its numeric parameter.\n");
01589 printf(
01590 "input_file must be a file with extension .node, or extension .poly if the\n");
01591 printf(
01592 "-p switch is used. If -r is used, you must supply .node and .ele files,\n");
01593 printf(
01594 "and possibly a .poly file and an .area file as well. The formats of these\n"
01595 );
01596 printf("files are described below.\n\n");
01597 printf("Command Line Switches:\n\n");
01598 printf(
01599 " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
01600 );
01601 printf(
01602 " vertices, segments, holes, regional attributes, and regional area\n");
01603 printf(
01604 " constraints. Generates a constrained Delaunay triangulation (CDT)\n"
01605 );
01606 printf(
01607 " fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
01608 printf(
01609 " constrained Delaunay triangulation (CCDT). If you want a truly\n");
01610 printf(
01611 " Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
01612 printf(
01613 " well. When -p is not used, Triangle reads a .node file by default.\n"
01614 );
01615 printf(
01616 " -r Refines a previously generated mesh. The mesh is read from a .node\n"
01617 );
01618 printf(
01619 " file and an .ele file. If -p is also used, a .poly file is read\n");
01620 printf(
01621 " and used to constrain segments in the mesh. If -a is also used\n");
01622 printf(
01623 " (with no number following), an .area file is read and used to\n");
01624 printf(
01625 " impose area constraints on the mesh. Further details on refinement\n"
01626 );
01627 printf(" appear below.\n");
01628 printf(
01629 " -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
01630 printf(
01631 " Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
01632 );
01633 printf(
01634 " ensure that all angles are between 20 and 140 degrees. An\n");
01635 printf(
01636 " alternative bound on the minimum angle, replacing 20 degrees, may\n");
01637 printf(
01638 " be specified after the `q'. The specified angle may include a\n");
01639 printf(
01640 " decimal point, but not exponential notation. Note that a bound of\n"
01641 );
01642 printf(
01643 " theta degrees on the smallest angle also implies a bound of\n");
01644 printf(
01645 " (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
01646 );
01647 printf(
01648 " degrees or smaller, Triangle is mathematically guaranteed to\n");
01649 printf(
01650 " terminate (assuming infinite precision arithmetic--Triangle may\n");
01651 printf(
01652 " fail to terminate if you run out of precision). In practice,\n");
01653 printf(
01654 " Triangle often succeeds for minimum angles up to 34 degrees. For\n");
01655 printf(
01656 " some meshes, however, you might need to reduce the minimum angle to\n"
01657 );
01658 printf(
01659 " avoid problems associated with insufficient floating-point\n");
01660 printf(" precision.\n");
01661 printf(
01662 " -a Imposes a maximum triangle area. If a number follows the `a', no\n");
01663 printf(
01664 " triangle is generated whose area is larger than that number. If no\n"
01665 );
01666 printf(
01667 " number is specified, an .area file (if -r is used) or .poly file\n");
01668 printf(
01669 " (if -r is not used) specifies a set of maximum area constraints.\n");
01670 printf(
01671 " An .area file contains a separate area constraint for each\n");
01672 printf(
01673 " triangle, and is useful for refining a finite element mesh based on\n"
01674 );
01675 printf(
01676 " a posteriori error estimates. A .poly file can optionally contain\n"
01677 );
01678 printf(
01679 " an area constraint for each segment-bounded region, thereby\n");
01680 printf(
01681 " controlling triangle densities in a first triangulation of a PSLG.\n"
01682 );
01683 printf(
01684 " You can impose both a fixed area constraint and a varying area\n");
01685 printf(
01686 " constraint by invoking the -a switch twice, once with and once\n");
01687 printf(
01688 " without a number following. Each area specified may include a\n");
01689 printf(" decimal point.\n");
01690 printf(
01691 " -u Imposes a user-defined constraint on triangle size. There are two\n"
01692 );
01693 printf(
01694 " ways to use this feature. One is to edit the triunsuitable()\n");
01695 printf(
01696 " procedure in triangle.c to encode any constraint you like, then\n");
01697 printf(
01698 " recompile Triangle. The other is to compile triangle.c with the\n");
01699 printf(
01700 " EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
01701 printf(
01702 " link Triangle with a separate object file that implements\n");
01703 printf(
01704 " triunsuitable(). In either case, the -u switch causes the user-\n");
01705 printf(" defined test to be applied to every triangle.\n");
01706 printf(
01707 " -A Assigns an additional floating-point attribute to each triangle\n");
01708 printf(
01709 " that identifies what segment-bounded region each triangle belongs\n");
01710 printf(
01711 " to. Attributes are assigned to regions by the .poly file. If a\n");
01712 printf(
01713 " region is not explicitly marked by the .poly file, triangles in\n");
01714 printf(
01715 " that region are assigned an attribute of zero. The -A switch has\n");
01716 printf(
01717 " an effect only when the -p switch is used and the -r switch is not.\n"
01718 );
01719 printf(
01720 " -c Creates segments on the convex hull of the triangulation. If you\n");
01721 printf(
01722 " are triangulating a vertex set, this switch causes a .poly file to\n"
01723 );
01724 printf(
01725 " be written, containing all edges of the convex hull. If you are\n");
01726 printf(
01727 " triangulating a PSLG, this switch specifies that the whole convex\n");
01728 printf(
01729 " hull of the PSLG should be triangulated, regardless of what\n");
01730 printf(
01731 " segments the PSLG has. If you do not use this switch when\n");
01732 printf(
01733 " triangulating a PSLG, Triangle assumes that you have identified the\n"
01734 );
01735 printf(
01736 " region to be triangulated by surrounding it with segments of the\n");
01737 printf(
01738 " input PSLG. Beware: if you are not careful, this switch can cause\n"
01739 );
01740 printf(
01741 " the introduction of an extremely thin angle between a PSLG segment\n"
01742 );
01743 printf(
01744 " and a convex hull segment, which can cause overrefinement (and\n");
01745 printf(
01746 " possibly failure if Triangle runs out of precision). If you are\n");
01747 printf(
01748 " refining a mesh, the -c switch works differently: it causes a\n");
01749 printf(
01750 " .poly file to be written containing the boundary edges of the mesh\n"
01751 );
01752 printf(" (useful if no .poly file was read).\n");
01753 printf(
01754 " -D Conforming Delaunay triangulation: use this switch if you want to\n"
01755 );
01756 printf(
01757 " ensure that all the triangles in the mesh are Delaunay, and not\n");
01758 printf(
01759 " merely constrained Delaunay; or if you want to ensure that all the\n"
01760 );
01761 printf(
01762 " Voronoi vertices lie within the triangulation. (Some finite volume\n"
01763 );
01764 printf(
01765 " methods have this requirement.) This switch invokes Ruppert's\n");
01766 printf(
01767 " original algorithm, which splits every subsegment whose diametral\n");
01768 printf(
01769 " circle is encroached. It usually increases the number of vertices\n"
01770 );
01771 printf(" and triangles.\n");
01772 printf(
01773 " -j Jettisons vertices that are not part of the final triangulation\n");
01774 printf(
01775 " from the output .node file. By default, Triangle copies all\n");
01776 printf(
01777 " vertices in the input .node file to the output .node file, in the\n");
01778 printf(
01779 " same order, so their indices do not change. The -j switch prevents\n"
01780 );
01781 printf(
01782 " duplicated input vertices, or vertices `eaten' by holes, from\n");
01783 printf(
01784 " appearing in the output .node file. Thus, if two input vertices\n");
01785 printf(
01786 " have exactly the same coordinates, only the first appears in the\n");
01787 printf(
01788 " output. If any vertices are jettisoned, the vertex numbering in\n");
01789 printf(
01790 " the output .node file differs from that of the input .node file.\n");
01791 printf(
01792 " -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
01793 printf(
01794 " -v Outputs the Voronoi diagram associated with the triangulation.\n");
01795 printf(
01796 " Does not attempt to detect degeneracies, so some Voronoi vertices\n");
01797 printf(
01798 " may be duplicated. See the discussion of Voronoi diagrams below.\n");
01799 printf(
01800 " -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
01801 printf(" triangle.\n");
01802 printf(
01803 " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
01804 );
01805 printf(" viewing with the Geometry Center's Geomview package.\n");
01806 printf(
01807 " -B No boundary markers in the output .node, .poly, and .edge output\n");
01808 printf(
01809 " files. See the detailed discussion of boundary markers below.\n");
01810 printf(
01811 " -P No output .poly file. Saves disk space, but you lose the ability\n");
01812 printf(
01813 " to maintain constraining segments on later refinements of the mesh.\n"
01814 );
01815 printf(" -N No output .node file.\n");
01816 printf(" -E No output .ele file.\n");
01817 printf(
01818 " -I No iteration numbers. Suppresses the output of .node and .poly\n");
01819 printf(
01820 " files, so your input files won't be overwritten. (If your input is\n"
01821 );
01822 printf(
01823 " a .poly file only, a .node file is written.) Cannot be used with\n");
01824 printf(
01825 " the -r switch, because that would overwrite your input .ele file.\n");
01826 printf(
01827 " Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
01828 printf(
01829 " using a .node file for input, because no .node file is written, so\n"
01830 );
01831 printf(" there is no record of any added Steiner points.\n");
01832 printf(" -O No holes. Ignores the holes in the .poly file.\n");
01833 printf(
01834 " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
01835 );
01836 printf(
01837 " arithmetic for certain tests if it thinks the inexact tests are not\n"
01838 );
01839 printf(
01840 " accurate enough. Exact arithmetic ensures the robustness of the\n");
01841 printf(
01842 " triangulation algorithms, despite floating-point roundoff error.\n");
01843 printf(
01844 " Disabling exact arithmetic with the -X switch causes a small\n");
01845 printf(
01846 " improvement in speed and creates the possibility that Triangle will\n"
01847 );
01848 printf(" fail to produce a valid mesh. Not recommended.\n");
01849 printf(
01850 " -z Numbers all items starting from zero (rather than one). Note that\n"
01851 );
01852 printf(
01853 " this switch is normally overridden by the value used to number the\n"
01854 );
01855 printf(
01856 " first vertex of the input .node or .poly file. However, this\n");
01857 printf(
01858 " switch is useful when calling Triangle from another program.\n");
01859 printf(
01860 " -o2 Generates second-order subparametric elements with six nodes each.\n"
01861 );
01862 printf(
01863 " -Y No new vertices on the boundary. This switch is useful when the\n");
01864 printf(
01865 " mesh boundary must be preserved so that it conforms to some\n");
01866 printf(
01867 " adjacent mesh. Be forewarned that you will probably sacrifice much\n"
01868 );
01869 printf(
01870 " of the quality of the mesh; Triangle will try, but the resulting\n");
01871 printf(
01872 " mesh may contain poorly shaped triangles. Works well if all the\n");
01873 printf(
01874 " boundary vertices are closely spaced. Specify this switch twice\n");
01875 printf(
01876 " (`-YY') to prevent all segment splitting, including internal\n");
01877 printf(" boundaries.\n");
01878 printf(
01879 " -S Specifies the maximum number of Steiner points (vertices that are\n");
01880 printf(
01881 " not in the input, but are added to meet the constraints on minimum\n"
01882 );
01883 printf(
01884 " angle and maximum area). The default is to allow an unlimited\n");
01885 printf(
01886 " number. If you specify this switch with no number after it,\n");
01887 printf(
01888 " the limit is set to zero. Triangle always adds vertices at segment\n"
01889 );
01890 printf(
01891 " intersections, even if it needs to use more vertices than the limit\n"
01892 );
01893 printf(
01894 " you set. When Triangle inserts segments by splitting (-s), it\n");
01895 printf(
01896 " always adds enough vertices to ensure that all the segments of the\n"
01897 );
01898 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
01899 printf(
01900 " -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
01901 printf(
01902 " construct a Delaunay triangulation. Try it if the divide-and-\n");
01903 printf(" conquer algorithm fails.\n");
01904 printf(
01905 " -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
01906 printf(
01907 " triangulation. Warning: does not use exact arithmetic for all\n");
01908 printf(" calculations. An exact result is not guaranteed.\n");
01909 printf(
01910 " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
01911 printf(
01912 " default, Triangle alternates between vertical and horizontal cuts,\n"
01913 );
01914 printf(
01915 " which usually improve the speed except with vertex sets that are\n");
01916 printf(
01917 " small or short and wide. This switch is primarily of theoretical\n");
01918 printf(" interest.\n");
01919 printf(
01920 " -s Specifies that segments should be forced into the triangulation by\n"
01921 );
01922 printf(
01923 " recursively splitting them at their midpoints, rather than by\n");
01924 printf(
01925 " generating a constrained Delaunay triangulation. Segment splitting\n"
01926 );
01927 printf(
01928 " is true to Ruppert's original algorithm, but can create needlessly\n"
01929 );
01930 printf(
01931 " small triangles. This switch is primarily of theoretical interest.\n"
01932 );
01933 printf(
01934 " -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
01935 );
01936 printf(
01937 " checking, even if the -X switch is used. Useful if you suspect\n");
01938 printf(" Triangle is buggy.\n");
01939 printf(
01940 " -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
01941 printf(" unless an error occurs.\n");
01942 printf(
01943 " -V Verbose: Gives detailed information about what Triangle is doing.\n"
01944 );
01945 printf(
01946 " Add more `V's for increasing amount of detail. `-V' is most\n");
01947 printf(
01948 " useful; itgives information on algorithmic progress and much more\n");
01949 printf(
01950 " detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
01951 printf(
01952 " prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
01953 );
01954 printf(" information only a debugger could love.\n");
01955 printf(" -h Help: Displays these instructions.\n");
01956 printf("\n");
01957 printf("Definitions:\n");
01958 printf("\n");
01959 printf(
01960 " A Delaunay triangulation of a vertex set is a triangulation whose\n");
01961 printf(
01962 " vertices are the vertex set, that covers the convex hull of the vertex\n");
01963 printf(
01964 " set. A Delaunay triangulation has the property that no vertex lies\n");
01965 printf(
01966 " inside the circumscribing circle (circle that passes through all three\n");
01967 printf(" vertices) of any triangle in the triangulation.\n\n");
01968 printf(
01969 " A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
01970 printf(
01971 " polygonal cells (some of which may be unbounded, meaning infinitely\n");
01972 printf(
01973 " large), where each cell is the set of points in the plane that are closer\n"
01974 );
01975 printf(
01976 " to some input vertex than to any other input vertex. The Voronoi diagram\n"
01977 );
01978 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
01979 printf(
01980 " A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
01981 printf(
01982 " Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
01983 );
01984 printf(
01985 " Segments may intersect each other only at their endpoints. The file\n");
01986 printf(" format for PSLGs (.poly files) is described below.\n\n");
01987 printf(
01988 " A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
01989 printf(
01990 " Delaunay triangulation, but each PSLG segment is present as a single edge\n"
01991 );
01992 printf(
01993 " of the CDT. (A constrained Delaunay triangulation is not truly a\n");
01994 printf(
01995 " Delaunay triangulation, because some of its triangles might not be\n");
01996 printf(
01997 " Delaunay.) By definition, a CDT does not have any vertices other than\n");
01998 printf(
01999 " those specified in the input PSLG. Depending on context, a CDT might\n");
02000 printf(
02001 " cover the convex hull of the PSLG, or it might cover only a segment-\n");
02002 printf(" bounded region (e.g. a polygon).\n\n");
02003 printf(
02004 " A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
02005 );
02006 printf(
02007 " each triangle is truly Delaunay, and each PSLG segment is represented by\n"
02008 );
02009 printf(
02010 " a linear contiguous sequence of edges of the triangulation. New vertices\n"
02011 );
02012 printf(
02013 " (not part of the PSLG) may appear, and each input segment may have been\n");
02014 printf(
02015 " subdivided into shorter edges (subsegments) by these additional vertices.\n"
02016 );
02017 printf(
02018 " The new vertices are frequently necessary to maintain the Delaunay\n");
02019 printf(" property while ensuring that every segment is represented.\n\n");
02020 printf(
02021 " A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
02022 printf(
02023 " triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
02024 printf(" vertices may appear, and input segments may be subdivided into\n");
02025 printf(
02026 " subsegments, but not to guarantee that segments are respected; rather, to\n"
02027 );
02028 printf(
02029 " improve the quality of the triangles. The high-quality meshes produced\n");
02030 printf(
02031 " by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
02032 printf(" with the -D switch.\n\n");
02033 printf("File Formats:\n\n");
02034 printf(
02035 " All files may contain comments prefixed by the character '#'. Vertices,\n"
02036 );
02037 printf(
02038 " triangles, edges, holes, and maximum area constraints must be numbered\n");
02039 printf(
02040 " consecutively, starting from either 1 or 0. Whichever you choose, all\n");
02041 printf(
02042 " input files must be consistent; if the vertices are numbered from 1, so\n");
02043 printf(
02044 " must be all other objects. Triangle automatically detects your choice\n");
02045 printf(
02046 " while reading the .node (or .poly) file. (When calling Triangle from\n");
02047 printf(
02048 " another program, use the -z switch if you wish to number objects from\n");
02049 printf(" zero.) Examples of these file formats are given below.\n\n");
02050 printf(" .node files:\n");
02051 printf(
02052 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02053 );
02054 printf(
02055 " <# of boundary markers (0 or 1)>\n"
02056 );
02057 printf(
02058 " Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02059 printf("\n");
02060 printf(
02061 " The attributes, which are typically floating-point values of physical\n");
02062 printf(
02063 " quantities (such as mass or conductivity) associated with the nodes of\n"
02064 );
02065 printf(
02066 " a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
02067 );
02068 printf(
02069 " -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
02070 );
02071 printf(" has attributes assigned to it by linear interpolation.\n\n");
02072 printf(
02073 " If the fourth entry of the first line is `1', the last column of the\n");
02074 printf(
02075 " remainder of the file is assumed to contain boundary markers. Boundary\n"
02076 );
02077 printf(
02078 " markers are used to identify boundary vertices and vertices resting on\n"
02079 );
02080 printf(
02081 " PSLG segments; a complete description appears in a section below. The\n"
02082 );
02083 printf(
02084 " .node file produced by Triangle contains boundary markers in the last\n");
02085 printf(" column unless they are suppressed by the -B switch.\n\n");
02086 printf(" .ele files:\n");
02087 printf(
02088 " First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
02089 printf(
02090 " Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
02091 printf("\n");
02092 printf(
02093 " Nodes are indices into the corresponding .node file. The first three\n");
02094 printf(
02095 " nodes are the corner vertices, and are listed in counterclockwise order\n"
02096 );
02097 printf(
02098 " around each triangle. (The remaining nodes, if any, depend on the type\n"
02099 );
02100 printf(" of finite element used.)\n\n");
02101 printf(
02102 " The attributes are just like those of .node files. Because there is no\n"
02103 );
02104 printf(
02105 " simple mapping from input to output triangles, Triangle attempts to\n");
02106 printf(
02107 " interpolate attributes, and may cause a lot of diffusion of attributes\n"
02108 );
02109 printf(
02110 " among nearby triangles as the triangulation is refined. Attributes do\n"
02111 );
02112 printf(" not diffuse across segments, so attributes used to identify\n");
02113 printf(" segment-bounded regions remain intact.\n\n");
02114 printf(
02115 " In .ele files produced by Triangle, each triangular element has three\n");
02116 printf(
02117 " nodes (vertices) unless the -o2 switch is used, in which case\n");
02118 printf(
02119 " subparametric quadratic elements with six nodes each are generated.\n");
02120 printf(
02121 " The first three nodes are the corners in counterclockwise order, and\n");
02122 printf(
02123 " the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
02124 printf(
02125 " opposite the first, second, and third vertices, respectively.\n");
02126 printf("\n");
02127 printf(" .poly files:\n");
02128 printf(
02129 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02130 );
02131 printf(
02132 " <# of boundary markers (0 or 1)>\n"
02133 );
02134 printf(
02135 " Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02136 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
02137 printf(
02138 " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
02139 printf(" One line: <# of holes>\n");
02140 printf(" Following lines: <hole #> <x> <y>\n");
02141 printf(
02142 " Optional line: <# of regional attributes and/or area constraints>\n");
02143 printf(
02144 " Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
02145 printf("\n");
02146 printf(
02147 " A .poly file represents a PSLG, as well as some additional information.\n"
02148 );
02149 printf(
02150 " The first section lists all the vertices, and is identical to the\n");
02151 printf(
02152 " format of .node files. <# of vertices> may be set to zero to indicate\n"
02153 );
02154 printf(
02155 " that the vertices are listed in a separate .node file; .poly files\n");
02156 printf(
02157 " produced by Triangle always have this format. A vertex set represented\n"
02158 );
02159 printf(
02160 " this way has the advantage that it may easily be triangulated with or\n");
02161 printf(
02162 " without segments (depending on whether the -p switch is invoked).\n");
02163 printf("\n");
02164 printf(
02165 " The second section lists the segments. Segments are edges whose\n");
02166 printf(
02167 " presence in the triangulation is enforced. (Depending on the choice of\n"
02168 );
02169 printf(
02170 " switches, segment might be subdivided into smaller edges). Each\n");
02171 printf(
02172 " segment is specified by listing the indices of its two endpoints. This\n"
02173 );
02174 printf(
02175 " means that you must include its endpoints in the vertex list. Each\n");
02176 printf(" segment, like each point, may have a boundary marker.\n\n");
02177 printf(
02178 " If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
02179 );
02180 printf(
02181 " Delaunay triangulation (CDT), in which each segment appears as a single\n"
02182 );
02183 printf(
02184 " edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
02185 );
02186 printf(
02187 " produces a conforming constrained Delaunay triangulation (CCDT), in\n");
02188 printf(
02189 " which segments may be subdivided into smaller edges. If -D is\n");
02190 printf(
02191 " selected, Triangle produces a conforming Delaunay triangulation, so\n");
02192 printf(
02193 " that every triangle is Delaunay, and not just constrained Delaunay.\n");
02194 printf("\n");
02195 printf(
02196 " The third section lists holes (and concavities, if -c is selected) in\n");
02197 printf(
02198 " the triangulation. Holes are specified by identifying a point inside\n");
02199 printf(
02200 " each hole. After the triangulation is formed, Triangle creates holes\n");
02201 printf(
02202 " by eating triangles, spreading out from each hole point until its\n");
02203 printf(
02204 " progress is blocked by segments in the PSLG. You must be careful to\n");
02205 printf(
02206 " enclose each hole in segments, or your whole triangulation might be\n");
02207 printf(
02208 " eaten away. If the two triangles abutting a segment are eaten, the\n");
02209 printf(
02210 " segment itself is also eaten. Do not place a hole directly on a\n");
02211 printf(" segment; if you do, Triangle chooses one side of the segment\n");
02212 printf(" arbitrarily.\n\n");
02213 printf(
02214 " The optional fourth section lists regional attributes (to be assigned\n");
02215 printf(
02216 " to all triangles in a region) and regional constraints on the maximum\n");
02217 printf(
02218 " triangle area. Triangle reads this section only if the -A switch is\n");
02219 printf(
02220 " used or the -a switch is used without a number following it, and the -r\n"
02221 );
02222 printf(
02223 " switch is not used. Regional attributes and area constraints are\n");
02224 printf(
02225 " propagated in the same manner as holes: you specify a point for each\n");
02226 printf(
02227 " attribute and/or constraint, and the attribute and/or constraint\n");
02228 printf(
02229 " affects the whole region (bounded by segments) containing the point.\n");
02230 printf(
02231 " If two values are written on a line after the x and y coordinate, the\n");
02232 printf(
02233 " first such value is assumed to be a regional attribute (but is only\n");
02234 printf(
02235 " applied if the -A switch is selected), and the second value is assumed\n"
02236 );
02237 printf(
02238 " to be a regional area constraint (but is only applied if the -a switch\n"
02239 );
02240 printf(
02241 " is selected). You may specify just one value after the coordinates,\n");
02242 printf(
02243 " which can serve as both an attribute and an area constraint, depending\n"
02244 );
02245 printf(
02246 " on the choice of switches. If you are using the -A and -a switches\n");
02247 printf(
02248 " simultaneously and wish to assign an attribute to some region without\n");
02249 printf(" imposing an area constraint, use a negative maximum area.\n\n");
02250 printf(
02251 " When a triangulation is created from a .poly file, you must either\n");
02252 printf(
02253 " enclose the entire region to be triangulated in PSLG segments, or\n");
02254 printf(
02255 " use the -c switch, which automatically creates extra segments that\n");
02256 printf(
02257 " enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
02258 );
02259 printf(
02260 " Triangle eats all triangles that are not enclosed by segments; if you\n");
02261 printf(
02262 " are not careful, your whole triangulation may be eaten away. If you do\n"
02263 );
02264 printf(
02265 " use the -c switch, you can still produce concavities by the appropriate\n"
02266 );
02267 printf(
02268 " placement of holes just inside the boundary of the convex hull.\n");
02269 printf("\n");
02270 printf(
02271 " An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
02272 printf(
02273 " upon segments (except, of course, the endpoints of each segment). You\n"
02274 );
02275 printf(
02276 " aren't required to make your .poly files ideal, but you should be aware\n"
02277 );
02278 printf(
02279 " of what can go wrong. Segment intersections are relatively safe--\n");
02280 printf(
02281 " Triangle calculates the intersection points for you and adds them to\n");
02282 printf(
02283 " the triangulation--as long as your machine's floating-point precision\n");
02284 printf(
02285 " doesn't become a problem. You are tempting the fates if you have three\n"
02286 );
02287 printf(
02288 " segments that cross at the same location, and expect Triangle to figure\n"
02289 );
02290 printf(
02291 " out where the intersection point is. Thanks to floating-point roundoff\n"
02292 );
02293 printf(
02294 " error, Triangle will probably decide that the three segments intersect\n"
02295 );
02296 printf(
02297 " at three different points, and you will find a minuscule triangle in\n");
02298 printf(
02299 " your output--unless Triangle tries to refine the tiny triangle, uses\n");
02300 printf(
02301 " up the last bit of machine precision, and fails to terminate at all.\n");
02302 printf(
02303 " You're better off putting the intersection point in the input files,\n");
02304 printf(
02305 " and manually breaking up each segment into two. Similarly, if you\n");
02306 printf(
02307 " place a vertex at the middle of a segment, and hope that Triangle will\n"
02308 );
02309 printf(
02310 " break up the segment at that vertex, you might get lucky. On the other\n"
02311 );
02312 printf(
02313 " hand, Triangle might decide that the vertex doesn't lie precisely on\n");
02314 printf(
02315 " the segment, and you'll have a needle-sharp triangle in your output--or\n"
02316 );
02317 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
02318 printf("\n");
02319 printf(
02320 " When Triangle reads a .poly file, it also writes a .poly file, which\n");
02321 printf(
02322 " includes all the subsegments--the edges that are parts of input\n");
02323 printf(
02324 " segments. If the -c switch is used, the output .poly file also\n");
02325 printf(
02326 " includes all of the edges on the convex hull. Hence, the output .poly\n"
02327 );
02328 printf(
02329 " file is useful for finding edges associated with input segments and for\n"
02330 );
02331 printf(
02332 " setting boundary conditions in finite element simulations. Moreover,\n");
02333 printf(
02334 " you will need the output .poly file if you plan to refine the output\n");
02335 printf(
02336 " mesh, and don't want segments to be missing in later triangulations.\n");
02337 printf("\n");
02338 printf(" .area files:\n");
02339 printf(" First line: <# of triangles>\n");
02340 printf(" Following lines: <triangle #> <maximum area>\n");
02341 printf("\n");
02342 printf(
02343 " An .area file associates with each triangle a maximum area that is used\n"
02344 );
02345 printf(
02346 " for mesh refinement. As with other file formats, every triangle must\n");
02347 printf(
02348 " be represented, and the triangles must be numbered consecutively. A\n");
02349 printf(
02350 " triangle may be left unconstrained by assigning it a negative maximum\n");
02351 printf(" area.\n\n");
02352 printf(" .edge files:\n");
02353 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
02354 printf(
02355 " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
02356 printf("\n");
02357 printf(
02358 " Endpoints are indices into the corresponding .node file. Triangle can\n"
02359 );
02360 printf(
02361 " produce .edge files (use the -e switch), but cannot read them. The\n");
02362 printf(
02363 " optional column of boundary markers is suppressed by the -B switch.\n");
02364 printf("\n");
02365 printf(
02366 " In Voronoi diagrams, one also finds a special kind of edge that is an\n");
02367 printf(
02368 " infinite ray with only one endpoint. For these edges, a different\n");
02369 printf(" format is used:\n\n");
02370 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
02371 printf(
02372 " The `direction' is a floating-point vector that indicates the direction\n"
02373 );
02374 printf(" of the infinite ray.\n\n");
02375 printf(" .neigh files:\n");
02376 printf(
02377 " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
02378 );
02379 printf(
02380 " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
02381 printf("\n");
02382 printf(
02383 " Neighbors are indices into the corresponding .ele file. An index of -1\n"
02384 );
02385 printf(
02386 " indicates no neighbor (because the triangle is on an exterior\n");
02387 printf(
02388 " boundary). The first neighbor of triangle i is opposite the first\n");
02389 printf(" corner of triangle i, and so on.\n\n");
02390 printf(
02391 " Triangle can produce .neigh files (use the -n switch), but cannot read\n"
02392 );
02393 printf(" them.\n\n");
02394 printf("Boundary Markers:\n\n");
02395 printf(
02396 " Boundary markers are tags used mainly to identify which output vertices\n");
02397 printf(
02398 " and edges are associated with which PSLG segment, and to identify which\n");
02399 printf(
02400 " vertices and edges occur on a boundary of the triangulation. A common\n");
02401 printf(
02402 " use is to determine where boundary conditions should be applied to a\n");
02403 printf(
02404 " finite element mesh. You can prevent boundary markers from being written\n"
02405 );
02406 printf(" into files produced by Triangle by using the -B switch.\n\n");
02407 printf(
02408 " The boundary marker associated with each segment in an output .poly file\n"
02409 );
02410 printf(" and each edge in an output .edge file is chosen as follows:\n");
02411 printf(
02412 " - If an output edge is part or all of a PSLG segment with a nonzero\n");
02413 printf(
02414 " boundary marker, then the edge is assigned the same marker.\n");
02415 printf(
02416 " - Otherwise, if the edge lies on a boundary of the triangulation\n");
02417 printf(
02418 " (even the boundary of a hole), then the edge is assigned the marker\n");
02419 printf(" one (1).\n");
02420 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
02421 printf(
02422 " The boundary marker associated with each vertex in an output .node file\n");
02423 printf(" is chosen as follows:\n");
02424 printf(
02425 " - If a vertex is assigned a nonzero boundary marker in the input file,\n"
02426 );
02427 printf(
02428 " then it is assigned the same marker in the output .node file.\n");
02429 printf(
02430 " - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
02431 printf(
02432 " endpoint of the segment) with a nonzero boundary marker, then the\n");
02433 printf(
02434 " vertex is assigned the same marker. If the vertex lies on several\n");
02435 printf(" such segments, one of the markers is chosen arbitrarily.\n");
02436 printf(
02437 " - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
02438 printf(" then the vertex is assigned the marker one (1).\n");
02439 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
02440 printf("\n");
02441 printf(
02442 " If you want Triangle to determine for you which vertices and edges are on\n"
02443 );
02444 printf(
02445 " the boundary, assign them the boundary marker zero (or use no markers at\n"
02446 );
02447 printf(
02448 " all) in your input files. In the output files, all boundary vertices,\n");
02449 printf(" edges, and segments will be assigned the value one.\n\n");
02450 printf("Triangulation Iteration Numbers:\n\n");
02451 printf(
02452 " Because Triangle can read and refine its own triangulations, input\n");
02453 printf(
02454 " and output files have iteration numbers. For instance, Triangle might\n");
02455 printf(
02456 " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
02457 printf(
02458 " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
02459 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
02460 printf(
02461 " their iteration number is zero; hence, Triangle might read the file\n");
02462 printf(
02463 " points.node, triangulate it, and produce the files points.1.node and\n");
02464 printf(" points.1.ele.\n\n");
02465 printf(
02466 " Iteration numbers allow you to create a sequence of successively finer\n");
02467 printf(
02468 " meshes suitable for multigrid methods. They also allow you to produce a\n"
02469 );
02470 printf(
02471 " sequence of meshes using error estimate-driven mesh refinement.\n");
02472 printf("\n");
02473 printf(
02474 " If you're not using refinement or quality meshing, and you don't like\n");
02475 printf(
02476 " iteration numbers, use the -I switch to disable them. This switch also\n");
02477 printf(
02478 " disables output of .node and .poly files to prevent your input files from\n"
02479 );
02480 printf(
02481 " being overwritten. (If the input is a .poly file that contains its own\n");
02482 printf(
02483 " points, a .node file is written. This can be quite convenient for\n");
02484 printf(" computing CDTs or quality meshes.)\n\n");
02485 printf("Examples of How to Use Triangle:\n\n");
02486 printf(
02487 " `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
02488 );
02489 printf(
02490 " triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
02491 printf(
02492 " to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
02493 printf(
02494 " instead. (No additional .node file is needed, so none is written.)\n");
02495 printf("\n");
02496 printf(
02497 " `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
02498 printf(
02499 " object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
02500 );
02501 printf(
02502 " its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
02503 );
02504 printf(
02505 " The segments are copied to object.2.poly, and all edges are written to\n");
02506 printf(" object.2.edge.\n\n");
02507 printf(
02508 " `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
02509 );
02510 printf(
02511 " object.node), generates a mesh whose angles are all between 31.5 and 117\n"
02512 );
02513 printf(
02514 " degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
02515 );
02516 printf(
02517 " mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
02518 printf(" into multiple subsegments; these are written to object.1.poly.\n");
02519 printf("\n");
02520 printf(
02521 " Here is a sample file `box.poly' describing a square with a square hole:\n"
02522 );
02523 printf("\n");
02524 printf(
02525 " # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
02526 );
02527 printf(" 8 2 0 1\n");
02528 printf(" # Outer box has these vertices:\n");
02529 printf(" 1 0 0 0\n");
02530 printf(" 2 0 3 0\n");
02531 printf(" 3 3 0 0\n");
02532 printf(" 4 3 3 33 # A special marker for this vertex.\n");
02533 printf(" # Inner square has these vertices:\n");
02534 printf(" 5 1 1 0\n");
02535 printf(" 6 1 2 0\n");
02536 printf(" 7 2 1 0\n");
02537 printf(" 8 2 2 0\n");
02538 printf(" # Five segments with boundary markers.\n");
02539 printf(" 5 1\n");
02540 printf(" 1 1 2 5 # Left side of outer box.\n");
02541 printf(" # Square hole has these segments:\n");
02542 printf(" 2 5 7 0\n");
02543 printf(" 3 7 8 0\n");
02544 printf(" 4 8 6 10\n");
02545 printf(" 5 6 5 0\n");
02546 printf(" # One hole in the middle of the inner square.\n");
02547 printf(" 1\n");
02548 printf(" 1 1.5 1.5\n");
02549 printf("\n");
02550 printf(
02551 " Note that some segments are missing from the outer square, so you must\n");
02552 printf(
02553 " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
02554 );
02555 printf(
02556 " file `box.1.node', with twelve vertices. The last four vertices were\n");
02557 printf(
02558 " added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
02559 printf(
02560 " from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
02561 printf(
02562 " other vertices but 4 have been marked to indicate that they lie on a\n");
02563 printf(" boundary.\n\n");
02564 printf(" 12 2 0 1\n");
02565 printf(" 1 0 0 5\n");
02566 printf(" 2 0 3 5\n");
02567 printf(" 3 3 0 1\n");
02568 printf(" 4 3 3 33\n");
02569 printf(" 5 1 1 1\n");
02570 printf(" 6 1 2 10\n");
02571 printf(" 7 2 1 1\n");
02572 printf(" 8 2 2 10\n");
02573 printf(" 9 0 1.5 5\n");
02574 printf(" 10 1.5 0 1\n");
02575 printf(" 11 3 1.5 1\n");
02576 printf(" 12 1.5 3 1\n");
02577 printf(" # Generated by triangle -pqc box.poly\n");
02578 printf("\n");
02579 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
02580 printf("\n");
02581 printf(" 12 3 0\n");
02582 printf(" 1 5 6 9\n");
02583 printf(" 2 10 3 7\n");
02584 printf(" 3 6 8 12\n");
02585 printf(" 4 9 1 5\n");
02586 printf(" 5 6 2 9\n");
02587 printf(" 6 7 3 11\n");
02588 printf(" 7 11 4 8\n");
02589 printf(" 8 7 5 10\n");
02590 printf(" 9 12 2 6\n");
02591 printf(" 10 8 7 11\n");
02592 printf(" 11 5 1 10\n");
02593 printf(" 12 8 4 12\n");
02594 printf(" # Generated by triangle -pqc box.poly\n\n");
02595 printf(
02596 " Here is the output file `box.1.poly'. Note that segments have been added\n"
02597 );
02598 printf(
02599 " to represent the convex hull, and some segments have been subdivided by\n");
02600 printf(
02601 " newly added vertices. Note also that <# of vertices> is set to zero to\n");
02602 printf(" indicate that the vertices should be read from the .node file.\n");
02603 printf("\n");
02604 printf(" 0 2 0 1\n");
02605 printf(" 12 1\n");
02606 printf(" 1 1 9 5\n");
02607 printf(" 2 5 7 1\n");
02608 printf(" 3 8 7 1\n");
02609 printf(" 4 6 8 10\n");
02610 printf(" 5 5 6 1\n");
02611 printf(" 6 3 10 1\n");
02612 printf(" 7 4 11 1\n");
02613 printf(" 8 2 12 1\n");
02614 printf(" 9 9 2 5\n");
02615 printf(" 10 10 1 1\n");
02616 printf(" 11 11 3 1\n");
02617 printf(" 12 12 4 1\n");
02618 printf(" 1\n");
02619 printf(" 1 1.5 1.5\n");
02620 printf(" # Generated by triangle -pqc box.poly\n");
02621 printf("\n");
02622 printf("Refinement and Area Constraints:\n");
02623 printf("\n");
02624 printf(
02625 " The -r switch causes a mesh (.node and .ele files) to be read and\n");
02626 printf(
02627 " refined. If the -p switch is also used, a .poly file is read and used to\n"
02628 );
02629 printf(
02630 " specify edges that are constrained and cannot be eliminated (although\n");
02631 printf(
02632 " they can be subdivided into smaller edges) by the refinement process.\n");
02633 printf("\n");
02634 printf(
02635 " When you refine a mesh, you generally want to impose tighter constraints.\n"
02636 );
02637 printf(
02638 " One way to accomplish this is to use -q with a larger angle, or -a\n");
02639 printf(
02640 " followed by a smaller area than you used to generate the mesh you are\n");
02641 printf(
02642 " refining. Another way to do this is to create an .area file, which\n");
02643 printf(
02644 " specifies a maximum area for each triangle, and use the -a switch\n");
02645 printf(
02646 " (without a number following). Each triangle's area constraint is applied\n"
02647 );
02648 printf(
02649 " to that triangle. Area constraints tend to diffuse as the mesh is\n");
02650 printf(
02651 " refined, so if there are large variations in area constraint between\n");
02652 printf(
02653 " adjacent triangles, you may not get the results you want. In that case,\n"
02654 );
02655 printf(
02656 " consider instead using the -u switch and writing a C procedure that\n");
02657 printf(" determines which triangles are too large.\n\n");
02658 printf(
02659 " If you are refining a mesh composed of linear (three-node) elements, the\n"
02660 );
02661 printf(
02662 " output mesh contains all the nodes present in the input mesh, in the same\n"
02663 );
02664 printf(
02665 " order, with new nodes added at the end of the .node file. However, the\n");
02666 printf(
02667 " refinement is not hierarchical: there is no guarantee that each output\n");
02668 printf(
02669 " element is contained in a single input element. Often, an output element\n"
02670 );
02671 printf(
02672 " can overlap two or three input elements, and some input edges are not\n");
02673 printf(
02674 " present in the output mesh. Hence, a sequence of refined meshes forms a\n"
02675 );
02676 printf(
02677 " hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
02678 printf(
02679 " mesh of higher-order elements, the hierarchical property applies only to\n"
02680 );
02681 printf(
02682 " the nodes at the corners of an element; the midpoint nodes on each edge\n");
02683 printf(" are discarded before the mesh is refined.\n\n");
02684 printf(
02685 " Maximum area constraints in .poly files operate differently from those in\n"
02686 );
02687 printf(
02688 " .area files. A maximum area in a .poly file applies to the whole\n");
02689 printf(
02690 " (segment-bounded) region in which a point falls, whereas a maximum area\n");
02691 printf(
02692 " in an .area file applies to only one triangle. Area constraints in .poly\n"
02693 );
02694 printf(
02695 " files are used only when a mesh is first generated, whereas area\n");
02696 printf(
02697 " constraints in .area files are used only to refine an existing mesh, and\n"
02698 );
02699 printf(
02700 " are typically based on a posteriori error estimates resulting from a\n");
02701 printf(" finite element simulation on that mesh.\n\n");
02702 printf(
02703 " `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
02704 printf(
02705 " refines the triangulation to enforce a 25 degree minimum angle, and then\n"
02706 );
02707 printf(
02708 " writes the refined triangulation to object.2.node and object.2.ele.\n");
02709 printf("\n");
02710 printf(
02711 " `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
02712 );
02713 printf(
02714 " After reconstructing the mesh and its subsegments, Triangle refines the\n");
02715 printf(
02716 " mesh so that no triangle has area greater than 6.2, and furthermore the\n");
02717 printf(
02718 " triangles satisfy the maximum area constraints in z.3.area. No angle\n");
02719 printf(
02720 " bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
02721 );
02722 printf(" z.4.poly.\n\n");
02723 printf(
02724 " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
02725 printf(
02726 " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
02727 printf(" suitable for multigrid.\n\n");
02728 printf("Convex Hulls and Mesh Boundaries:\n\n");
02729 printf(
02730 " If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
02731 printf(
02732 " hull as a by-product in the output .poly file if you use the -c switch.\n");
02733 printf(
02734 " There are faster algorithms for finding a two-dimensional convex hull\n");
02735 printf(" than triangulation, of course, but this one comes for free.\n\n");
02736 printf(
02737 " If the input is an unconstrained mesh (you are using the -r switch but\n");
02738 printf(
02739 " not the -p switch), Triangle produces a list of its boundary edges\n");
02740 printf(
02741 " (including hole boundaries) as a by-product when you use the -c switch.\n");
02742 printf(
02743 " If you also use the -p switch, the output .poly file contains all the\n");
02744 printf(" segments from the input .poly file as well.\n\n");
02745 printf("Voronoi Diagrams:\n\n");
02746 printf(
02747 " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
02748 printf(
02749 " .v.edge. For example, `triangle -v points' reads points.node, produces\n");
02750 printf(
02751 " its Delaunay triangulation in points.1.node and points.1.ele, and\n");
02752 printf(
02753 " produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
02754 );
02755 printf(
02756 " .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
02757 printf(
02758 " file contains a list of all Voronoi edges, some of which may be infinite\n"
02759 );
02760 printf(
02761 " rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
02762 printf(" vertices through Triangle, if so desired.)\n\n");
02763 printf(
02764 " This implementation does not use exact arithmetic to compute the Voronoi\n"
02765 );
02766 printf(
02767 " vertices, and does not check whether neighboring vertices are identical.\n"
02768 );
02769 printf(
02770 " Be forewarned that if the Delaunay triangulation is degenerate or\n");
02771 printf(
02772 " near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
02773 printf(" crossing edges.\n\n");
02774 printf(
02775 " The result is a valid Voronoi diagram only if Triangle's output is a true\n"
02776 );
02777 printf(
02778 " Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
02779 printf(
02780 " may contain crossing edges and other pathology) if the output is a CDT or\n"
02781 );
02782 printf(
02783 " CCDT, or if it has holes or concavities. If the triangulated domain is\n");
02784 printf(
02785 " convex and has no holes, you can use -D switch to force Triangle to\n");
02786 printf(
02787 " construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
02788 printf(" Voronoi diagram will be valid.\n\n");
02789 printf("Mesh Topology:\n\n");
02790 printf(
02791 " You may wish to know which triangles are adjacent to a certain Delaunay\n");
02792 printf(
02793 " edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
02794 printf(
02795 " Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
02796 printf(
02797 " each other. All of this information can be found by cross-referencing\n");
02798 printf(
02799 " output files with the recollection that the Delaunay triangulation and\n");
02800 printf(" the Voronoi diagram are planar duals.\n\n");
02801 printf(
02802 " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
02803 printf(
02804 " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
02805 printf(
02806 " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
02807 printf(
02808 " vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
02809 printf(" of vertex k of the corresponding .node file.\n\n");
02810 printf(
02811 " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
02812 printf(
02813 " vertices of the corresponding Voronoi edge. If the endpoints of a\n");
02814 printf(
02815 " Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
02816 );
02817 printf(
02818 " and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
02819 );
02820 printf(
02821 " respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
02822 );
02823 printf(
02824 " at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
02825 );
02826 printf(
02827 " a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
02828 );
02829 printf(
02830 " adjoin the right and left sides of the corresponding Voronoi edge,\n");
02831 printf(
02832 " respectively. To find which Voronoi cells are adjacent to each other,\n");
02833 printf(" just read the list of Delaunay edges.\n\n");
02834 printf(
02835 " Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
02836 );
02837 printf(
02838 " but you can reconstructed it straightforwardly. For instance, to find\n");
02839 printf(
02840 " all the edges of Voronoi cell 1, search the output .edge file for every\n");
02841 printf(
02842 " edge that has input vertex 1 as an endpoint. The corresponding dual\n");
02843 printf(
02844 " edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
02845 printf("\n");
02846 printf(
02847 " For each Voronoi vertex, the .neigh file gives a list of the three\n");
02848 printf(
02849 " Voronoi vertices attached to it. You might find this more convenient\n");
02850 printf(" than the .v.edge file.\n\n");
02851 printf("Quadratic Elements:\n\n");
02852 printf(
02853 " Triangle generates meshes with subparametric quadratic elements if the\n");
02854 printf(
02855 " -o2 switch is specified. Quadratic elements have six nodes per element,\n"
02856 );
02857 printf(
02858 " rather than three. `Subparametric' means that the edges of the triangles\n"
02859 );
02860 printf(
02861 " are always straight, so that subparametric quadratic elements are\n");
02862 printf(
02863 " geometrically identical to linear elements, even though they can be used\n"
02864 );
02865 printf(
02866 " with quadratic interpolating functions. The three extra nodes of an\n");
02867 printf(
02868 " element fall at the midpoints of the three edges, with the fourth, fifth,\n"
02869 );
02870 printf(
02871 " and sixth nodes appearing opposite the first, second, and third corners\n");
02872 printf(" respectively.\n\n");
02873 printf("Domains with Small Angles:\n\n");
02874 printf(
02875 " If two input segments adjoin each other at a small angle, clearly the -q\n"
02876 );
02877 printf(
02878 " switch cannot remove the small angle. Moreover, Triangle may have no\n");
02879 printf(
02880 " choice but to generate additional triangles whose smallest angles are\n");
02881 printf(
02882 " smaller than the specified bound. However, these triangles only appear\n");
02883 printf(
02884 " between input segments separated by small angles. Moreover, if you\n");
02885 printf(
02886 " request a minimum angle of theta degrees, Triangle will generally produce\n"
02887 );
02888 printf(
02889 " no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
02890 );
02891 printf(" the minimum angle.\n\n");
02892 printf("Statistics:\n\n");
02893 printf(
02894 " After generating a mesh, Triangle prints a count of entities in the\n");
02895 printf(
02896 " output mesh, including the number of vertices, triangles, edges, exterior\n"
02897 );
02898 printf(
02899 " boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
02900 printf(
02901 " including hole boundaries), interior boundary edges (i.e. subsegments of\n"
02902 );
02903 printf(
02904 " input segments not on the boundary), and total subsegments. If you've\n");
02905 printf(
02906 " forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
02907 );
02908 printf(
02909 " with the -rNEP switches to read the mesh and print the statistics without\n"
02910 );
02911 printf(
02912 " writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
02913 printf("\n");
02914 printf(
02915 " The -V switch produces extended statistics, including a rough estimate\n");
02916 printf(
02917 " of memory use, the number of calls to geometric predicates, and\n");
02918 printf(
02919 " histograms of the angles and the aspect ratios of the triangles in the\n");
02920 printf(" mesh.\n\n");
02921 printf("Exact Arithmetic:\n\n");
02922 printf(
02923 " Triangle uses adaptive exact arithmetic to perform what computational\n");
02924 printf(
02925 " geometers call the `orientation' and `incircle' tests. If the floating-\n"
02926 );
02927 printf(
02928 " point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
02929 printf(
02930 " most workstations do), and does not use extended precision internal\n");
02931 printf(
02932 " floating-point registers, then your output is guaranteed to be an\n");
02933 printf(
02934 " absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
02935 );
02936 printf(
02937 " error notwithstanding. The word `adaptive' implies that these arithmetic\n"
02938 );
02939 printf(
02940 " routines compute the result only to the precision necessary to guarantee\n"
02941 );
02942 printf(
02943 " correctness, so they are usually nearly as fast as their approximate\n");
02944 printf(" counterparts.\n\n");
02945 printf(
02946 " May CPUs, including Intel x86 processors, have extended precision\n");
02947 printf(
02948 " floating-point registers. These must be reconfigured so their precision\n"
02949 );
02950 printf(
02951 " is reduced to memory precision. Triangle does this if it is compiled\n");
02952 printf(" correctly. See the makefile for details.\n\n");
02953 printf(
02954 " The exact tests can be disabled with the -X switch. On most inputs, this\n"
02955 );
02956 printf(
02957 " switch reduces the computation time by about eight percent--it's not\n");
02958 printf(
02959 " worth the risk. There are rare difficult inputs (having many collinear\n");
02960 printf(
02961 " and cocircular vertices), however, for which the difference in speed\n");
02962 printf(
02963 " could be a factor of two. Be forewarned that these are precisely the\n");
02964 printf(
02965 " inputs most likely to cause errors if you use the -X switch. Hence, the\n"
02966 );
02967 printf(" -X switch is not recommended.\n\n");
02968 printf(
02969 " Unfortunately, the exact tests don't solve every numerical problem.\n");
02970 printf(
02971 " Exact arithmetic is not used to compute the positions of new vertices,\n");
02972 printf(
02973 " because the bit complexity of vertex coordinates would grow without\n");
02974 printf(
02975 " bound. Hence, segment intersections aren't computed exactly; in very\n");
02976 printf(
02977 " unusual cases, roundoff error in computing an intersection point might\n");
02978 printf(
02979 " actually lead to an inverted triangle and an invalid triangulation.\n");
02980 printf(
02981 " (This is one reason to specify your own intersection points in your .poly\n"
02982 );
02983 printf(
02984 " files.) Similarly, exact arithmetic is not used to compute the vertices\n"
02985 );
02986 printf(" of the Voronoi diagram.\n\n");
02987 printf(
02988 " Another pair of problems not solved by the exact arithmetic routines is\n");
02989 printf(
02990 " underflow and overflow. If Triangle is compiled for double precision\n");
02991 printf(
02992 " arithmetic, I believe that Triangle's geometric predicates work correctly\n"
02993 );
02994 printf(
02995 " if the exponent of every input coordinate falls in the range [-148, 201].\n"
02996 );
02997 printf(
02998 " Underflow can silently prevent the orientation and incircle tests from\n");
02999 printf(
03000 " being performed exactly, while overflow typically causes a floating\n");
03001 printf(" exception.\n\n");
03002 printf("Calling Triangle from Another Program:\n\n");
03003 printf(" Read the file triangle.h for details.\n\n");
03004 printf("Troubleshooting:\n\n");
03005 printf(" Please read this section before mailing me bugs.\n\n");
03006 printf(" `My output mesh has no triangles!'\n\n");
03007 printf(
03008 " If you're using a PSLG, you've probably failed to specify a proper set\n"
03009 );
03010 printf(
03011 " of bounding segments, or forgotten to use the -c switch. Or you may\n");
03012 printf(
03013 " have placed a hole badly, thereby eating all your triangles. To test\n");
03014 printf(" these possibilities, try again with the -c and -O switches.\n");
03015 printf(
03016 " Alternatively, all your input vertices may be collinear, in which case\n"
03017 );
03018 printf(" you can hardly expect to triangulate them.\n\n");
03019 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
03020 printf(
03021 " Bad things can happen when triangles get so small that the distance\n");
03022 printf(
03023 " between their vertices isn't much larger than the precision of your\n");
03024 printf(
03025 " machine's arithmetic. If you've compiled Triangle for single-precision\n"
03026 );
03027 printf(
03028 " arithmetic, you might do better by recompiling it for double-precision.\n"
03029 );
03030 printf(
03031 " Then again, you might just have to settle for more lenient constraints\n"
03032 );
03033 printf(
03034 " on the minimum angle and the maximum area than you had planned.\n");
03035 printf("\n");
03036 printf(
03037 " You can minimize precision problems by ensuring that the origin lies\n");
03038 printf(
03039 " inside your vertex set, or even inside the densest part of your\n");
03040 printf(
03041 " mesh. If you're triangulating an object whose x-coordinates all fall\n");
03042 printf(
03043 " between 6247133 and 6247134, you're not leaving much floating-point\n");
03044 printf(" precision for Triangle to work with.\n\n");
03045 printf(
03046 " Precision problems can occur covertly if the input PSLG contains two\n");
03047 printf(
03048 " segments that meet (or intersect) at an extremely small angle, or if\n");
03049 printf(
03050 " such an angle is introduced by the -c switch. If you don't realize\n");
03051 printf(
03052 " that a tiny angle is being formed, you might never discover why\n");
03053 printf(
03054 " Triangle is crashing. To check for this possibility, use the -S switch\n"
03055 );
03056 printf(
03057 " (with an appropriate limit on the number of Steiner points, found by\n");
03058 printf(
03059 " trial-and-error) to stop Triangle early, and view the output .poly file\n"
03060 );
03061 printf(
03062 " with Show Me (described below). Look carefully for regions where dense\n"
03063 );
03064 printf(
03065 " clusters of vertices are forming and for small angles between segments.\n"
03066 );
03067 printf(
03068 " Zoom in closely, as such segments might look like a single segment from\n"
03069 );
03070 printf(" a distance.\n\n");
03071 printf(
03072 " If some of the input values are too large, Triangle may suffer a\n");
03073 printf(
03074 " floating exception due to overflow when attempting to perform an\n");
03075 printf(
03076 " orientation or incircle test. (Read the section on exact arithmetic\n");
03077 printf(
03078 " above.) Again, I recommend compiling Triangle for double (rather\n");
03079 printf(" than single) precision arithmetic.\n\n");
03080 printf(
03081 " Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
03082 printf(
03083 " -u) with an input that is not segment-bounded--that is, if your input\n");
03084 printf(
03085 " is a vertex set, or you're using the -c switch. If the convex hull of\n"
03086 );
03087 printf(
03088 " your input vertices has collinear vertices on its boundary, an input\n");
03089 printf(
03090 " vertex that you think lies on the convex hull might actually lie just\n");
03091 printf(
03092 " inside the convex hull. If so, the vertex and the nearby convex hull\n");
03093 printf(
03094 " edge form an extremely thin triangle. When Triangle tries to refine\n");
03095 printf(
03096 " the mesh to enforce angle and area constraints, Triangle might generate\n"
03097 );
03098 printf(
03099 " extremely tiny triangles, or it might fail because of insufficient\n");
03100 printf(" floating-point precision.\n\n");
03101 printf(
03102 " `The numbering of the output vertices doesn't match the input vertices.'\n"
03103 );
03104 printf("\n");
03105 printf(
03106 " You may have had duplicate input vertices, or you may have eaten some\n");
03107 printf(
03108 " of your input vertices with a hole, or by placing them outside the area\n"
03109 );
03110 printf(
03111 " enclosed by segments. In any case, you can solve the problem by not\n");
03112 printf(" using the -j switch.\n\n");
03113 printf(
03114 " `Triangle executes without incident, but when I look at the resulting\n");
03115 printf(
03116 " mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
03117 printf("\n");
03118 printf(
03119 " If you select the -X switch, Triangle occasionally makes mistakes due\n");
03120 printf(
03121 " to floating-point roundoff error. Although these errors are rare,\n");
03122 printf(
03123 " don't use the -X switch. If you still have problems, please report the\n"
03124 );
03125 printf(" bug.\n\n");
03126 printf(
03127 " `Triangle executes without incident, but when I look at the resulting\n");
03128 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
03129 printf(" inconsistencies.'\n");
03130 printf("\n");
03131 printf(
03132 " If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
03133 );
03134 printf(
03135 " diagram if the domain you are triangulating is convex and free of\n");
03136 printf(
03137 " holes, and you use the -D switch to construct a conforming Delaunay\n");
03138 printf(" triangulation (instead of a CDT or CCDT).\n\n");
03139 printf(
03140 " Strange things can happen if you've taken liberties with your PSLG. Do\n");
03141 printf(
03142 " you have a vertex lying in the middle of a segment? Triangle sometimes\n");
03143 printf(
03144 " copes poorly with that sort of thing. Do you want to lay out a collinear\n"
03145 );
03146 printf(
03147 " row of evenly spaced, segment-connected vertices? Have you simply\n");
03148 printf(
03149 " defined one long segment connecting the leftmost vertex to the rightmost\n"
03150 );
03151 printf(
03152 " vertex, and a bunch of vertices lying along it? This method occasionally\n"
03153 );
03154 printf(
03155 " works, especially with horizontal and vertical lines, but often it\n");
03156 printf(
03157 " doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
03158 );
03159 printf(" separate segment. If you don't like it, tough.\n\n");
03160 printf(
03161 " Furthermore, if you have segments that intersect other than at their\n");
03162 printf(
03163 " endpoints, try not to let the intersections fall extremely close to PSLG\n"
03164 );
03165 printf(" vertices or each other.\n\n");
03166 printf(
03167 " If you have problems refining a triangulation not produced by Triangle:\n");
03168 printf(
03169 " Are you sure the triangulation is geometrically valid? Is it formatted\n");
03170 printf(
03171 " correctly for Triangle? Are the triangles all listed so the first three\n"
03172 );
03173 printf(
03174 " vertices are their corners in counterclockwise order? Are all of the\n");
03175 printf(
03176 " triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
03177 );
03178 printf(" assumes that it starts with a CDT.\n\n");
03179 printf("Show Me:\n\n");
03180 printf(
03181 " Triangle comes with a separate program named `Show Me', whose primary\n");
03182 printf(
03183 " purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
03184 );
03185 printf(
03186 " purpose is to check the validity of your input files, and do so more\n");
03187 printf(
03188 " thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
03189 printf(
03190 " you have the X Windows system. Sorry, Microsoft Windows users.\n");
03191 printf("\n");
03192 printf("Triangle on the Web:\n");
03193 printf("\n");
03194 printf(" To see an illustrated version of these instructions, check out\n");
03195 printf("\n");
03196 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
03197 printf("\n");
03198 printf("A Brief Plea:\n");
03199 printf("\n");
03200 printf(
03201 " If you use Triangle, and especially if you use it to accomplish real\n");
03202 printf(
03203 " work, I would like very much to hear from you. A short letter or email\n");
03204 printf(
03205 " (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
03206 );
03207 printf(
03208 " to me. The more people I know are using this program, the more easily I\n"
03209 );
03210 printf(
03211 " can justify spending time on improvements, which in turn will benefit\n");
03212 printf(
03213 " you. Also, I can put you on a list to receive email whenever a new\n");
03214 printf(" version of Triangle is available.\n\n");
03215 printf(
03216 " If you use a mesh generated by Triangle in a publication, please include\n"
03217 );
03218 printf(
03219 " an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
03220 );
03221 printf(
03222 " If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
03223 printf(
03224 " ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
03225 printf(
03226 " Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
03227 printf(
03228 " Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
03229 printf(
03230 " Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
03231 printf(
03232 " Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
03233 );
03234 printf(" Geometry.)'\n\n");
03235 printf("Research credit:\n\n");
03236 printf(
03237 " Of course, I can take credit for only a fraction of the ideas that made\n");
03238 printf(
03239 " this mesh generator possible. Triangle owes its existence to the efforts\n"
03240 );
03241 printf(
03242 " of many fine computational geometers and other researchers, including\n");
03243 printf(
03244 " Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
03245 );
03246 printf(
03247 " Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
03248 printf(
03249 " Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
03250 printf(
03251 " Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
03252 printf(
03253 " Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
03254 );
03255 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
03256 printf(
03257 " Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
03258 printf(" source code for references.\n\n");
03259 triexit(0);
03260 }
03261
03262 #endif
03263
03264
03265
03266
03267
03268
03269
03270 void internalerror()
03271 {
03272 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
03273 printf(" Include the message above, your input data set, and the exact\n");
03274 printf(" command line you used to run Triangle.\n");
03275 triexit(1);
03276 }
03277
03278
03279
03280
03281
03282
03283
03284
03285 #ifdef ANSI_DECLARATORS
03286 void parsecommandline(int argc, char **argv, struct behavior *b)
03287 #else
03288 void parsecommandline(argc, argv, b)
03289 int argc;
03290 char **argv;
03291 struct behavior *b;
03292 #endif
03293
03294 {
03295 #ifdef TRILIBRARY
03296 #define STARTINDEX 0
03297 #else
03298 #define STARTINDEX 1
03299 int increment;
03300 int meshnumber;
03301 #endif
03302 int i, j, k;
03303 char workstring[FILENAMESIZE];
03304
03305 b->poly = b->refine = b->quality = 0;
03306 b->vararea = b->fixedarea = b->usertest = 0;
03307 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
03308 b->firstnumber = 1;
03309 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
03310 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
03311 b->noiterationnum = 0;
03312 b->noholes = b->noexact = 0;
03313 b->incremental = b->sweepline = 0;
03314 b->dwyer = 1;
03315 b->splitseg = 0;
03316 b->docheck = 0;
03317 b->nobisect = 0;
03318 b->conformdel = 0;
03319 b->steiner = -1;
03320 b->order = 1;
03321 b->minangle = 0.0;
03322 b->maxarea = -1.0;
03323 b->quiet = b->verbose = 0;
03324 #ifndef TRILIBRARY
03325 b->innodefilename[0] = '\0';
03326 #endif
03327
03328 for (i = STARTINDEX; i < argc; i++) {
03329 #ifndef TRILIBRARY
03330 if (argv[i][0] == '-') {
03331 #endif
03332 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
03333 if (argv[i][j] == 'p') {
03334 b->poly = 1;
03335 }
03336 #ifndef CDT_ONLY
03337 if (argv[i][j] == 'r') {
03338 b->refine = 1;
03339 }
03340 if (argv[i][j] == 'q') {
03341 b->quality = 1;
03342 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03343 (argv[i][j + 1] == '.')) {
03344 k = 0;
03345 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03346 (argv[i][j + 1] == '.')) {
03347 j++;
03348 workstring[k] = argv[i][j];
03349 k++;
03350 }
03351 workstring[k] = '\0';
03352 b->minangle = (REAL) strtod(workstring, (char **) NULL);
03353 } else {
03354 b->minangle = 20.0;
03355 }
03356 }
03357 if (argv[i][j] == 'a') {
03358 b->quality = 1;
03359 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03360 (argv[i][j + 1] == '.')) {
03361 b->fixedarea = 1;
03362 k = 0;
03363 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03364 (argv[i][j + 1] == '.')) {
03365 j++;
03366 workstring[k] = argv[i][j];
03367 k++;
03368 }
03369 workstring[k] = '\0';
03370 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
03371 if (b->maxarea <= 0.0) {
03372 printf("Error: Maximum area must be greater than zero.\n");
03373 triexit(1);
03374 }
03375 } else {
03376 b->vararea = 1;
03377 }
03378 }
03379 if (argv[i][j] == 'u') {
03380 b->quality = 1;
03381 b->usertest = 1;
03382 }
03383 #endif
03384 if (argv[i][j] == 'A') {
03385 b->regionattrib = 1;
03386 }
03387 if (argv[i][j] == 'c') {
03388 b->convex = 1;
03389 }
03390 if (argv[i][j] == 'w') {
03391 b->weighted = 1;
03392 }
03393 if (argv[i][j] == 'W') {
03394 b->weighted = 2;
03395 }
03396 if (argv[i][j] == 'j') {
03397 b->jettison = 1;
03398 }
03399 if (argv[i][j] == 'z') {
03400 b->firstnumber = 0;
03401 }
03402 if (argv[i][j] == 'e') {
03403 b->edgesout = 1;
03404 }
03405 if (argv[i][j] == 'v') {
03406 b->voronoi = 1;
03407 }
03408 if (argv[i][j] == 'n') {
03409 b->neighbors = 1;
03410 }
03411 if (argv[i][j] == 'g') {
03412 b->geomview = 1;
03413 }
03414 if (argv[i][j] == 'B') {
03415 b->nobound = 1;
03416 }
03417 if (argv[i][j] == 'P') {
03418 b->nopolywritten = 1;
03419 }
03420 if (argv[i][j] == 'N') {
03421 b->nonodewritten = 1;
03422 }
03423 if (argv[i][j] == 'E') {
03424 b->noelewritten = 1;
03425 }
03426 #ifndef TRILIBRARY
03427 if (argv[i][j] == 'I') {
03428 b->noiterationnum = 1;
03429 }
03430 #endif
03431 if (argv[i][j] == 'O') {
03432 b->noholes = 1;
03433 }
03434 if (argv[i][j] == 'X') {
03435 b->noexact = 1;
03436 }
03437 if (argv[i][j] == 'o') {
03438 if (argv[i][j + 1] == '2') {
03439 j++;
03440 b->order = 2;
03441 }
03442 }
03443 #ifndef CDT_ONLY
03444 if (argv[i][j] == 'Y') {
03445 b->nobisect++;
03446 }
03447 if (argv[i][j] == 'S') {
03448 b->steiner = 0;
03449 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
03450 j++;
03451 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
03452 }
03453 }
03454 #endif
03455 #ifndef REDUCED
03456 if (argv[i][j] == 'i') {
03457 b->incremental = 1;
03458 }
03459 if (argv[i][j] == 'F') {
03460 b->sweepline = 1;
03461 }
03462 #endif
03463 if (argv[i][j] == 'l') {
03464 b->dwyer = 0;
03465 }
03466 #ifndef REDUCED
03467 #ifndef CDT_ONLY
03468 if (argv[i][j] == 's') {
03469 b->splitseg = 1;
03470 }
03471 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
03472 b->quality = 1;
03473 b->conformdel = 1;
03474 }
03475 #endif
03476 if (argv[i][j] == 'C') {
03477 b->docheck = 1;
03478 }
03479 #endif
03480 if (argv[i][j] == 'Q') {
03481 b->quiet = 1;
03482 }
03483 if (argv[i][j] == 'V') {
03484 b->verbose++;
03485 }
03486 #ifndef TRILIBRARY
03487 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03488 (argv[i][j] == '?')) {
03489 info();
03490 }
03491 #endif
03492 }
03493 #ifndef TRILIBRARY
03494 } else {
03495 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
03496 b->innodefilename[FILENAMESIZE - 1] = '\0';
03497 }
03498 #endif
03499 }
03500 #ifndef TRILIBRARY
03501 if (b->innodefilename[0] == '\0') {
03502 syntax();
03503 }
03504 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
03505 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03506 }
03507 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
03508 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03509 b->poly = 1;
03510 }
03511 #ifndef CDT_ONLY
03512 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
03513 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
03514 b->refine = 1;
03515 }
03516 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
03517 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03518 b->refine = 1;
03519 b->quality = 1;
03520 b->vararea = 1;
03521 }
03522 #endif
03523 #endif
03524 b->usesegments = b->poly || b->refine || b->quality || b->convex;
03525 b->goodangle = cos(b->minangle * PI / 180.0);
03526 if (b->goodangle == 1.0) {
03527 b->offconstant = 0.0;
03528 } else {
03529 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
03530 }
03531 b->goodangle *= b->goodangle;
03532 if (b->refine && b->noiterationnum) {
03533 printf(
03534 "Error: You cannot use the -I switch when refining a triangulation.\n");
03535 triexit(1);
03536 }
03537
03538
03539 if (!b->refine && !b->poly) {
03540 b->vararea = 0;
03541 }
03542
03543
03544 if (b->refine || !b->poly) {
03545 b->regionattrib = 0;
03546 }
03547
03548
03549 if (b->weighted && (b->poly || b->quality)) {
03550 b->weighted = 0;
03551 if (!b->quiet) {
03552 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
03553 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
03554 );
03555 }
03556 }
03557 if (b->jettison && b->nonodewritten && !b->quiet) {
03558 printf("Warning: -j and -N switches are somewhat incompatible.\n");
03559 printf(" If any vertices are jettisoned, you will need the output\n");
03560 printf(" .node file to reconstruct the new node indices.");
03561 }
03562
03563 #ifndef TRILIBRARY
03564 strcpy(b->inpolyfilename, b->innodefilename);
03565 strcpy(b->inelefilename, b->innodefilename);
03566 strcpy(b->areafilename, b->innodefilename);
03567 increment = 0;
03568 strcpy(workstring, b->innodefilename);
03569 j = 1;
03570 while (workstring[j] != '\0') {
03571 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03572 increment = j + 1;
03573 }
03574 j++;
03575 }
03576 meshnumber = 0;
03577 if (increment > 0) {
03578 j = increment;
03579 do {
03580 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03581 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03582 } else {
03583 increment = 0;
03584 }
03585 j++;
03586 } while (workstring[j] != '\0');
03587 }
03588 if (b->noiterationnum) {
03589 strcpy(b->outnodefilename, b->innodefilename);
03590 strcpy(b->outelefilename, b->innodefilename);
03591 strcpy(b->edgefilename, b->innodefilename);
03592 strcpy(b->vnodefilename, b->innodefilename);
03593 strcpy(b->vedgefilename, b->innodefilename);
03594 strcpy(b->neighborfilename, b->innodefilename);
03595 strcpy(b->offfilename, b->innodefilename);
03596 strcat(b->outnodefilename, ".node");
03597 strcat(b->outelefilename, ".ele");
03598 strcat(b->edgefilename, ".edge");
03599 strcat(b->vnodefilename, ".v.node");
03600 strcat(b->vedgefilename, ".v.edge");
03601 strcat(b->neighborfilename, ".neigh");
03602 strcat(b->offfilename, ".off");
03603 } else if (increment == 0) {
03604 strcpy(b->outnodefilename, b->innodefilename);
03605 strcpy(b->outpolyfilename, b->innodefilename);
03606 strcpy(b->outelefilename, b->innodefilename);
03607 strcpy(b->edgefilename, b->innodefilename);
03608 strcpy(b->vnodefilename, b->innodefilename);
03609 strcpy(b->vedgefilename, b->innodefilename);
03610 strcpy(b->neighborfilename, b->innodefilename);
03611 strcpy(b->offfilename, b->innodefilename);
03612 strcat(b->outnodefilename, ".1.node");
03613 strcat(b->outpolyfilename, ".1.poly");
03614 strcat(b->outelefilename, ".1.ele");
03615 strcat(b->edgefilename, ".1.edge");
03616 strcat(b->vnodefilename, ".1.v.node");
03617 strcat(b->vedgefilename, ".1.v.edge");
03618 strcat(b->neighborfilename, ".1.neigh");
03619 strcat(b->offfilename, ".1.off");
03620 } else {
03621 workstring[increment] = '%';
03622 workstring[increment + 1] = 'd';
03623 workstring[increment + 2] = '\0';
03624 sprintf(b->outnodefilename, workstring, meshnumber + 1);
03625 strcpy(b->outpolyfilename, b->outnodefilename);
03626 strcpy(b->outelefilename, b->outnodefilename);
03627 strcpy(b->edgefilename, b->outnodefilename);
03628 strcpy(b->vnodefilename, b->outnodefilename);
03629 strcpy(b->vedgefilename, b->outnodefilename);
03630 strcpy(b->neighborfilename, b->outnodefilename);
03631 strcpy(b->offfilename, b->outnodefilename);
03632 strcat(b->outnodefilename, ".node");
03633 strcat(b->outpolyfilename, ".poly");
03634 strcat(b->outelefilename, ".ele");
03635 strcat(b->edgefilename, ".edge");
03636 strcat(b->vnodefilename, ".v.node");
03637 strcat(b->vedgefilename, ".v.edge");
03638 strcat(b->neighborfilename, ".neigh");
03639 strcat(b->offfilename, ".off");
03640 }
03641 strcat(b->innodefilename, ".node");
03642 strcat(b->inpolyfilename, ".poly");
03643 strcat(b->inelefilename, ".ele");
03644 strcat(b->areafilename, ".area");
03645 #endif
03646 }
03647
03650
03651
03652
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667 #ifdef ANSI_DECLARATORS
03668 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
03669 #else
03670 void printtriangle(m, b, t)
03671 struct mesh *m;
03672 struct behavior *b;
03673 struct otri *t;
03674 #endif
03675
03676 {
03677 struct otri printtri;
03678 struct osub printsh;
03679 vertex printvertex;
03680
03681 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
03682 t->orient);
03683 decode(t->tri[0], printtri);
03684 if (printtri.tri == m->dummytri) {
03685 printf(" [0] = Outer space\n");
03686 } else {
03687 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
03688 printtri.orient);
03689 }
03690 decode(t->tri[1], printtri);
03691 if (printtri.tri == m->dummytri) {
03692 printf(" [1] = Outer space\n");
03693 } else {
03694 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
03695 printtri.orient);
03696 }
03697 decode(t->tri[2], printtri);
03698 if (printtri.tri == m->dummytri) {
03699 printf(" [2] = Outer space\n");
03700 } else {
03701 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
03702 printtri.orient);
03703 }
03704
03705 org(*t, printvertex);
03706 if (printvertex == (vertex) NULL)
03707 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
03708 else
03709 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03710 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
03711 printvertex[0], printvertex[1]);
03712 dest(*t, printvertex);
03713 if (printvertex == (vertex) NULL)
03714 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
03715 else
03716 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03717 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
03718 printvertex[0], printvertex[1]);
03719 apex(*t, printvertex);
03720 if (printvertex == (vertex) NULL)
03721 printf(" Apex [%d] = NULL\n", t->orient + 3);
03722 else
03723 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
03724 t->orient + 3, (unsigned long) printvertex,
03725 printvertex[0], printvertex[1]);
03726
03727 if (b->usesegments) {
03728 sdecode(t->tri[6], printsh);
03729 if (printsh.ss != m->dummysub) {
03730 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
03731 printsh.ssorient);
03732 }
03733 sdecode(t->tri[7], printsh);
03734 if (printsh.ss != m->dummysub) {
03735 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
03736 printsh.ssorient);
03737 }
03738 sdecode(t->tri[8], printsh);
03739 if (printsh.ss != m->dummysub) {
03740 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
03741 printsh.ssorient);
03742 }
03743 }
03744
03745 if (b->vararea) {
03746 printf(" Area constraint: %.4g\n", areabound(*t));
03747 }
03748 }
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761 #ifdef ANSI_DECLARATORS
03762 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
03763 #else
03764 void printsubseg(m, b, s)
03765 struct mesh *m;
03766 struct behavior *b;
03767 struct osub *s;
03768 #endif
03769
03770 {
03771 struct osub printsh;
03772 struct otri printtri;
03773 vertex printvertex;
03774
03775 printf("subsegment x%lx with orientation %d and mark %d:\n",
03776 (unsigned long) s->ss, s->ssorient, mark(*s));
03777 sdecode(s->ss[0], printsh);
03778 if (printsh.ss == m->dummysub) {
03779 printf(" [0] = No subsegment\n");
03780 } else {
03781 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
03782 printsh.ssorient);
03783 }
03784 sdecode(s->ss[1], printsh);
03785 if (printsh.ss == m->dummysub) {
03786 printf(" [1] = No subsegment\n");
03787 } else {
03788 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
03789 printsh.ssorient);
03790 }
03791
03792 sorg(*s, printvertex);
03793 if (printvertex == (vertex) NULL)
03794 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
03795 else
03796 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03797 2 + s->ssorient, (unsigned long) printvertex,
03798 printvertex[0], printvertex[1]);
03799 sdest(*s, printvertex);
03800 if (printvertex == (vertex) NULL)
03801 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
03802 else
03803 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03804 3 - s->ssorient, (unsigned long) printvertex,
03805 printvertex[0], printvertex[1]);
03806
03807 decode(s->ss[6], printtri);
03808 if (printtri.tri == m->dummytri) {
03809 printf(" [6] = Outer space\n");
03810 } else {
03811 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
03812 printtri.orient);
03813 }
03814 decode(s->ss[7], printtri);
03815 if (printtri.tri == m->dummytri) {
03816 printf(" [7] = Outer space\n");
03817 } else {
03818 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
03819 printtri.orient);
03820 }
03821
03822 segorg(*s, printvertex);
03823 if (printvertex == (vertex) NULL)
03824 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
03825 else
03826 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
03827 4 + s->ssorient, (unsigned long) printvertex,
03828 printvertex[0], printvertex[1]);
03829 segdest(*s, printvertex);
03830 if (printvertex == (vertex) NULL)
03831 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
03832 else
03833 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
03834 5 - s->ssorient, (unsigned long) printvertex,
03835 printvertex[0], printvertex[1]);
03836 }
03837
03840
03841
03842
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855 #ifdef ANSI_DECLARATORS
03856 void poolzero(struct memorypool *pool)
03857 #else
03858 void poolzero(pool)
03859 struct memorypool *pool;
03860 #endif
03861
03862 {
03863 pool->firstblock = (VOID **) NULL;
03864 pool->nowblock = (VOID **) NULL;
03865 pool->nextitem = (VOID *) NULL;
03866 pool->deaditemstack = (VOID *) NULL;
03867 pool->pathblock = (VOID **) NULL;
03868 pool->pathitem = (VOID *) NULL;
03869 pool->alignbytes = 0;
03870 pool->itembytes = 0;
03871 pool->itemsperblock = 0;
03872 pool->itemsfirstblock = 0;
03873 pool->items = 0;
03874 pool->maxitems = 0;
03875 pool->unallocateditems = 0;
03876 pool->pathitemsleft = 0;
03877 }
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889 #ifdef ANSI_DECLARATORS
03890 void poolrestart(struct memorypool *pool)
03891 #else
03892 void poolrestart(pool)
03893 struct memorypool *pool;
03894 #endif
03895
03896 {
03897 unsigned long alignptr;
03898
03899 pool->items = 0;
03900 pool->maxitems = 0;
03901
03902
03903 pool->nowblock = pool->firstblock;
03904
03905 alignptr = (unsigned long) (pool->nowblock + 1);
03906
03907 pool->nextitem = (VOID *)
03908 (alignptr + (unsigned long) pool->alignbytes -
03909 (alignptr % (unsigned long) pool->alignbytes));
03910
03911 pool->unallocateditems = pool->itemsfirstblock;
03912
03913 pool->deaditemstack = (VOID *) NULL;
03914 }
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933
03934
03935 #ifdef ANSI_DECLARATORS
03936 void poolinit(struct memorypool *pool, int bytecount, int itemcount,
03937 int firstitemcount, int alignment)
03938 #else
03939 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
03940 struct memorypool *pool;
03941 int bytecount;
03942 int itemcount;
03943 int firstitemcount;
03944 int alignment;
03945 #endif
03946
03947 {
03948
03949
03950
03951
03952 if (alignment > sizeof(VOID *)) {
03953 pool->alignbytes = alignment;
03954 } else {
03955 pool->alignbytes = sizeof(VOID *);
03956 }
03957 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
03958 pool->alignbytes;
03959 pool->itemsperblock = itemcount;
03960 if (firstitemcount == 0) {
03961 pool->itemsfirstblock = itemcount;
03962 } else {
03963 pool->itemsfirstblock = firstitemcount;
03964 }
03965
03966
03967
03968
03969 pool->firstblock = (VOID **)
03970 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
03971 pool->alignbytes);
03972
03973 *(pool->firstblock) = (VOID *) NULL;
03974 poolrestart(pool);
03975 }
03976
03977
03978
03979
03980
03981
03982
03983 #ifdef ANSI_DECLARATORS
03984 void pooldeinit(struct memorypool *pool)
03985 #else
03986 void pooldeinit(pool)
03987 struct memorypool *pool;
03988 #endif
03989
03990 {
03991 while (pool->firstblock != (VOID **) NULL) {
03992 pool->nowblock = (VOID **) *(pool->firstblock);
03993 trifree((VOID *) pool->firstblock);
03994 pool->firstblock = pool->nowblock;
03995 }
03996 }
03997
03998
03999
04000
04001
04002
04003
04004 #ifdef ANSI_DECLARATORS
04005 VOID *poolalloc(struct memorypool *pool)
04006 #else
04007 VOID *poolalloc(pool)
04008 struct memorypool *pool;
04009 #endif
04010
04011 {
04012 VOID *newitem;
04013 VOID **newblock;
04014 unsigned long alignptr;
04015
04016
04017
04018 if (pool->deaditemstack != (VOID *) NULL) {
04019 newitem = pool->deaditemstack;
04020 pool->deaditemstack = * (VOID **) pool->deaditemstack;
04021 } else {
04022
04023 if (pool->unallocateditems == 0) {
04024
04025 if (*(pool->nowblock) == (VOID *) NULL) {
04026
04027 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
04028 (int) sizeof(VOID *) +
04029 pool->alignbytes);
04030 *(pool->nowblock) = (VOID *) newblock;
04031
04032 *newblock = (VOID *) NULL;
04033 }
04034
04035
04036 pool->nowblock = (VOID **) *(pool->nowblock);
04037
04038
04039 alignptr = (unsigned long) (pool->nowblock + 1);
04040
04041 pool->nextitem = (VOID *)
04042 (alignptr + (unsigned long) pool->alignbytes -
04043 (alignptr % (unsigned long) pool->alignbytes));
04044
04045 pool->unallocateditems = pool->itemsperblock;
04046 }
04047
04048
04049 newitem = pool->nextitem;
04050
04051 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
04052 pool->unallocateditems--;
04053 pool->maxitems++;
04054 }
04055 pool->items++;
04056 return newitem;
04057 }
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067 #ifdef ANSI_DECLARATORS
04068 void pooldealloc(struct memorypool *pool, VOID *dyingitem)
04069 #else
04070 void pooldealloc(pool, dyingitem)
04071 struct memorypool *pool;
04072 VOID *dyingitem;
04073 #endif
04074
04075 {
04076
04077 *((VOID **) dyingitem) = pool->deaditemstack;
04078 pool->deaditemstack = dyingitem;
04079 pool->items--;
04080 }
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090 #ifdef ANSI_DECLARATORS
04091 void traversalinit(struct memorypool *pool)
04092 #else
04093 void traversalinit(pool)
04094 struct memorypool *pool;
04095 #endif
04096
04097 {
04098 unsigned long alignptr;
04099
04100
04101 pool->pathblock = pool->firstblock;
04102
04103 alignptr = (unsigned long) (pool->pathblock + 1);
04104
04105 pool->pathitem = (VOID *)
04106 (alignptr + (unsigned long) pool->alignbytes -
04107 (alignptr % (unsigned long) pool->alignbytes));
04108
04109 pool->pathitemsleft = pool->itemsfirstblock;
04110 }
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124
04125
04126 #ifdef ANSI_DECLARATORS
04127 VOID *traverse(struct memorypool *pool)
04128 #else
04129 VOID *traverse(pool)
04130 struct memorypool *pool;
04131 #endif
04132
04133 {
04134 VOID *newitem;
04135 unsigned long alignptr;
04136
04137
04138 if (pool->pathitem == pool->nextitem) {
04139 return (VOID *) NULL;
04140 }
04141
04142
04143 if (pool->pathitemsleft == 0) {
04144
04145 pool->pathblock = (VOID **) *(pool->pathblock);
04146
04147 alignptr = (unsigned long) (pool->pathblock + 1);
04148
04149 pool->pathitem = (VOID *)
04150 (alignptr + (unsigned long) pool->alignbytes -
04151 (alignptr % (unsigned long) pool->alignbytes));
04152
04153 pool->pathitemsleft = pool->itemsperblock;
04154 }
04155
04156 newitem = pool->pathitem;
04157
04158 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
04159 pool->pathitemsleft--;
04160 return newitem;
04161 }
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191 #ifdef ANSI_DECLARATORS
04192 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
04193 int subsegbytes)
04194 #else
04195 void dummyinit(m, b, trianglebytes, subsegbytes)
04196 struct mesh *m;
04197 struct behavior *b;
04198 int trianglebytes;
04199 int subsegbytes;
04200 #endif
04201
04202 {
04203 unsigned long alignptr;
04204
04205
04206 m->dummytribase = (triangle *) trimalloc(trianglebytes +
04207 m->triangles.alignbytes);
04208
04209 alignptr = (unsigned long) m->dummytribase;
04210 m->dummytri = (triangle *)
04211 (alignptr + (unsigned long) m->triangles.alignbytes -
04212 (alignptr % (unsigned long) m->triangles.alignbytes));
04213
04214
04215
04216
04217 m->dummytri[0] = (triangle) m->dummytri;
04218 m->dummytri[1] = (triangle) m->dummytri;
04219 m->dummytri[2] = (triangle) m->dummytri;
04220
04221 m->dummytri[3] = (triangle) NULL;
04222 m->dummytri[4] = (triangle) NULL;
04223 m->dummytri[5] = (triangle) NULL;
04224
04225 if (b->usesegments) {
04226
04227
04228
04229 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
04230 m->subsegs.alignbytes);
04231
04232 alignptr = (unsigned long) m->dummysubbase;
04233 m->dummysub = (subseg *)
04234 (alignptr + (unsigned long) m->subsegs.alignbytes -
04235 (alignptr % (unsigned long) m->subsegs.alignbytes));
04236
04237
04238
04239
04240 m->dummysub[0] = (subseg) m->dummysub;
04241 m->dummysub[1] = (subseg) m->dummysub;
04242
04243 m->dummysub[2] = (subseg) NULL;
04244 m->dummysub[3] = (subseg) NULL;
04245 m->dummysub[4] = (subseg) NULL;
04246 m->dummysub[5] = (subseg) NULL;
04247
04248 m->dummysub[6] = (subseg) m->dummytri;
04249 m->dummysub[7] = (subseg) m->dummytri;
04250
04251 * (int *) (m->dummysub + 8) = 0;
04252
04253
04254
04255 m->dummytri[6] = (triangle) m->dummysub;
04256 m->dummytri[7] = (triangle) m->dummysub;
04257 m->dummytri[8] = (triangle) m->dummysub;
04258 }
04259 }
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271 #ifdef ANSI_DECLARATORS
04272 void initializevertexpool(struct mesh *m, struct behavior *b)
04273 #else
04274 void initializevertexpool(m, b)
04275 struct mesh *m;
04276 struct behavior *b;
04277 #endif
04278
04279 {
04280 int vertexsize;
04281
04282
04283
04284
04285 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
04286 sizeof(int) - 1) /
04287 sizeof(int);
04288 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
04289 if (b->poly) {
04290
04291
04292 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
04293 sizeof(triangle);
04294 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
04295 }
04296
04297
04298 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
04299 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
04300 sizeof(REAL));
04301 }
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314 #ifdef ANSI_DECLARATORS
04315 void initializetrisubpools(struct mesh *m, struct behavior *b)
04316 #else
04317 void initializetrisubpools(m, b)
04318 struct mesh *m;
04319 struct behavior *b;
04320 #endif
04321
04322 {
04323 int trisize;
04324
04325
04326
04327
04328
04329 m->highorderindex = 6 + (b->usesegments * 3);
04330
04331 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
04332 sizeof(triangle);
04333
04334
04335 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
04336
04337
04338
04339 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
04340
04341
04342 if (b->vararea) {
04343 trisize = (m->areaboundindex + 1) * sizeof(REAL);
04344 } else if (m->eextras + b->regionattrib > 0) {
04345 trisize = m->areaboundindex * sizeof(REAL);
04346 }
04347
04348
04349
04350
04351 if ((b->voronoi || b->neighbors) &&
04352 (trisize < 6 * sizeof(triangle) + sizeof(int))) {
04353 trisize = 6 * sizeof(triangle) + sizeof(int);
04354 }
04355
04356
04357 poolinit(&m->triangles, trisize, TRIPERBLOCK,
04358 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
04359 TRIPERBLOCK, 4);
04360
04361 if (b->usesegments) {
04362
04363
04364 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
04365 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
04366
04367
04368 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
04369 } else {
04370
04371 dummyinit(m, b, m->triangles.itembytes, 0);
04372 }
04373 }
04374
04375
04376
04377
04378
04379
04380
04381 #ifdef ANSI_DECLARATORS
04382 void triangledealloc(struct mesh *m, triangle *dyingtriangle)
04383 #else
04384 void triangledealloc(m, dyingtriangle)
04385 struct mesh *m;
04386 triangle *dyingtriangle;
04387 #endif
04388
04389 {
04390
04391
04392 killtri(dyingtriangle);
04393 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
04394 }
04395
04396
04397
04398
04399
04400
04401
04402 #ifdef ANSI_DECLARATORS
04403 triangle *triangletraverse(struct mesh *m)
04404 #else
04405 triangle *triangletraverse(m)
04406 struct mesh *m;
04407 #endif
04408
04409 {
04410 triangle *newtriangle;
04411
04412 do {
04413 newtriangle = (triangle *) traverse(&m->triangles);
04414 if (newtriangle == (triangle *) NULL) {
04415 return (triangle *) NULL;
04416 }
04417 } while (deadtri(newtriangle));
04418 return newtriangle;
04419 }
04420
04421
04422
04423
04424
04425
04426
04427 #ifdef ANSI_DECLARATORS
04428 void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
04429 #else
04430 void subsegdealloc(m, dyingsubseg)
04431 struct mesh *m;
04432 subseg *dyingsubseg;
04433 #endif
04434
04435 {
04436
04437
04438 killsubseg(dyingsubseg);
04439 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
04440 }
04441
04442
04443
04444
04445
04446
04447
04448 #ifdef ANSI_DECLARATORS
04449 subseg *subsegtraverse(struct mesh *m)
04450 #else
04451 subseg *subsegtraverse(m)
04452 struct mesh *m;
04453 #endif
04454
04455 {
04456 subseg *newsubseg;
04457
04458 do {
04459 newsubseg = (subseg *) traverse(&m->subsegs);
04460 if (newsubseg == (subseg *) NULL) {
04461 return (subseg *) NULL;
04462 }
04463 } while (deadsubseg(newsubseg));
04464 return newsubseg;
04465 }
04466
04467
04468
04469
04470
04471
04472
04473 #ifdef ANSI_DECLARATORS
04474 void vertexdealloc(struct mesh *m, vertex dyingvertex)
04475 #else
04476 void vertexdealloc(m, dyingvertex)
04477 struct mesh *m;
04478 vertex dyingvertex;
04479 #endif
04480
04481 {
04482
04483
04484 setvertextype(dyingvertex, DEADVERTEX);
04485 pooldealloc(&m->vertices, (VOID *) dyingvertex);
04486 }
04487
04488
04489
04490
04491
04492
04493
04494 #ifdef ANSI_DECLARATORS
04495 vertex vertextraverse(struct mesh *m)
04496 #else
04497 vertex vertextraverse(m)
04498 struct mesh *m;
04499 #endif
04500
04501 {
04502 vertex newvertex;
04503
04504 do {
04505 newvertex = (vertex) traverse(&m->vertices);
04506 if (newvertex == (vertex) NULL) {
04507 return (vertex) NULL;
04508 }
04509 } while (vertextype(newvertex) == DEADVERTEX);
04510 return newvertex;
04511 }
04512
04513
04514
04515
04516
04517
04518
04519
04520 #ifndef CDT_ONLY
04521
04522 #ifdef ANSI_DECLARATORS
04523 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
04524 #else
04525 void badsubsegdealloc(m, dyingseg)
04526 struct mesh *m;
04527 struct badsubseg *dyingseg;
04528 #endif
04529
04530 {
04531
04532
04533 dyingseg->subsegorg = (vertex) NULL;
04534 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
04535 }
04536
04537 #endif
04538
04539
04540
04541
04542
04543
04544
04545 #ifndef CDT_ONLY
04546
04547 #ifdef ANSI_DECLARATORS
04548 struct badsubseg *badsubsegtraverse(struct mesh *m)
04549 #else
04550 struct badsubseg *badsubsegtraverse(m)
04551 struct mesh *m;
04552 #endif
04553
04554 {
04555 struct badsubseg *newseg;
04556
04557 do {
04558 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
04559 if (newseg == (struct badsubseg *) NULL) {
04560 return (struct badsubseg *) NULL;
04561 }
04562 } while (newseg->subsegorg == (vertex) NULL);
04563 return newseg;
04564 }
04565
04566 #endif
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576
04577
04578
04579
04580 #ifdef ANSI_DECLARATORS
04581 vertex getvertex(struct mesh *m, struct behavior *b, int number)
04582 #else
04583 vertex getvertex(m, b, number)
04584 struct mesh *m;
04585 struct behavior *b;
04586 int number;
04587 #endif
04588
04589 {
04590 VOID **getblock;
04591 char *foundvertex;
04592 unsigned long alignptr;
04593 int current;
04594
04595 getblock = m->vertices.firstblock;
04596 current = b->firstnumber;
04597
04598
04599 if (current + m->vertices.itemsfirstblock <= number) {
04600 getblock = (VOID **) *getblock;
04601 current += m->vertices.itemsfirstblock;
04602 while (current + m->vertices.itemsperblock <= number) {
04603 getblock = (VOID **) *getblock;
04604 current += m->vertices.itemsperblock;
04605 }
04606 }
04607
04608
04609 alignptr = (unsigned long) (getblock + 1);
04610 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
04611 (alignptr % (unsigned long) m->vertices.alignbytes));
04612 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
04613 }
04614
04615
04616
04617
04618
04619
04620
04621 #ifdef ANSI_DECLARATORS
04622 void triangledeinit(struct mesh *m, struct behavior *b)
04623 #else
04624 void triangledeinit(m, b)
04625 struct mesh *m;
04626 struct behavior *b;
04627 #endif
04628
04629 {
04630 pooldeinit(&m->triangles);
04631 trifree((VOID *) m->dummytribase);
04632 if (b->usesegments) {
04633 pooldeinit(&m->subsegs);
04634 trifree((VOID *) m->dummysubbase);
04635 }
04636 pooldeinit(&m->vertices);
04637 #ifndef CDT_ONLY
04638 if (b->quality) {
04639 pooldeinit(&m->badsubsegs);
04640 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
04641 pooldeinit(&m->badtriangles);
04642 pooldeinit(&m->flipstackers);
04643 }
04644 }
04645 #endif
04646 }
04647
04650
04651
04652
04656
04657
04658
04659
04660
04661
04662 #ifdef ANSI_DECLARATORS
04663 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
04664 #else
04665 void maketriangle(m, b, newotri)
04666 struct mesh *m;
04667 struct behavior *b;
04668 struct otri *newotri;
04669 #endif
04670
04671 {
04672 int i;
04673
04674 newotri->tri = (triangle *) poolalloc(&m->triangles);
04675
04676 newotri->tri[0] = (triangle) m->dummytri;
04677 newotri->tri[1] = (triangle) m->dummytri;
04678 newotri->tri[2] = (triangle) m->dummytri;
04679
04680 newotri->tri[3] = (triangle) NULL;
04681 newotri->tri[4] = (triangle) NULL;
04682 newotri->tri[5] = (triangle) NULL;
04683 if (b->usesegments) {
04684
04685
04686 newotri->tri[6] = (triangle) m->dummysub;
04687 newotri->tri[7] = (triangle) m->dummysub;
04688 newotri->tri[8] = (triangle) m->dummysub;
04689 }
04690 for (i = 0; i < m->eextras; i++) {
04691 setelemattribute(*newotri, i, 0.0);
04692 }
04693 if (b->vararea) {
04694 setareabound(*newotri, -1.0);
04695 }
04696
04697 newotri->orient = 0;
04698 }
04699
04700
04701
04702
04703
04704
04705
04706 #ifdef ANSI_DECLARATORS
04707 void makesubseg(struct mesh *m, struct osub *newsubseg)
04708 #else
04709 void makesubseg(m, newsubseg)
04710 struct mesh *m;
04711 struct osub *newsubseg;
04712 #endif
04713
04714 {
04715 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
04716
04717
04718 newsubseg->ss[0] = (subseg) m->dummysub;
04719 newsubseg->ss[1] = (subseg) m->dummysub;
04720
04721 newsubseg->ss[2] = (subseg) NULL;
04722 newsubseg->ss[3] = (subseg) NULL;
04723 newsubseg->ss[4] = (subseg) NULL;
04724 newsubseg->ss[5] = (subseg) NULL;
04725
04726 newsubseg->ss[6] = (subseg) m->dummytri;
04727 newsubseg->ss[7] = (subseg) m->dummytri;
04728
04729 setmark(*newsubseg, 0);
04730
04731 newsubseg->ssorient = 0;
04732 }
04733
04736
04737
04738
04742
04743
04744
04745
04746
04747
04748
04749
04750
04751
04752
04753
04754
04755 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771 #define Fast_Two_Sum_Tail(a, b, x, y) \
04772 bvirt = x - a; \
04773 y = b - bvirt
04774
04775 #define Fast_Two_Sum(a, b, x, y) \
04776 x = (REAL) (a + b); \
04777 Fast_Two_Sum_Tail(a, b, x, y)
04778
04779 #define Two_Sum_Tail(a, b, x, y) \
04780 bvirt = (REAL) (x - a); \
04781 avirt = x - bvirt; \
04782 bround = b - bvirt; \
04783 around = a - avirt; \
04784 y = around + bround
04785
04786 #define Two_Sum(a, b, x, y) \
04787 x = (REAL) (a + b); \
04788 Two_Sum_Tail(a, b, x, y)
04789
04790 #define Two_Diff_Tail(a, b, x, y) \
04791 bvirt = (REAL) (a - x); \
04792 avirt = x + bvirt; \
04793 bround = bvirt - b; \
04794 around = a - avirt; \
04795 y = around + bround
04796
04797 #define Two_Diff(a, b, x, y) \
04798 x = (REAL) (a - b); \
04799 Two_Diff_Tail(a, b, x, y)
04800
04801 #define Split(a, ahi, alo) \
04802 c = (REAL) (splitter * a); \
04803 abig = (REAL) (c - a); \
04804 ahi = c - abig; \
04805 alo = a - ahi
04806
04807 #define Two_Product_Tail(a, b, x, y) \
04808 Split(a, ahi, alo); \
04809 Split(b, bhi, blo); \
04810 err1 = x - (ahi * bhi); \
04811 err2 = err1 - (alo * bhi); \
04812 err3 = err2 - (ahi * blo); \
04813 y = (alo * blo) - err3
04814
04815 #define Two_Product(a, b, x, y) \
04816 x = (REAL) (a * b); \
04817 Two_Product_Tail(a, b, x, y)
04818
04819
04820
04821
04822 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
04823 x = (REAL) (a * b); \
04824 Split(a, ahi, alo); \
04825 err1 = x - (ahi * bhi); \
04826 err2 = err1 - (alo * bhi); \
04827 err3 = err2 - (ahi * blo); \
04828 y = (alo * blo) - err3
04829
04830
04831
04832 #define Square_Tail(a, x, y) \
04833 Split(a, ahi, alo); \
04834 err1 = x - (ahi * ahi); \
04835 err3 = err1 - ((ahi + ahi) * alo); \
04836 y = (alo * alo) - err3
04837
04838 #define Square(a, x, y) \
04839 x = (REAL) (a * a); \
04840 Square_Tail(a, x, y)
04841
04842
04843
04844
04845 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
04846 Two_Sum(a0, b , _i, x0); \
04847 Two_Sum(a1, _i, x2, x1)
04848
04849 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
04850 Two_Diff(a0, b , _i, x0); \
04851 Two_Sum( a1, _i, x2, x1)
04852
04853 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
04854 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
04855 Two_One_Sum(_j, _0, b1, x3, x2, x1)
04856
04857 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
04858 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
04859 Two_One_Diff(_j, _0, b1, x3, x2, x1)
04860
04861
04862
04863 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
04864 Split(b, bhi, blo); \
04865 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
04866 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
04867 Two_Sum(_i, _0, _k, x1); \
04868 Fast_Two_Sum(_j, _k, x3, x2)
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889 void exactinit()
04890 {
04891 REAL half;
04892 REAL check, lastcheck;
04893 int every_other;
04894 #ifdef LINUX
04895 int cword;
04896 #endif
04897
04898 #ifdef CPU86
04899 #ifdef SINGLE
04900 _control87(_PC_24, _MCW_PC);
04901 #else
04902 _control87(_PC_53, _MCW_PC);
04903 #endif
04904 #endif
04905 #ifdef LINUX
04906 #ifdef SINGLE
04907
04908 cword = 4210;
04909 #else
04910
04911 cword = 4722;
04912 #endif
04913 _FPU_SETCW(cword);
04914 #endif
04915
04916 every_other = 1;
04917 half = 0.5;
04918 epsilon = 1.0;
04919 splitter = 1.0;
04920 check = 1.0;
04921
04922
04923
04924
04925 do {
04926 lastcheck = check;
04927 epsilon *= half;
04928 if (every_other) {
04929 splitter *= 2.0;
04930 }
04931 every_other = !every_other;
04932 check = 1.0 + epsilon;
04933 } while ((check != 1.0) && (check != lastcheck));
04934 splitter += 1.0;
04935
04936 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
04937 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
04938 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
04939 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
04940 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
04941 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
04942 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
04943 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
04944 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
04945 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
04946 }
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962 #ifdef ANSI_DECLARATORS
04963 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
04964 #else
04965 int fast_expansion_sum_zeroelim(elen, e, flen, f, h)
04966 int elen;
04967 REAL *e;
04968 int flen;
04969 REAL *f;
04970 REAL *h;
04971 #endif
04972
04973 {
04974 REAL Q;
04975 INEXACT REAL Qnew;
04976 INEXACT REAL hh;
04977 INEXACT REAL bvirt;
04978 REAL avirt, bround, around;
04979 int eindex, findex, hindex;
04980 REAL enow, fnow;
04981
04982 enow = e[0];
04983 fnow = f[0];
04984 eindex = findex = 0;
04985 if ((fnow > enow) == (fnow > -enow)) {
04986 Q = enow;
04987 enow = e[++eindex];
04988 } else {
04989 Q = fnow;
04990 fnow = f[++findex];
04991 }
04992 hindex = 0;
04993 if ((eindex < elen) && (findex < flen)) {
04994 if ((fnow > enow) == (fnow > -enow)) {
04995 Fast_Two_Sum(enow, Q, Qnew, hh);
04996 enow = e[++eindex];
04997 } else {
04998 Fast_Two_Sum(fnow, Q, Qnew, hh);
04999 fnow = f[++findex];
05000 }
05001 Q = Qnew;
05002 if (hh != 0.0) {
05003 h[hindex++] = hh;
05004 }
05005 while ((eindex < elen) && (findex < flen)) {
05006 if ((fnow > enow) == (fnow > -enow)) {
05007 Two_Sum(Q, enow, Qnew, hh);
05008 enow = e[++eindex];
05009 } else {
05010 Two_Sum(Q, fnow, Qnew, hh);
05011 fnow = f[++findex];
05012 }
05013 Q = Qnew;
05014 if (hh != 0.0) {
05015 h[hindex++] = hh;
05016 }
05017 }
05018 }
05019 while (eindex < elen) {
05020 Two_Sum(Q, enow, Qnew, hh);
05021 enow = e[++eindex];
05022 Q = Qnew;
05023 if (hh != 0.0) {
05024 h[hindex++] = hh;
05025 }
05026 }
05027 while (findex < flen) {
05028 Two_Sum(Q, fnow, Qnew, hh);
05029 fnow = f[++findex];
05030 Q = Qnew;
05031 if (hh != 0.0) {
05032 h[hindex++] = hh;
05033 }
05034 }
05035 if ((Q != 0.0) || (hindex == 0)) {
05036 h[hindex++] = Q;
05037 }
05038 return hindex;
05039 }
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056 #ifdef ANSI_DECLARATORS
05057 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
05058 #else
05059 int scale_expansion_zeroelim(elen, e, b, h)
05060 int elen;
05061 REAL *e;
05062 REAL b;
05063 REAL *h;
05064 #endif
05065
05066 {
05067 INEXACT REAL Q, sum;
05068 REAL hh;
05069 INEXACT REAL product1;
05070 REAL product0;
05071 int eindex, hindex;
05072 REAL enow;
05073 INEXACT REAL bvirt;
05074 REAL avirt, bround, around;
05075 INEXACT REAL c;
05076 INEXACT REAL abig;
05077 REAL ahi, alo, bhi, blo;
05078 REAL err1, err2, err3;
05079
05080 Split(b, bhi, blo);
05081 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
05082 hindex = 0;
05083 if (hh != 0) {
05084 h[hindex++] = hh;
05085 }
05086 for (eindex = 1; eindex < elen; eindex++) {
05087 enow = e[eindex];
05088 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
05089 Two_Sum(Q, product0, sum, hh);
05090 if (hh != 0) {
05091 h[hindex++] = hh;
05092 }
05093 Fast_Two_Sum(product1, sum, Q, hh);
05094 if (hh != 0) {
05095 h[hindex++] = hh;
05096 }
05097 }
05098 if ((Q != 0.0) || (hindex == 0)) {
05099 h[hindex++] = Q;
05100 }
05101 return hindex;
05102 }
05103
05104
05105
05106
05107
05108
05109
05110
05111
05112 #ifdef ANSI_DECLARATORS
05113 REAL estimate(int elen, REAL *e)
05114 #else
05115 REAL estimate(elen, e)
05116 int elen;
05117 REAL *e;
05118 #endif
05119
05120 {
05121 REAL Q;
05122 int eindex;
05123
05124 Q = e[0];
05125 for (eindex = 1; eindex < elen; eindex++) {
05126 Q += e[eindex];
05127 }
05128 return Q;
05129 }
05130
05131
05132
05133
05134
05135
05136
05137
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151 #ifdef ANSI_DECLARATORS
05152 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
05153 #else
05154 REAL counterclockwiseadapt(pa, pb, pc, detsum)
05155 vertex pa;
05156 vertex pb;
05157 vertex pc;
05158 REAL detsum;
05159 #endif
05160
05161 {
05162 INEXACT REAL acx, acy, bcx, bcy;
05163 REAL acxtail, acytail, bcxtail, bcytail;
05164 INEXACT REAL detleft, detright;
05165 REAL detlefttail, detrighttail;
05166 REAL det, errbound;
05167 REAL B[4], C1[8], C2[12], D[16];
05168 INEXACT REAL B3;
05169 int C1length, C2length, Dlength;
05170 REAL u[4];
05171 INEXACT REAL u3;
05172 INEXACT REAL s1, t1;
05173 REAL s0, t0;
05174
05175 INEXACT REAL bvirt;
05176 REAL avirt, bround, around;
05177 INEXACT REAL c;
05178 INEXACT REAL abig;
05179 REAL ahi, alo, bhi, blo;
05180 REAL err1, err2, err3;
05181 INEXACT REAL _i, _j;
05182 REAL _0;
05183
05184 acx = (REAL) (pa[0] - pc[0]);
05185 bcx = (REAL) (pb[0] - pc[0]);
05186 acy = (REAL) (pa[1] - pc[1]);
05187 bcy = (REAL) (pb[1] - pc[1]);
05188
05189 Two_Product(acx, bcy, detleft, detlefttail);
05190 Two_Product(acy, bcx, detright, detrighttail);
05191
05192 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
05193 B3, B[2], B[1], B[0]);
05194 B[3] = B3;
05195
05196 det = estimate(4, B);
05197 errbound = ccwerrboundB * detsum;
05198 if ((det >= errbound) || (-det >= errbound)) {
05199 return det;
05200 }
05201
05202 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
05203 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
05204 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
05205 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
05206
05207 if ((acxtail == 0.0) && (acytail == 0.0)
05208 && (bcxtail == 0.0) && (bcytail == 0.0)) {
05209 return det;
05210 }
05211
05212 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
05213 det += (acx * bcytail + bcy * acxtail)
05214 - (acy * bcxtail + bcx * acytail);
05215 if ((det >= errbound) || (-det >= errbound)) {
05216 return det;
05217 }
05218
05219 Two_Product(acxtail, bcy, s1, s0);
05220 Two_Product(acytail, bcx, t1, t0);
05221 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05222 u[3] = u3;
05223 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
05224
05225 Two_Product(acx, bcytail, s1, s0);
05226 Two_Product(acy, bcxtail, t1, t0);
05227 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05228 u[3] = u3;
05229 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
05230
05231 Two_Product(acxtail, bcytail, s1, s0);
05232 Two_Product(acytail, bcxtail, t1, t0);
05233 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05234 u[3] = u3;
05235 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
05236
05237 return(D[Dlength - 1]);
05238 }
05239
05240 #ifdef ANSI_DECLARATORS
05241 REAL counterclockwise(struct mesh *m, struct behavior *b,
05242 vertex pa, vertex pb, vertex pc)
05243 #else
05244 REAL counterclockwise(m, b, pa, pb, pc)
05245 struct mesh *m;
05246 struct behavior *b;
05247 vertex pa;
05248 vertex pb;
05249 vertex pc;
05250 #endif
05251
05252 {
05253 REAL detleft, detright, det;
05254 REAL detsum, errbound;
05255
05256 m->counterclockcount++;
05257
05258 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
05259 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
05260 det = detleft - detright;
05261
05262 if (b->noexact) {
05263 return det;
05264 }
05265
05266 if (detleft > 0.0) {
05267 if (detright <= 0.0) {
05268 return det;
05269 } else {
05270 detsum = detleft + detright;
05271 }
05272 } else if (detleft < 0.0) {
05273 if (detright >= 0.0) {
05274 return det;
05275 } else {
05276 detsum = -detleft - detright;
05277 }
05278 } else {
05279 return det;
05280 }
05281
05282 errbound = ccwerrboundA * detsum;
05283 if ((det >= errbound) || (-det >= errbound)) {
05284 return det;
05285 }
05286
05287 return counterclockwiseadapt(pa, pb, pc, detsum);
05288 }
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309 #ifdef ANSI_DECLARATORS
05310 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
05311 #else
05312 REAL incircleadapt(pa, pb, pc, pd, permanent)
05313 vertex pa;
05314 vertex pb;
05315 vertex pc;
05316 vertex pd;
05317 REAL permanent;
05318 #endif
05319
05320 {
05321 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
05322 REAL det, errbound;
05323
05324 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05325 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05326 REAL bc[4], ca[4], ab[4];
05327 INEXACT REAL bc3, ca3, ab3;
05328 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
05329 int axbclen, axxbclen, aybclen, ayybclen, alen;
05330 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
05331 int bxcalen, bxxcalen, bycalen, byycalen, blen;
05332 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
05333 int cxablen, cxxablen, cyablen, cyyablen, clen;
05334 REAL abdet[64];
05335 int ablen;
05336 REAL fin1[1152], fin2[1152];
05337 REAL *finnow, *finother, *finswap;
05338 int finlength;
05339
05340 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
05341 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
05342 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
05343 REAL aa[4], bb[4], cc[4];
05344 INEXACT REAL aa3, bb3, cc3;
05345 INEXACT REAL ti1, tj1;
05346 REAL ti0, tj0;
05347 REAL u[4], v[4];
05348 INEXACT REAL u3, v3;
05349 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
05350 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
05351 int temp8len, temp16alen, temp16blen, temp16clen;
05352 int temp32alen, temp32blen, temp48len, temp64len;
05353 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
05354 int axtbblen, axtcclen, aytbblen, aytcclen;
05355 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
05356 int bxtaalen, bxtcclen, bytaalen, bytcclen;
05357 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
05358 int cxtaalen, cxtbblen, cytaalen, cytbblen;
05359 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
05360 int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
05361 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
05362 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
05363 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
05364 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
05365 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
05366 REAL abt[8], bct[8], cat[8];
05367 int abtlen, bctlen, catlen;
05368 REAL abtt[4], bctt[4], catt[4];
05369 int abttlen, bcttlen, cattlen;
05370 INEXACT REAL abtt3, bctt3, catt3;
05371 REAL negate;
05372
05373 INEXACT REAL bvirt;
05374 REAL avirt, bround, around;
05375 INEXACT REAL c;
05376 INEXACT REAL abig;
05377 REAL ahi, alo, bhi, blo;
05378 REAL err1, err2, err3;
05379 INEXACT REAL _i, _j;
05380 REAL _0;
05381
05382 adx = (REAL) (pa[0] - pd[0]);
05383 bdx = (REAL) (pb[0] - pd[0]);
05384 cdx = (REAL) (pc[0] - pd[0]);
05385 ady = (REAL) (pa[1] - pd[1]);
05386 bdy = (REAL) (pb[1] - pd[1]);
05387 cdy = (REAL) (pc[1] - pd[1]);
05388
05389 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
05390 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
05391 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
05392 bc[3] = bc3;
05393 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
05394 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
05395 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
05396 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
05397 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
05398
05399 Two_Product(cdx, ady, cdxady1, cdxady0);
05400 Two_Product(adx, cdy, adxcdy1, adxcdy0);
05401 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
05402 ca[3] = ca3;
05403 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
05404 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
05405 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
05406 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
05407 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
05408
05409 Two_Product(adx, bdy, adxbdy1, adxbdy0);
05410 Two_Product(bdx, ady, bdxady1, bdxady0);
05411 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
05412 ab[3] = ab3;
05413 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
05414 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
05415 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
05416 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
05417 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
05418
05419 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
05420 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
05421
05422 det = estimate(finlength, fin1);
05423 errbound = iccerrboundB * permanent;
05424 if ((det >= errbound) || (-det >= errbound)) {
05425 return det;
05426 }
05427
05428 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
05429 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
05430 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
05431 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
05432 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
05433 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
05434 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
05435 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
05436 return det;
05437 }
05438
05439 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
05440 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
05441 - (bdy * cdxtail + cdx * bdytail))
05442 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
05443 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
05444 - (cdy * adxtail + adx * cdytail))
05445 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
05446 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
05447 - (ady * bdxtail + bdx * adytail))
05448 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
05449 if ((det >= errbound) || (-det >= errbound)) {
05450 return det;
05451 }
05452
05453 finnow = fin1;
05454 finother = fin2;
05455
05456 if ((bdxtail != 0.0) || (bdytail != 0.0)
05457 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05458 Square(adx, adxadx1, adxadx0);
05459 Square(ady, adyady1, adyady0);
05460 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
05461 aa[3] = aa3;
05462 }
05463 if ((cdxtail != 0.0) || (cdytail != 0.0)
05464 || (adxtail != 0.0) || (adytail != 0.0)) {
05465 Square(bdx, bdxbdx1, bdxbdx0);
05466 Square(bdy, bdybdy1, bdybdy0);
05467 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
05468 bb[3] = bb3;
05469 }
05470 if ((adxtail != 0.0) || (adytail != 0.0)
05471 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05472 Square(cdx, cdxcdx1, cdxcdx0);
05473 Square(cdy, cdycdy1, cdycdy0);
05474 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
05475 cc[3] = cc3;
05476 }
05477
05478 if (adxtail != 0.0) {
05479 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
05480 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
05481 temp16a);
05482
05483 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
05484 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
05485
05486 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
05487 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
05488
05489 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05490 temp16blen, temp16b, temp32a);
05491 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05492 temp32alen, temp32a, temp48);
05493 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05494 temp48, finother);
05495 finswap = finnow; finnow = finother; finother = finswap;
05496 }
05497 if (adytail != 0.0) {
05498 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
05499 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
05500 temp16a);
05501
05502 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
05503 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
05504
05505 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
05506 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
05507
05508 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05509 temp16blen, temp16b, temp32a);
05510 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05511 temp32alen, temp32a, temp48);
05512 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05513 temp48, finother);
05514 finswap = finnow; finnow = finother; finother = finswap;
05515 }
05516 if (bdxtail != 0.0) {
05517 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
05518 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
05519 temp16a);
05520
05521 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
05522 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
05523
05524 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
05525 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
05526
05527 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05528 temp16blen, temp16b, temp32a);
05529 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05530 temp32alen, temp32a, temp48);
05531 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05532 temp48, finother);
05533 finswap = finnow; finnow = finother; finother = finswap;
05534 }
05535 if (bdytail != 0.0) {
05536 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
05537 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
05538 temp16a);
05539
05540 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
05541 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
05542
05543 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
05544 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
05545
05546 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05547 temp16blen, temp16b, temp32a);
05548 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05549 temp32alen, temp32a, temp48);
05550 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05551 temp48, finother);
05552 finswap = finnow; finnow = finother; finother = finswap;
05553 }
05554 if (cdxtail != 0.0) {
05555 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
05556 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
05557 temp16a);
05558
05559 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
05560 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
05561
05562 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
05563 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
05564
05565 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05566 temp16blen, temp16b, temp32a);
05567 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05568 temp32alen, temp32a, temp48);
05569 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05570 temp48, finother);
05571 finswap = finnow; finnow = finother; finother = finswap;
05572 }
05573 if (cdytail != 0.0) {
05574 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
05575 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
05576 temp16a);
05577
05578 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
05579 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
05580
05581 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
05582 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
05583
05584 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05585 temp16blen, temp16b, temp32a);
05586 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05587 temp32alen, temp32a, temp48);
05588 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05589 temp48, finother);
05590 finswap = finnow; finnow = finother; finother = finswap;
05591 }
05592
05593 if ((adxtail != 0.0) || (adytail != 0.0)) {
05594 if ((bdxtail != 0.0) || (bdytail != 0.0)
05595 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05596 Two_Product(bdxtail, cdy, ti1, ti0);
05597 Two_Product(bdx, cdytail, tj1, tj0);
05598 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05599 u[3] = u3;
05600 negate = -bdy;
05601 Two_Product(cdxtail, negate, ti1, ti0);
05602 negate = -bdytail;
05603 Two_Product(cdx, negate, tj1, tj0);
05604 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05605 v[3] = v3;
05606 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
05607
05608 Two_Product(bdxtail, cdytail, ti1, ti0);
05609 Two_Product(cdxtail, bdytail, tj1, tj0);
05610 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
05611 bctt[3] = bctt3;
05612 bcttlen = 4;
05613 } else {
05614 bct[0] = 0.0;
05615 bctlen = 1;
05616 bctt[0] = 0.0;
05617 bcttlen = 1;
05618 }
05619
05620 if (adxtail != 0.0) {
05621 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
05622 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
05623 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
05624 temp32a);
05625 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05626 temp32alen, temp32a, temp48);
05627 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05628 temp48, finother);
05629 finswap = finnow; finnow = finother; finother = finswap;
05630 if (bdytail != 0.0) {
05631 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
05632 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05633 temp16a);
05634 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05635 temp16a, finother);
05636 finswap = finnow; finnow = finother; finother = finswap;
05637 }
05638 if (cdytail != 0.0) {
05639 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
05640 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05641 temp16a);
05642 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05643 temp16a, finother);
05644 finswap = finnow; finnow = finother; finother = finswap;
05645 }
05646
05647 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
05648 temp32a);
05649 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
05650 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
05651 temp16a);
05652 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
05653 temp16b);
05654 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05655 temp16blen, temp16b, temp32b);
05656 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05657 temp32blen, temp32b, temp64);
05658 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05659 temp64, finother);
05660 finswap = finnow; finnow = finother; finother = finswap;
05661 }
05662 if (adytail != 0.0) {
05663 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
05664 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
05665 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
05666 temp32a);
05667 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05668 temp32alen, temp32a, temp48);
05669 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05670 temp48, finother);
05671 finswap = finnow; finnow = finother; finother = finswap;
05672
05673
05674 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
05675 temp32a);
05676 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
05677 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
05678 temp16a);
05679 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
05680 temp16b);
05681 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05682 temp16blen, temp16b, temp32b);
05683 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05684 temp32blen, temp32b, temp64);
05685 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05686 temp64, finother);
05687 finswap = finnow; finnow = finother; finother = finswap;
05688 }
05689 }
05690 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
05691 if ((cdxtail != 0.0) || (cdytail != 0.0)
05692 || (adxtail != 0.0) || (adytail != 0.0)) {
05693 Two_Product(cdxtail, ady, ti1, ti0);
05694 Two_Product(cdx, adytail, tj1, tj0);
05695 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05696 u[3] = u3;
05697 negate = -cdy;
05698 Two_Product(adxtail, negate, ti1, ti0);
05699 negate = -cdytail;
05700 Two_Product(adx, negate, tj1, tj0);
05701 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05702 v[3] = v3;
05703 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
05704
05705 Two_Product(cdxtail, adytail, ti1, ti0);
05706 Two_Product(adxtail, cdytail, tj1, tj0);
05707 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
05708 catt[3] = catt3;
05709 cattlen = 4;
05710 } else {
05711 cat[0] = 0.0;
05712 catlen = 1;
05713 catt[0] = 0.0;
05714 cattlen = 1;
05715 }
05716
05717 if (bdxtail != 0.0) {
05718 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
05719 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
05720 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
05721 temp32a);
05722 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05723 temp32alen, temp32a, temp48);
05724 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05725 temp48, finother);
05726 finswap = finnow; finnow = finother; finother = finswap;
05727 if (cdytail != 0.0) {
05728 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
05729 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05730 temp16a);
05731 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05732 temp16a, finother);
05733 finswap = finnow; finnow = finother; finother = finswap;
05734 }
05735 if (adytail != 0.0) {
05736 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
05737 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05738 temp16a);
05739 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05740 temp16a, finother);
05741 finswap = finnow; finnow = finother; finother = finswap;
05742 }
05743
05744 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
05745 temp32a);
05746 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
05747 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
05748 temp16a);
05749 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
05750 temp16b);
05751 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05752 temp16blen, temp16b, temp32b);
05753 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05754 temp32blen, temp32b, temp64);
05755 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05756 temp64, finother);
05757 finswap = finnow; finnow = finother; finother = finswap;
05758 }
05759 if (bdytail != 0.0) {
05760 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
05761 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
05762 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
05763 temp32a);
05764 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05765 temp32alen, temp32a, temp48);
05766 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05767 temp48, finother);
05768 finswap = finnow; finnow = finother; finother = finswap;
05769
05770
05771 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
05772 temp32a);
05773 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
05774 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
05775 temp16a);
05776 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
05777 temp16b);
05778 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05779 temp16blen, temp16b, temp32b);
05780 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05781 temp32blen, temp32b, temp64);
05782 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05783 temp64, finother);
05784 finswap = finnow; finnow = finother; finother = finswap;
05785 }
05786 }
05787 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
05788 if ((adxtail != 0.0) || (adytail != 0.0)
05789 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05790 Two_Product(adxtail, bdy, ti1, ti0);
05791 Two_Product(adx, bdytail, tj1, tj0);
05792 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05793 u[3] = u3;
05794 negate = -ady;
05795 Two_Product(bdxtail, negate, ti1, ti0);
05796 negate = -adytail;
05797 Two_Product(bdx, negate, tj1, tj0);
05798 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05799 v[3] = v3;
05800 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
05801
05802 Two_Product(adxtail, bdytail, ti1, ti0);
05803 Two_Product(bdxtail, adytail, tj1, tj0);
05804 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
05805 abtt[3] = abtt3;
05806 abttlen = 4;
05807 } else {
05808 abt[0] = 0.0;
05809 abtlen = 1;
05810 abtt[0] = 0.0;
05811 abttlen = 1;
05812 }
05813
05814 if (cdxtail != 0.0) {
05815 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
05816 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
05817 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
05818 temp32a);
05819 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05820 temp32alen, temp32a, temp48);
05821 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05822 temp48, finother);
05823 finswap = finnow; finnow = finother; finother = finswap;
05824 if (adytail != 0.0) {
05825 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
05826 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05827 temp16a);
05828 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05829 temp16a, finother);
05830 finswap = finnow; finnow = finother; finother = finswap;
05831 }
05832 if (bdytail != 0.0) {
05833 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
05834 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05835 temp16a);
05836 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05837 temp16a, finother);
05838 finswap = finnow; finnow = finother; finother = finswap;
05839 }
05840
05841 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
05842 temp32a);
05843 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
05844 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
05845 temp16a);
05846 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
05847 temp16b);
05848 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05849 temp16blen, temp16b, temp32b);
05850 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05851 temp32blen, temp32b, temp64);
05852 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05853 temp64, finother);
05854 finswap = finnow; finnow = finother; finother = finswap;
05855 }
05856 if (cdytail != 0.0) {
05857 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
05858 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
05859 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
05860 temp32a);
05861 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05862 temp32alen, temp32a, temp48);
05863 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05864 temp48, finother);
05865 finswap = finnow; finnow = finother; finother = finswap;
05866
05867
05868 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
05869 temp32a);
05870 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
05871 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
05872 temp16a);
05873 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
05874 temp16b);
05875 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05876 temp16blen, temp16b, temp32b);
05877 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05878 temp32blen, temp32b, temp64);
05879 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05880 temp64, finother);
05881 finswap = finnow; finnow = finother; finother = finswap;
05882 }
05883 }
05884
05885 return finnow[finlength - 1];
05886 }
05887
05888 #ifdef ANSI_DECLARATORS
05889 REAL incircle(struct mesh *m, struct behavior *b,
05890 vertex pa, vertex pb, vertex pc, vertex pd)
05891 #else
05892 REAL incircle(m, b, pa, pb, pc, pd)
05893 struct mesh *m;
05894 struct behavior *b;
05895 vertex pa;
05896 vertex pb;
05897 vertex pc;
05898 vertex pd;
05899 #endif
05900
05901 {
05902 REAL adx, bdx, cdx, ady, bdy, cdy;
05903 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
05904 REAL alift, blift, clift;
05905 REAL det;
05906 REAL permanent, errbound;
05907
05908 m->incirclecount++;
05909
05910 adx = pa[0] - pd[0];
05911 bdx = pb[0] - pd[0];
05912 cdx = pc[0] - pd[0];
05913 ady = pa[1] - pd[1];
05914 bdy = pb[1] - pd[1];
05915 cdy = pc[1] - pd[1];
05916
05917 bdxcdy = bdx * cdy;
05918 cdxbdy = cdx * bdy;
05919 alift = adx * adx + ady * ady;
05920
05921 cdxady = cdx * ady;
05922 adxcdy = adx * cdy;
05923 blift = bdx * bdx + bdy * bdy;
05924
05925 adxbdy = adx * bdy;
05926 bdxady = bdx * ady;
05927 clift = cdx * cdx + cdy * cdy;
05928
05929 det = alift * (bdxcdy - cdxbdy)
05930 + blift * (cdxady - adxcdy)
05931 + clift * (adxbdy - bdxady);
05932
05933 if (b->noexact) {
05934 return det;
05935 }
05936
05937 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
05938 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
05939 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
05940 errbound = iccerrboundA * permanent;
05941 if ((det > errbound) || (-det > errbound)) {
05942 return det;
05943 }
05944
05945 return incircleadapt(pa, pb, pc, pd, permanent);
05946 }
05947
05948
05949
05950
05951
05952
05953
05954
05955
05956
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970 #ifdef ANSI_DECLARATORS
05971 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
05972 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
05973 REAL permanent)
05974 #else
05975 REAL orient3dadapt(pa, pb, pc, pd,
05976 aheight, bheight, cheight, dheight, permanent)
05977 vertex pa;
05978 vertex pb;
05979 vertex pc;
05980 vertex pd;
05981 REAL aheight;
05982 REAL bheight;
05983 REAL cheight;
05984 REAL dheight;
05985 REAL permanent;
05986 #endif
05987
05988 {
05989 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
05990 REAL det, errbound;
05991
05992 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05993 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05994 REAL bc[4], ca[4], ab[4];
05995 INEXACT REAL bc3, ca3, ab3;
05996 REAL adet[8], bdet[8], cdet[8];
05997 int alen, blen, clen;
05998 REAL abdet[16];
05999 int ablen;
06000 REAL *finnow, *finother, *finswap;
06001 REAL fin1[192], fin2[192];
06002 int finlength;
06003
06004 REAL adxtail, bdxtail, cdxtail;
06005 REAL adytail, bdytail, cdytail;
06006 REAL adheighttail, bdheighttail, cdheighttail;
06007 INEXACT REAL at_blarge, at_clarge;
06008 INEXACT REAL bt_clarge, bt_alarge;
06009 INEXACT REAL ct_alarge, ct_blarge;
06010 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
06011 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
06012 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
06013 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
06014 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
06015 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
06016 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
06017 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
06018 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
06019 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
06020 REAL bct[8], cat[8], abt[8];
06021 int bctlen, catlen, abtlen;
06022 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
06023 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
06024 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
06025 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
06026 REAL u[4], v[12], w[16];
06027 INEXACT REAL u3;
06028 int vlength, wlength;
06029 REAL negate;
06030
06031 INEXACT REAL bvirt;
06032 REAL avirt, bround, around;
06033 INEXACT REAL c;
06034 INEXACT REAL abig;
06035 REAL ahi, alo, bhi, blo;
06036 REAL err1, err2, err3;
06037 INEXACT REAL _i, _j, _k;
06038 REAL _0;
06039
06040 adx = (REAL) (pa[0] - pd[0]);
06041 bdx = (REAL) (pb[0] - pd[0]);
06042 cdx = (REAL) (pc[0] - pd[0]);
06043 ady = (REAL) (pa[1] - pd[1]);
06044 bdy = (REAL) (pb[1] - pd[1]);
06045 cdy = (REAL) (pc[1] - pd[1]);
06046 adheight = (REAL) (aheight - dheight);
06047 bdheight = (REAL) (bheight - dheight);
06048 cdheight = (REAL) (cheight - dheight);
06049
06050 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
06051 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
06052 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
06053 bc[3] = bc3;
06054 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
06055
06056 Two_Product(cdx, ady, cdxady1, cdxady0);
06057 Two_Product(adx, cdy, adxcdy1, adxcdy0);
06058 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
06059 ca[3] = ca3;
06060 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
06061
06062 Two_Product(adx, bdy, adxbdy1, adxbdy0);
06063 Two_Product(bdx, ady, bdxady1, bdxady0);
06064 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
06065 ab[3] = ab3;
06066 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
06067
06068 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
06069 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
06070
06071 det = estimate(finlength, fin1);
06072 errbound = o3derrboundB * permanent;
06073 if ((det >= errbound) || (-det >= errbound)) {
06074 return det;
06075 }
06076
06077 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
06078 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
06079 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
06080 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
06081 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
06082 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
06083 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
06084 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
06085 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
06086
06087 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
06088 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
06089 (adheighttail == 0.0) &&
06090 (bdheighttail == 0.0) &&
06091 (cdheighttail == 0.0)) {
06092 return det;
06093 }
06094
06095 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
06096 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
06097 (bdy * cdxtail + cdx * bdytail)) +
06098 adheighttail * (bdx * cdy - bdy * cdx)) +
06099 (bdheight * ((cdx * adytail + ady * cdxtail) -
06100 (cdy * adxtail + adx * cdytail)) +
06101 bdheighttail * (cdx * ady - cdy * adx)) +
06102 (cdheight * ((adx * bdytail + bdy * adxtail) -
06103 (ady * bdxtail + bdx * adytail)) +
06104 cdheighttail * (adx * bdy - ady * bdx));
06105 if ((det >= errbound) || (-det >= errbound)) {
06106 return det;
06107 }
06108
06109 finnow = fin1;
06110 finother = fin2;
06111
06112 if (adxtail == 0.0) {
06113 if (adytail == 0.0) {
06114 at_b[0] = 0.0;
06115 at_blen = 1;
06116 at_c[0] = 0.0;
06117 at_clen = 1;
06118 } else {
06119 negate = -adytail;
06120 Two_Product(negate, bdx, at_blarge, at_b[0]);
06121 at_b[1] = at_blarge;
06122 at_blen = 2;
06123 Two_Product(adytail, cdx, at_clarge, at_c[0]);
06124 at_c[1] = at_clarge;
06125 at_clen = 2;
06126 }
06127 } else {
06128 if (adytail == 0.0) {
06129 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
06130 at_b[1] = at_blarge;
06131 at_blen = 2;
06132 negate = -adxtail;
06133 Two_Product(negate, cdy, at_clarge, at_c[0]);
06134 at_c[1] = at_clarge;
06135 at_clen = 2;
06136 } else {
06137 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
06138 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
06139 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
06140 at_blarge, at_b[2], at_b[1], at_b[0]);
06141 at_b[3] = at_blarge;
06142 at_blen = 4;
06143 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
06144 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
06145 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
06146 at_clarge, at_c[2], at_c[1], at_c[0]);
06147 at_c[3] = at_clarge;
06148 at_clen = 4;
06149 }
06150 }
06151 if (bdxtail == 0.0) {
06152 if (bdytail == 0.0) {
06153 bt_c[0] = 0.0;
06154 bt_clen = 1;
06155 bt_a[0] = 0.0;
06156 bt_alen = 1;
06157 } else {
06158 negate = -bdytail;
06159 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
06160 bt_c[1] = bt_clarge;
06161 bt_clen = 2;
06162 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
06163 bt_a[1] = bt_alarge;
06164 bt_alen = 2;
06165 }
06166 } else {
06167 if (bdytail == 0.0) {
06168 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
06169 bt_c[1] = bt_clarge;
06170 bt_clen = 2;
06171 negate = -bdxtail;
06172 Two_Product(negate, ady, bt_alarge, bt_a[0]);
06173 bt_a[1] = bt_alarge;
06174 bt_alen = 2;
06175 } else {
06176 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
06177 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
06178 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
06179 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
06180 bt_c[3] = bt_clarge;
06181 bt_clen = 4;
06182 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
06183 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
06184 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
06185 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
06186 bt_a[3] = bt_alarge;
06187 bt_alen = 4;
06188 }
06189 }
06190 if (cdxtail == 0.0) {
06191 if (cdytail == 0.0) {
06192 ct_a[0] = 0.0;
06193 ct_alen = 1;
06194 ct_b[0] = 0.0;
06195 ct_blen = 1;
06196 } else {
06197 negate = -cdytail;
06198 Two_Product(negate, adx, ct_alarge, ct_a[0]);
06199 ct_a[1] = ct_alarge;
06200 ct_alen = 2;
06201 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
06202 ct_b[1] = ct_blarge;
06203 ct_blen = 2;
06204 }
06205 } else {
06206 if (cdytail == 0.0) {
06207 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
06208 ct_a[1] = ct_alarge;
06209 ct_alen = 2;
06210 negate = -cdxtail;
06211 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
06212 ct_b[1] = ct_blarge;
06213 ct_blen = 2;
06214 } else {
06215 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
06216 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
06217 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
06218 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
06219 ct_a[3] = ct_alarge;
06220 ct_alen = 4;
06221 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
06222 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
06223 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
06224 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
06225 ct_b[3] = ct_blarge;
06226 ct_blen = 4;
06227 }
06228 }
06229
06230 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
06231 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
06232 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06233 finother);
06234 finswap = finnow; finnow = finother; finother = finswap;
06235
06236 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
06237 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
06238 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06239 finother);
06240 finswap = finnow; finnow = finother; finother = finswap;
06241
06242 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
06243 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
06244 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06245 finother);
06246 finswap = finnow; finnow = finother; finother = finswap;
06247
06248 if (adheighttail != 0.0) {
06249 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
06250 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06251 finother);
06252 finswap = finnow; finnow = finother; finother = finswap;
06253 }
06254 if (bdheighttail != 0.0) {
06255 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
06256 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06257 finother);
06258 finswap = finnow; finnow = finother; finother = finswap;
06259 }
06260 if (cdheighttail != 0.0) {
06261 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
06262 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06263 finother);
06264 finswap = finnow; finnow = finother; finother = finswap;
06265 }
06266
06267 if (adxtail != 0.0) {
06268 if (bdytail != 0.0) {
06269 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
06270 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
06271 u[3] = u3;
06272 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06273 finother);
06274 finswap = finnow; finnow = finother; finother = finswap;
06275 if (cdheighttail != 0.0) {
06276 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
06277 u3, u[2], u[1], u[0]);
06278 u[3] = u3;
06279 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06280 finother);
06281 finswap = finnow; finnow = finother; finother = finswap;
06282 }
06283 }
06284 if (cdytail != 0.0) {
06285 negate = -adxtail;
06286 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
06287 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
06288 u[3] = u3;
06289 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06290 finother);
06291 finswap = finnow; finnow = finother; finother = finswap;
06292 if (bdheighttail != 0.0) {
06293 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
06294 u3, u[2], u[1], u[0]);
06295 u[3] = u3;
06296 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06297 finother);
06298 finswap = finnow; finnow = finother; finother = finswap;
06299 }
06300 }
06301 }
06302 if (bdxtail != 0.0) {
06303 if (cdytail != 0.0) {
06304 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
06305 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
06306 u[3] = u3;
06307 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06308 finother);
06309 finswap = finnow; finnow = finother; finother = finswap;
06310 if (adheighttail != 0.0) {
06311 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
06312 u3, u[2], u[1], u[0]);
06313 u[3] = u3;
06314 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06315 finother);
06316 finswap = finnow; finnow = finother; finother = finswap;
06317 }
06318 }
06319 if (adytail != 0.0) {
06320 negate = -bdxtail;
06321 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
06322 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
06323 u[3] = u3;
06324 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06325 finother);
06326 finswap = finnow; finnow = finother; finother = finswap;
06327 if (cdheighttail != 0.0) {
06328 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
06329 u3, u[2], u[1], u[0]);
06330 u[3] = u3;
06331 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06332 finother);
06333 finswap = finnow; finnow = finother; finother = finswap;
06334 }
06335 }
06336 }
06337 if (cdxtail != 0.0) {
06338 if (adytail != 0.0) {
06339 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
06340 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
06341 u[3] = u3;
06342 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06343 finother);
06344 finswap = finnow; finnow = finother; finother = finswap;
06345 if (bdheighttail != 0.0) {
06346 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
06347 u3, u[2], u[1], u[0]);
06348 u[3] = u3;
06349 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06350 finother);
06351 finswap = finnow; finnow = finother; finother = finswap;
06352 }
06353 }
06354 if (bdytail != 0.0) {
06355 negate = -cdxtail;
06356 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
06357 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
06358 u[3] = u3;
06359 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06360 finother);
06361 finswap = finnow; finnow = finother; finother = finswap;
06362 if (adheighttail != 0.0) {
06363 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
06364 u3, u[2], u[1], u[0]);
06365 u[3] = u3;
06366 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06367 finother);
06368 finswap = finnow; finnow = finother; finother = finswap;
06369 }
06370 }
06371 }
06372
06373 if (adheighttail != 0.0) {
06374 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
06375 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06376 finother);
06377 finswap = finnow; finnow = finother; finother = finswap;
06378 }
06379 if (bdheighttail != 0.0) {
06380 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
06381 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06382 finother);
06383 finswap = finnow; finnow = finother; finother = finswap;
06384 }
06385 if (cdheighttail != 0.0) {
06386 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
06387 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06388 finother);
06389 finswap = finnow; finnow = finother; finother = finswap;
06390 }
06391
06392 return finnow[finlength - 1];
06393 }
06394
06395 #ifdef ANSI_DECLARATORS
06396 REAL orient3d(struct mesh *m, struct behavior *b,
06397 vertex pa, vertex pb, vertex pc, vertex pd,
06398 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
06399 #else
06400 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
06401 struct mesh *m;
06402 struct behavior *b;
06403 vertex pa;
06404 vertex pb;
06405 vertex pc;
06406 vertex pd;
06407 REAL aheight;
06408 REAL bheight;
06409 REAL cheight;
06410 REAL dheight;
06411 #endif
06412
06413 {
06414 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06415 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
06416 REAL det;
06417 REAL permanent, errbound;
06418
06419 m->orient3dcount++;
06420
06421 adx = pa[0] - pd[0];
06422 bdx = pb[0] - pd[0];
06423 cdx = pc[0] - pd[0];
06424 ady = pa[1] - pd[1];
06425 bdy = pb[1] - pd[1];
06426 cdy = pc[1] - pd[1];
06427 adheight = aheight - dheight;
06428 bdheight = bheight - dheight;
06429 cdheight = cheight - dheight;
06430
06431 bdxcdy = bdx * cdy;
06432 cdxbdy = cdx * bdy;
06433
06434 cdxady = cdx * ady;
06435 adxcdy = adx * cdy;
06436
06437 adxbdy = adx * bdy;
06438 bdxady = bdx * ady;
06439
06440 det = adheight * (bdxcdy - cdxbdy)
06441 + bdheight * (cdxady - adxcdy)
06442 + cdheight * (adxbdy - bdxady);
06443
06444 if (b->noexact) {
06445 return det;
06446 }
06447
06448 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
06449 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
06450 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
06451 errbound = o3derrboundA * permanent;
06452 if ((det > errbound) || (-det > errbound)) {
06453 return det;
06454 }
06455
06456 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
06457 permanent);
06458 }
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478 #ifdef ANSI_DECLARATORS
06479 REAL nonregular(struct mesh *m, struct behavior *b,
06480 vertex pa, vertex pb, vertex pc, vertex pd)
06481 #else
06482 REAL nonregular(m, b, pa, pb, pc, pd)
06483 struct mesh *m;
06484 struct behavior *b;
06485 vertex pa;
06486 vertex pb;
06487 vertex pc;
06488 vertex pd;
06489 #endif
06490
06491 {
06492 if (b->weighted == 0) {
06493 return incircle(m, b, pa, pb, pc, pd);
06494 } else if (b->weighted == 1) {
06495 return orient3d(m, b, pa, pb, pc, pd,
06496 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
06497 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
06498 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
06499 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
06500 } else {
06501 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
06502 }
06503 }
06504
06505
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515
06516
06517
06518
06519 #ifdef ANSI_DECLARATORS
06520 void findcircumcenter(struct mesh *m, struct behavior *b,
06521 vertex torg, vertex tdest, vertex tapex,
06522 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
06523 #else
06524 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
06525 offcenter)
06526 struct mesh *m;
06527 struct behavior *b;
06528 vertex torg;
06529 vertex tdest;
06530 vertex tapex;
06531 vertex circumcenter;
06532 REAL *xi;
06533 REAL *eta;
06534 int offcenter;
06535 #endif
06536
06537 {
06538 REAL xdo, ydo, xao, yao;
06539 REAL dodist, aodist, dadist;
06540 REAL denominator;
06541 REAL dx, dy, dxoff, dyoff;
06542
06543 m->circumcentercount++;
06544
06545
06546 xdo = tdest[0] - torg[0];
06547 ydo = tdest[1] - torg[1];
06548 xao = tapex[0] - torg[0];
06549 yao = tapex[1] - torg[1];
06550 dodist = xdo * xdo + ydo * ydo;
06551 aodist = xao * xao + yao * yao;
06552 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
06553 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
06554 if (b->noexact) {
06555 denominator = 0.5 / (xdo * yao - xao * ydo);
06556 } else {
06557
06558
06559
06560 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
06561
06562 m->counterclockcount--;
06563 }
06564 dx = (yao * dodist - ydo * aodist) * denominator;
06565 dy = (xdo * aodist - xao * dodist) * denominator;
06566
06567
06568
06569
06570
06571
06572 if ((dodist < aodist) && (dodist < dadist)) {
06573 if (offcenter && (b->offconstant > 0.0)) {
06574
06575 dxoff = 0.5 * xdo - b->offconstant * ydo;
06576 dyoff = 0.5 * ydo + b->offconstant * xdo;
06577
06578
06579 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06580 dx = dxoff;
06581 dy = dyoff;
06582 }
06583 }
06584 } else if (aodist < dadist) {
06585 if (offcenter && (b->offconstant > 0.0)) {
06586 dxoff = 0.5 * xao + b->offconstant * yao;
06587 dyoff = 0.5 * yao - b->offconstant * xao;
06588
06589
06590 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06591 dx = dxoff;
06592 dy = dyoff;
06593 }
06594 }
06595 } else {
06596 if (offcenter && (b->offconstant > 0.0)) {
06597 dxoff = 0.5 * (tapex[0] - tdest[0]) -
06598 b->offconstant * (tapex[1] - tdest[1]);
06599 dyoff = 0.5 * (tapex[1] - tdest[1]) +
06600 b->offconstant * (tapex[0] - tdest[0]);
06601
06602
06603 if (dxoff * dxoff + dyoff * dyoff <
06604 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
06605 dx = xdo + dxoff;
06606 dy = ydo + dyoff;
06607 }
06608 }
06609 }
06610
06611 circumcenter[0] = torg[0] + dx;
06612 circumcenter[1] = torg[1] + dy;
06613
06614
06615
06616
06617
06618
06619 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
06620 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
06621 }
06622
06625
06626
06627
06628
06629
06630
06631
06632
06633 #ifdef ANSI_DECLARATORS
06634 void triangleinit(struct mesh *m)
06635 #else
06636 void triangleinit(m)
06637 struct mesh *m;
06638 #endif
06639
06640 {
06641 poolzero(&m->vertices);
06642 poolzero(&m->triangles);
06643 poolzero(&m->subsegs);
06644 poolzero(&m->viri);
06645 poolzero(&m->badsubsegs);
06646 poolzero(&m->badtriangles);
06647 poolzero(&m->flipstackers);
06648 poolzero(&m->splaynodes);
06649
06650 m->recenttri.tri = (triangle *) NULL;
06651 m->undeads = 0;
06652 m->samples = 1;
06653 m->checksegments = 0;
06654 m->checkquality = 0;
06655 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
06656 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
06657 randomseed = 1;
06658
06659 exactinit();
06660 }
06661
06662
06663
06664
06665
06666
06667
06668
06669
06670
06671
06672 #ifdef ANSI_DECLARATORS
06673 unsigned long randomnation(unsigned int choices)
06674 #else
06675 unsigned long randomnation(choices)
06676 unsigned int choices;
06677 #endif
06678
06679 {
06680 randomseed = (randomseed * 1366l + 150889l) % 714025l;
06681 return randomseed / (714025l / choices + 1);
06682 }
06683
06684
06688
06689
06690
06691
06692
06693
06694 #ifndef REDUCED
06695
06696 #ifdef ANSI_DECLARATORS
06697 void checkmesh(struct mesh *m, struct behavior *b)
06698 #else
06699 void checkmesh(m, b)
06700 struct mesh *m;
06701 struct behavior *b;
06702 #endif
06703
06704 {
06705 struct otri triangleloop;
06706 struct otri oppotri, oppooppotri;
06707 vertex triorg, tridest, triapex;
06708 vertex oppoorg, oppodest;
06709 int horrors;
06710 int saveexact;
06711 triangle ptr;
06712
06713
06714 saveexact = b->noexact;
06715 b->noexact = 0;
06716 if (!b->quiet) {
06717 printf(" Checking consistency of mesh...\n");
06718 }
06719 horrors = 0;
06720
06721 traversalinit(&m->triangles);
06722 triangleloop.tri = triangletraverse(m);
06723 while (triangleloop.tri != (triangle *) NULL) {
06724
06725 for (triangleloop.orient = 0; triangleloop.orient < 3;
06726 triangleloop.orient++) {
06727 org(triangleloop, triorg);
06728 dest(triangleloop, tridest);
06729 if (triangleloop.orient == 0) {
06730
06731 apex(triangleloop, triapex);
06732 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
06733 printf(" !! !! Inverted ");
06734 printtriangle(m, b, &triangleloop);
06735 horrors++;
06736 }
06737 }
06738
06739 sym(triangleloop, oppotri);
06740 if (oppotri.tri != m->dummytri) {
06741
06742 sym(oppotri, oppooppotri);
06743 if ((triangleloop.tri != oppooppotri.tri)
06744 || (triangleloop.orient != oppooppotri.orient)) {
06745 printf(" !! !! Asymmetric triangle-triangle bond:\n");
06746 if (triangleloop.tri == oppooppotri.tri) {
06747 printf(" (Right triangle, wrong orientation)\n");
06748 }
06749 printf(" First ");
06750 printtriangle(m, b, &triangleloop);
06751 printf(" Second (nonreciprocating) ");
06752 printtriangle(m, b, &oppotri);
06753 horrors++;
06754 }
06755
06756
06757 org(oppotri, oppoorg);
06758 dest(oppotri, oppodest);
06759 if ((triorg != oppodest) || (tridest != oppoorg)) {
06760 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
06761 );
06762 printf(" First mismatched ");
06763 printtriangle(m, b, &triangleloop);
06764 printf(" Second mismatched ");
06765 printtriangle(m, b, &oppotri);
06766 horrors++;
06767 }
06768 }
06769 }
06770 triangleloop.tri = triangletraverse(m);
06771 }
06772 if (horrors == 0) {
06773 if (!b->quiet) {
06774 printf(" In my studied opinion, the mesh appears to be consistent.\n");
06775 }
06776 } else if (horrors == 1) {
06777 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
06778 } else {
06779 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
06780 }
06781
06782 b->noexact = saveexact;
06783 }
06784
06785 #endif
06786
06787
06788
06789
06790
06791
06792
06793 #ifndef REDUCED
06794
06795 #ifdef ANSI_DECLARATORS
06796 void checkdelaunay(struct mesh *m, struct behavior *b)
06797 #else
06798 void checkdelaunay(m, b)
06799 struct mesh *m;
06800 struct behavior *b;
06801 #endif
06802
06803 {
06804 struct otri triangleloop;
06805 struct otri oppotri;
06806 struct osub opposubseg;
06807 vertex triorg, tridest, triapex;
06808 vertex oppoapex;
06809 int shouldbedelaunay;
06810 int horrors;
06811 int saveexact;
06812 triangle ptr;
06813 subseg sptr;
06814
06815
06816 saveexact = b->noexact;
06817 b->noexact = 0;
06818 if (!b->quiet) {
06819 printf(" Checking Delaunay property of mesh...\n");
06820 }
06821 horrors = 0;
06822
06823 traversalinit(&m->triangles);
06824 triangleloop.tri = triangletraverse(m);
06825 while (triangleloop.tri != (triangle *) NULL) {
06826
06827 for (triangleloop.orient = 0; triangleloop.orient < 3;
06828 triangleloop.orient++) {
06829 org(triangleloop, triorg);
06830 dest(triangleloop, tridest);
06831 apex(triangleloop, triapex);
06832 sym(triangleloop, oppotri);
06833 apex(oppotri, oppoapex);
06834
06835
06836
06837 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
06838 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
06839 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
06840 (triorg != m->infvertex3) &&
06841 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
06842 (tridest != m->infvertex3) &&
06843 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
06844 (triapex != m->infvertex3) &&
06845 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
06846 (oppoapex != m->infvertex3);
06847 if (m->checksegments && shouldbedelaunay) {
06848
06849
06850 tspivot(triangleloop, opposubseg);
06851 if (opposubseg.ss != m->dummysub){
06852 shouldbedelaunay = 0;
06853 }
06854 }
06855 if (shouldbedelaunay) {
06856 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
06857 if (!b->weighted) {
06858 printf(" !! !! Non-Delaunay pair of triangles:\n");
06859 printf(" First non-Delaunay ");
06860 printtriangle(m, b, &triangleloop);
06861 printf(" Second non-Delaunay ");
06862 } else {
06863 printf(" !! !! Non-regular pair of triangles:\n");
06864 printf(" First non-regular ");
06865 printtriangle(m, b, &triangleloop);
06866 printf(" Second non-regular ");
06867 }
06868 printtriangle(m, b, &oppotri);
06869 horrors++;
06870 }
06871 }
06872 }
06873 triangleloop.tri = triangletraverse(m);
06874 }
06875 if (horrors == 0) {
06876 if (!b->quiet) {
06877 printf(
06878 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
06879 }
06880 } else if (horrors == 1) {
06881 printf(
06882 " !! !! !! !! Precisely one terrifying transgression identified.\n");
06883 } else {
06884 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
06885 }
06886
06887 b->noexact = saveexact;
06888 }
06889
06890 #endif
06891
06892
06893
06894
06895
06896
06897
06898
06899
06900
06901
06902
06903 #ifndef CDT_ONLY
06904
06905 #ifdef ANSI_DECLARATORS
06906 void enqueuebadtriang(struct mesh *m, struct behavior *b,
06907 struct badtriang *badtri)
06908 #else
06909 void enqueuebadtriang(m, b, badtri)
06910 struct mesh *m;
06911 struct behavior *b;
06912 struct badtriang *badtri;
06913 #endif
06914
06915 {
06916 REAL length, multiplier;
06917 int exponent, expincrement;
06918 int queuenumber;
06919 int posexponent;
06920 int i;
06921
06922 if (b->verbose > 2) {
06923 printf(" Queueing bad triangle:\n");
06924 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
06925 badtri->triangorg[0], badtri->triangorg[1],
06926 badtri->triangdest[0], badtri->triangdest[1],
06927 badtri->triangapex[0], badtri->triangapex[1]);
06928 }
06929
06930
06931
06932 if (badtri->key >= 1.0) {
06933 length = badtri->key;
06934 posexponent = 1;
06935 } else {
06936
06937
06938 length = 1.0 / badtri->key;
06939 posexponent = 0;
06940 }
06941
06942
06943 exponent = 0;
06944 while (length > 2.0) {
06945
06946 expincrement = 1;
06947 multiplier = 0.5;
06948 while (length * multiplier * multiplier > 1.0) {
06949 expincrement *= 2;
06950 multiplier *= multiplier;
06951 }
06952
06953 exponent += expincrement;
06954 length *= multiplier;
06955 }
06956
06957 exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
06958
06959
06960
06961 if (posexponent) {
06962 queuenumber = 2047 - exponent;
06963 } else {
06964 queuenumber = 2048 + exponent;
06965 }
06966
06967
06968 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
06969
06970
06971 if (queuenumber > m->firstnonemptyq) {
06972
06973 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
06974 m->firstnonemptyq = queuenumber;
06975 } else {
06976
06977
06978 i = queuenumber + 1;
06979 while (m->queuefront[i] == (struct badtriang *) NULL) {
06980 i++;
06981 }
06982
06983 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
06984 m->nextnonemptyq[i] = queuenumber;
06985 }
06986
06987 m->queuefront[queuenumber] = badtri;
06988 } else {
06989
06990 m->queuetail[queuenumber]->nexttriang = badtri;
06991 }
06992
06993 m->queuetail[queuenumber] = badtri;
06994
06995 badtri->nexttriang = (struct badtriang *) NULL;
06996 }
06997
06998 #endif
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07009 #ifndef CDT_ONLY
07010
07011 #ifdef ANSI_DECLARATORS
07012 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
07013 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
07014 #else
07015 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
07016 struct mesh *m;
07017 struct behavior *b;
07018 struct otri *enqtri;
07019 REAL minedge;
07020 vertex enqapex;
07021 vertex enqorg;
07022 vertex enqdest;
07023 #endif
07024
07025 {
07026 struct badtriang *newbad;
07027
07028
07029 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
07030 newbad->poortri = encode(*enqtri);
07031 newbad->key = minedge;
07032 newbad->triangapex = enqapex;
07033 newbad->triangorg = enqorg;
07034 newbad->triangdest = enqdest;
07035 enqueuebadtriang(m, b, newbad);
07036 }
07037
07038 #endif
07039
07040
07041
07042
07043
07044
07045
07046 #ifndef CDT_ONLY
07047
07048 #ifdef ANSI_DECLARATORS
07049 struct badtriang *dequeuebadtriang(struct mesh *m)
07050 #else
07051 struct badtriang *dequeuebadtriang(m)
07052 struct mesh *m;
07053 #endif
07054
07055 {
07056 struct badtriang *result;
07057
07058
07059 if (m->firstnonemptyq < 0) {
07060 return (struct badtriang *) NULL;
07061 }
07062
07063 result = m->queuefront[m->firstnonemptyq];
07064
07065 m->queuefront[m->firstnonemptyq] = result->nexttriang;
07066
07067
07068 if (result == m->queuetail[m->firstnonemptyq]) {
07069 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
07070 }
07071 return result;
07072 }
07073
07074 #endif
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097
07098
07099 #ifndef CDT_ONLY
07100
07101 #ifdef ANSI_DECLARATORS
07102 int checkseg4encroach(struct mesh *m, struct behavior *b,
07103 struct osub *testsubseg)
07104 #else
07105 int checkseg4encroach(m, b, testsubseg)
07106 struct mesh *m;
07107 struct behavior *b;
07108 struct osub *testsubseg;
07109 #endif
07110
07111 {
07112 struct otri neighbortri;
07113 struct osub testsym;
07114 struct badsubseg *encroachedseg;
07115 REAL dotproduct;
07116 int encroached;
07117 int sides;
07118 vertex eorg, edest, eapex;
07119 triangle ptr;
07120
07121 encroached = 0;
07122 sides = 0;
07123
07124 sorg(*testsubseg, eorg);
07125 sdest(*testsubseg, edest);
07126
07127 stpivot(*testsubseg, neighbortri);
07128
07129 if (neighbortri.tri != m->dummytri) {
07130 sides++;
07131
07132 apex(neighbortri, eapex);
07133
07134
07135
07136
07137
07138 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07139 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07140 if (dotproduct < 0.0) {
07141 if (b->conformdel ||
07142 (dotproduct * dotproduct >=
07143 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07144 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07145 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07146 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07147 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07148 encroached = 1;
07149 }
07150 }
07151 }
07152
07153 ssym(*testsubseg, testsym);
07154 stpivot(testsym, neighbortri);
07155
07156 if (neighbortri.tri != m->dummytri) {
07157 sides++;
07158
07159 apex(neighbortri, eapex);
07160
07161
07162 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07163 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07164 if (dotproduct < 0.0) {
07165 if (b->conformdel ||
07166 (dotproduct * dotproduct >=
07167 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07168 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07169 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07170 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07171 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07172 encroached += 2;
07173 }
07174 }
07175 }
07176
07177 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
07178 if (b->verbose > 2) {
07179 printf(
07180 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
07181 eorg[0], eorg[1], edest[0], edest[1]);
07182 }
07183
07184
07185 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
07186 if (encroached == 1) {
07187 encroachedseg->encsubseg = sencode(*testsubseg);
07188 encroachedseg->subsegorg = eorg;
07189 encroachedseg->subsegdest = edest;
07190 } else {
07191 encroachedseg->encsubseg = sencode(testsym);
07192 encroachedseg->subsegorg = edest;
07193 encroachedseg->subsegdest = eorg;
07194 }
07195 }
07196
07197 return encroached;
07198 }
07199
07200 #endif
07201
07202
07203
07204
07205
07206
07207
07208
07209
07210
07211
07212 #ifndef CDT_ONLY
07213
07214 #ifdef ANSI_DECLARATORS
07215 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
07216 #else
07217 void testtriangle(m, b, testtri)
07218 struct mesh *m;
07219 struct behavior *b;
07220 struct otri *testtri;
07221 #endif
07222
07223 {
07224 struct otri tri1, tri2;
07225 struct osub testsub;
07226 vertex torg, tdest, tapex;
07227 vertex base1, base2;
07228 vertex org1, dest1, org2, dest2;
07229 vertex joinvertex;
07230 REAL dxod, dyod, dxda, dyda, dxao, dyao;
07231 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
07232 REAL apexlen, orglen, destlen, minedge;
07233 REAL angle;
07234 REAL area;
07235 REAL dist1, dist2;
07236 subseg sptr;
07237 triangle ptr;
07238
07239 org(*testtri, torg);
07240 dest(*testtri, tdest);
07241 apex(*testtri, tapex);
07242 dxod = torg[0] - tdest[0];
07243 dyod = torg[1] - tdest[1];
07244 dxda = tdest[0] - tapex[0];
07245 dyda = tdest[1] - tapex[1];
07246 dxao = tapex[0] - torg[0];
07247 dyao = tapex[1] - torg[1];
07248 dxod2 = dxod * dxod;
07249 dyod2 = dyod * dyod;
07250 dxda2 = dxda * dxda;
07251 dyda2 = dyda * dyda;
07252 dxao2 = dxao * dxao;
07253 dyao2 = dyao * dyao;
07254
07255 apexlen = dxod2 + dyod2;
07256 orglen = dxda2 + dyda2;
07257 destlen = dxao2 + dyao2;
07258
07259 if ((apexlen < orglen) && (apexlen < destlen)) {
07260
07261 minedge = apexlen;
07262
07263 angle = dxda * dxao + dyda * dyao;
07264 angle = angle * angle / (orglen * destlen);
07265 base1 = torg;
07266 base2 = tdest;
07267 otricopy(*testtri, tri1);
07268 } else if (orglen < destlen) {
07269
07270 minedge = orglen;
07271
07272 angle = dxod * dxao + dyod * dyao;
07273 angle = angle * angle / (apexlen * destlen);
07274 base1 = tdest;
07275 base2 = tapex;
07276 lnext(*testtri, tri1);
07277 } else {
07278
07279 minedge = destlen;
07280
07281 angle = dxod * dxda + dyod * dyda;
07282 angle = angle * angle / (apexlen * orglen);
07283 base1 = tapex;
07284 base2 = torg;
07285 lprev(*testtri, tri1);
07286 }
07287
07288 if (b->vararea || b->fixedarea || b->usertest) {
07289
07290 area = 0.5 * (dxod * dyda - dyod * dxda);
07291 if (b->fixedarea && (area > b->maxarea)) {
07292
07293 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07294 return;
07295 }
07296
07297
07298 if ((b->vararea) && (area > areabound(*testtri)) &&
07299 (areabound(*testtri) > 0.0)) {
07300
07301 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07302 return;
07303 }
07304
07305 if (b->usertest) {
07306
07307 if (triunsuitable(torg, tdest, tapex, area)) {
07308 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07309 return;
07310 }
07311 }
07312 }
07313
07314
07315 if (angle > b->goodangle) {
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325 if ((vertextype(base1) == SEGMENTVERTEX) &&
07326 (vertextype(base2) == SEGMENTVERTEX)) {
07327
07328
07329 tspivot(tri1, testsub);
07330 if (testsub.ss == m->dummysub) {
07331
07332 otricopy(tri1, tri2);
07333 do {
07334 oprevself(tri1);
07335 tspivot(tri1, testsub);
07336 } while (testsub.ss == m->dummysub);
07337
07338 segorg(testsub, org1);
07339 segdest(testsub, dest1);
07340
07341 do {
07342 dnextself(tri2);
07343 tspivot(tri2, testsub);
07344 } while (testsub.ss == m->dummysub);
07345
07346 segorg(testsub, org2);
07347 segdest(testsub, dest2);
07348
07349 joinvertex = (vertex) NULL;
07350 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
07351 joinvertex = dest1;
07352 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
07353 joinvertex = org1;
07354 }
07355 if (joinvertex != (vertex) NULL) {
07356
07357
07358 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
07359 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
07360 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
07361 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
07362
07363 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
07364
07365 return;
07366 }
07367 }
07368 }
07369 }
07370
07371
07372 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07373 }
07374 }
07375
07376 #endif
07377
07380
07381
07382
07386
07387
07388
07389
07390
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400 #ifdef ANSI_DECLARATORS
07401 void makevertexmap(struct mesh *m, struct behavior *b)
07402 #else
07403 void makevertexmap(m, b)
07404 struct mesh *m;
07405 struct behavior *b;
07406 #endif
07407
07408 {
07409 struct otri triangleloop;
07410 vertex triorg;
07411
07412 if (b->verbose) {
07413 printf(" Constructing mapping from vertices to triangles.\n");
07414 }
07415 traversalinit(&m->triangles);
07416 triangleloop.tri = triangletraverse(m);
07417 while (triangleloop.tri != (triangle *) NULL) {
07418
07419 for (triangleloop.orient = 0; triangleloop.orient < 3;
07420 triangleloop.orient++) {
07421 org(triangleloop, triorg);
07422 setvertex2tri(triorg, encode(triangleloop));
07423 }
07424 triangleloop.tri = triangletraverse(m);
07425 }
07426 }
07427
07428
07429
07430
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454
07455
07456
07457
07458
07459
07460
07461
07462
07463
07464
07465
07466
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477
07478
07479
07480
07481
07482
07483
07484
07485
07486
07487
07488
07489
07490
07491
07492
07493
07494
07495 #ifdef ANSI_DECLARATORS
07496 enum locateresult preciselocate(struct mesh *m, struct behavior *b,
07497 vertex searchpoint, struct otri *searchtri,
07498 int stopatsubsegment)
07499 #else
07500 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
07501 struct mesh *m;
07502 struct behavior *b;
07503 vertex searchpoint;
07504 struct otri *searchtri;
07505 int stopatsubsegment;
07506 #endif
07507
07508 {
07509 struct otri backtracktri;
07510 struct osub checkedge;
07511 vertex forg, fdest, fapex;
07512 REAL orgorient, destorient;
07513 int moveleft;
07514 triangle ptr;
07515 subseg sptr;
07516
07517 if (b->verbose > 2) {
07518 printf(" Searching for point (%.12g, %.12g).\n",
07519 searchpoint[0], searchpoint[1]);
07520 }
07521
07522 org(*searchtri, forg);
07523 dest(*searchtri, fdest);
07524 apex(*searchtri, fapex);
07525 while (1) {
07526 if (b->verbose > 2) {
07527 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07528 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
07529 }
07530
07531 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
07532 lprevself(*searchtri);
07533 return ONVERTEX;
07534 }
07535
07536
07537 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
07538
07539
07540 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
07541 if (destorient > 0.0) {
07542 if (orgorient > 0.0) {
07543
07544
07545
07546
07547
07548 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
07549 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
07550 } else {
07551 moveleft = 1;
07552 }
07553 } else {
07554 if (orgorient > 0.0) {
07555 moveleft = 0;
07556 } else {
07557
07558
07559 if (destorient == 0.0) {
07560 lprevself(*searchtri);
07561 return ONEDGE;
07562 }
07563 if (orgorient == 0.0) {
07564 lnextself(*searchtri);
07565 return ONEDGE;
07566 }
07567 return INTRIANGLE;
07568 }
07569 }
07570
07571
07572
07573
07574 if (moveleft) {
07575 lprev(*searchtri, backtracktri);
07576 fdest = fapex;
07577 } else {
07578 lnext(*searchtri, backtracktri);
07579 forg = fapex;
07580 }
07581 sym(backtracktri, *searchtri);
07582
07583 if (m->checksegments && stopatsubsegment) {
07584
07585 tspivot(backtracktri, checkedge);
07586 if (checkedge.ss != m->dummysub) {
07587
07588 otricopy(backtracktri, *searchtri);
07589 return OUTSIDE;
07590 }
07591 }
07592
07593 if (searchtri->tri == m->dummytri) {
07594
07595 otricopy(backtracktri, *searchtri);
07596 return OUTSIDE;
07597 }
07598
07599 apex(*searchtri, fapex);
07600 }
07601 }
07602
07603
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616
07617
07618
07619
07620
07621
07622
07623
07624
07625
07626
07627
07628
07629
07630
07631
07632
07633
07634
07635
07636
07637
07638
07639 #ifdef ANSI_DECLARATORS
07640 enum locateresult locate(struct mesh *m, struct behavior *b,
07641 vertex searchpoint, struct otri *searchtri)
07642 #else
07643 enum locateresult locate(m, b, searchpoint, searchtri)
07644 struct mesh *m;
07645 struct behavior *b;
07646 vertex searchpoint;
07647 struct otri *searchtri;
07648 #endif
07649
07650 {
07651 VOID **sampleblock;
07652 char *firsttri;
07653 struct otri sampletri;
07654 vertex torg, tdest;
07655 unsigned long alignptr;
07656 REAL searchdist, dist;
07657 REAL ahead;
07658 long samplesperblock, totalsamplesleft, samplesleft;
07659 long population, totalpopulation;
07660 triangle ptr;
07661
07662 if (b->verbose > 2) {
07663 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
07664 searchpoint[0], searchpoint[1]);
07665 }
07666
07667
07668 org(*searchtri, torg);
07669 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07670 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07671 if (b->verbose > 2) {
07672 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
07673 torg[0], torg[1]);
07674 }
07675
07676
07677
07678 if (m->recenttri.tri != (triangle *) NULL) {
07679 if (!deadtri(m->recenttri.tri)) {
07680 org(m->recenttri, torg);
07681 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07682 otricopy(m->recenttri, *searchtri);
07683 return ONVERTEX;
07684 }
07685 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07686 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07687 if (dist < searchdist) {
07688 otricopy(m->recenttri, *searchtri);
07689 searchdist = dist;
07690 if (b->verbose > 2) {
07691 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
07692 torg[0], torg[1]);
07693 }
07694 }
07695 }
07696 }
07697
07698
07699
07700
07701
07702 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
07703 m->triangles.items) {
07704 m->samples++;
07705 }
07706
07707
07708
07709
07710
07711 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
07712
07713
07714 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
07715 m->triangles.maxitems + 1;
07716 totalsamplesleft = m->samples;
07717 population = m->triangles.itemsfirstblock;
07718 totalpopulation = m->triangles.maxitems;
07719 sampleblock = m->triangles.firstblock;
07720 sampletri.orient = 0;
07721 while (totalsamplesleft > 0) {
07722
07723 if (population > totalpopulation) {
07724 population = totalpopulation;
07725 }
07726
07727 alignptr = (unsigned long) (sampleblock + 1);
07728 firsttri = (char *) (alignptr +
07729 (unsigned long) m->triangles.alignbytes -
07730 (alignptr %
07731 (unsigned long) m->triangles.alignbytes));
07732
07733
07734 do {
07735 sampletri.tri = (triangle *) (firsttri +
07736 (randomnation((unsigned int) population) *
07737 m->triangles.itembytes));
07738 if (!deadtri(sampletri.tri)) {
07739 org(sampletri, torg);
07740 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07741 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07742 if (dist < searchdist) {
07743 otricopy(sampletri, *searchtri);
07744 searchdist = dist;
07745 if (b->verbose > 2) {
07746 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
07747 torg[0], torg[1]);
07748 }
07749 }
07750 }
07751
07752 samplesleft--;
07753 totalsamplesleft--;
07754 } while ((samplesleft > 0) && (totalsamplesleft > 0));
07755
07756 if (totalsamplesleft > 0) {
07757 sampleblock = (VOID **) *sampleblock;
07758 samplesleft = samplesperblock;
07759 totalpopulation -= population;
07760 population = TRIPERBLOCK;
07761 }
07762 }
07763
07764
07765 org(*searchtri, torg);
07766 dest(*searchtri, tdest);
07767
07768 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07769 return ONVERTEX;
07770 }
07771 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
07772 lnextself(*searchtri);
07773 return ONVERTEX;
07774 }
07775
07776 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
07777 if (ahead < 0.0) {
07778
07779
07780 symself(*searchtri);
07781 } else if (ahead == 0.0) {
07782
07783 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
07784 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
07785 return ONEDGE;
07786 }
07787 }
07788 return preciselocate(m, b, searchpoint, searchtri, 0);
07789 }
07790
07793
07794
07795
07799
07800
07801
07802
07803
07804
07805
07806
07807
07808
07809
07810 #ifdef ANSI_DECLARATORS
07811 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
07812 int subsegmark)
07813 #else
07814 void insertsubseg(m, b, tri, subsegmark)
07815 struct mesh *m;
07816 struct behavior *b;
07817 struct otri *tri;
07818 int subsegmark;
07819 #endif
07820
07821 {
07822 struct otri oppotri;
07823 struct osub newsubseg;
07824 vertex triorg, tridest;
07825 triangle ptr;
07826 subseg sptr;
07827
07828 org(*tri, triorg);
07829 dest(*tri, tridest);
07830
07831 if (vertexmark(triorg) == 0) {
07832 setvertexmark(triorg, subsegmark);
07833 }
07834 if (vertexmark(tridest) == 0) {
07835 setvertexmark(tridest, subsegmark);
07836 }
07837
07838 tspivot(*tri, newsubseg);
07839 if (newsubseg.ss == m->dummysub) {
07840
07841 makesubseg(m, &newsubseg);
07842 setsorg(newsubseg, tridest);
07843 setsdest(newsubseg, triorg);
07844 setsegorg(newsubseg, tridest);
07845 setsegdest(newsubseg, triorg);
07846
07847
07848
07849
07850 tsbond(*tri, newsubseg);
07851 sym(*tri, oppotri);
07852 ssymself(newsubseg);
07853 tsbond(oppotri, newsubseg);
07854 setmark(newsubseg, subsegmark);
07855 if (b->verbose > 2) {
07856 printf(" Inserting new ");
07857 printsubseg(m, b, &newsubseg);
07858 }
07859 } else {
07860 if (mark(newsubseg) == 0) {
07861 setmark(newsubseg, subsegmark);
07862 }
07863 }
07864 }
07865
07866
07867
07868
07869
07870
07871
07872
07873
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887
07888
07889
07890
07891
07892
07893
07894
07895
07896
07897
07898
07899
07900
07901
07902
07903
07904
07905
07906
07907
07908
07909
07910
07911
07912
07913
07914 #ifdef ANSI_DECLARATORS
07915 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
07916 #else
07917 void flip(m, b, flipedge)
07918 struct mesh *m;
07919 struct behavior *b;
07920 struct otri *flipedge;
07921 #endif
07922
07923 {
07924 struct otri botleft, botright;
07925 struct otri topleft, topright;
07926 struct otri top;
07927 struct otri botlcasing, botrcasing;
07928 struct otri toplcasing, toprcasing;
07929 struct osub botlsubseg, botrsubseg;
07930 struct osub toplsubseg, toprsubseg;
07931 vertex leftvertex, rightvertex, botvertex;
07932 vertex farvertex;
07933 triangle ptr;
07934 subseg sptr;
07935
07936
07937 org(*flipedge, rightvertex);
07938 dest(*flipedge, leftvertex);
07939 apex(*flipedge, botvertex);
07940 sym(*flipedge, top);
07941 #ifdef SELF_CHECK
07942 if (top.tri == m->dummytri) {
07943 printf("Internal error in flip(): Attempt to flip on boundary.\n");
07944 lnextself(*flipedge);
07945 return;
07946 }
07947 if (m->checksegments) {
07948 tspivot(*flipedge, toplsubseg);
07949 if (toplsubseg.ss != m->dummysub) {
07950 printf("Internal error in flip(): Attempt to flip a segment.\n");
07951 lnextself(*flipedge);
07952 return;
07953 }
07954 }
07955 #endif
07956 apex(top, farvertex);
07957
07958
07959 lprev(top, topleft);
07960 sym(topleft, toplcasing);
07961 lnext(top, topright);
07962 sym(topright, toprcasing);
07963 lnext(*flipedge, botleft);
07964 sym(botleft, botlcasing);
07965 lprev(*flipedge, botright);
07966 sym(botright, botrcasing);
07967
07968 bond(topleft, botlcasing);
07969 bond(botleft, botrcasing);
07970 bond(botright, toprcasing);
07971 bond(topright, toplcasing);
07972
07973 if (m->checksegments) {
07974
07975 tspivot(topleft, toplsubseg);
07976 tspivot(botleft, botlsubseg);
07977 tspivot(botright, botrsubseg);
07978 tspivot(topright, toprsubseg);
07979 if (toplsubseg.ss == m->dummysub) {
07980 tsdissolve(topright);
07981 } else {
07982 tsbond(topright, toplsubseg);
07983 }
07984 if (botlsubseg.ss == m->dummysub) {
07985 tsdissolve(topleft);
07986 } else {
07987 tsbond(topleft, botlsubseg);
07988 }
07989 if (botrsubseg.ss == m->dummysub) {
07990 tsdissolve(botleft);
07991 } else {
07992 tsbond(botleft, botrsubseg);
07993 }
07994 if (toprsubseg.ss == m->dummysub) {
07995 tsdissolve(botright);
07996 } else {
07997 tsbond(botright, toprsubseg);
07998 }
07999 }
08000
08001
08002 setorg(*flipedge, farvertex);
08003 setdest(*flipedge, botvertex);
08004 setapex(*flipedge, rightvertex);
08005 setorg(top, botvertex);
08006 setdest(top, farvertex);
08007 setapex(top, leftvertex);
08008 if (b->verbose > 2) {
08009 printf(" Edge flip results in left ");
08010 printtriangle(m, b, &top);
08011 printf(" and right ");
08012 printtriangle(m, b, flipedge);
08013 }
08014 }
08015
08016
08017
08018
08019
08020
08021
08022
08023
08024
08025
08026
08027
08028
08029
08030
08031
08032
08033
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046
08047
08048
08049 #ifdef ANSI_DECLARATORS
08050 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
08051 #else
08052 void unflip(m, b, flipedge)
08053 struct mesh *m;
08054 struct behavior *b;
08055 struct otri *flipedge;
08056 #endif
08057
08058 {
08059 struct otri botleft, botright;
08060 struct otri topleft, topright;
08061 struct otri top;
08062 struct otri botlcasing, botrcasing;
08063 struct otri toplcasing, toprcasing;
08064 struct osub botlsubseg, botrsubseg;
08065 struct osub toplsubseg, toprsubseg;
08066 vertex leftvertex, rightvertex, botvertex;
08067 vertex farvertex;
08068 triangle ptr;
08069 subseg sptr;
08070
08071
08072 org(*flipedge, rightvertex);
08073 dest(*flipedge, leftvertex);
08074 apex(*flipedge, botvertex);
08075 sym(*flipedge, top);
08076 #ifdef SELF_CHECK
08077 if (top.tri == m->dummytri) {
08078 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
08079 lnextself(*flipedge);
08080 return;
08081 }
08082 if (m->checksegments) {
08083 tspivot(*flipedge, toplsubseg);
08084 if (toplsubseg.ss != m->dummysub) {
08085 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
08086 lnextself(*flipedge);
08087 return;
08088 }
08089 }
08090 #endif
08091 apex(top, farvertex);
08092
08093
08094 lprev(top, topleft);
08095 sym(topleft, toplcasing);
08096 lnext(top, topright);
08097 sym(topright, toprcasing);
08098 lnext(*flipedge, botleft);
08099 sym(botleft, botlcasing);
08100 lprev(*flipedge, botright);
08101 sym(botright, botrcasing);
08102
08103 bond(topleft, toprcasing);
08104 bond(botleft, toplcasing);
08105 bond(botright, botlcasing);
08106 bond(topright, botrcasing);
08107
08108 if (m->checksegments) {
08109
08110 tspivot(topleft, toplsubseg);
08111 tspivot(botleft, botlsubseg);
08112 tspivot(botright, botrsubseg);
08113 tspivot(topright, toprsubseg);
08114 if (toplsubseg.ss == m->dummysub) {
08115 tsdissolve(botleft);
08116 } else {
08117 tsbond(botleft, toplsubseg);
08118 }
08119 if (botlsubseg.ss == m->dummysub) {
08120 tsdissolve(botright);
08121 } else {
08122 tsbond(botright, botlsubseg);
08123 }
08124 if (botrsubseg.ss == m->dummysub) {
08125 tsdissolve(topright);
08126 } else {
08127 tsbond(topright, botrsubseg);
08128 }
08129 if (toprsubseg.ss == m->dummysub) {
08130 tsdissolve(topleft);
08131 } else {
08132 tsbond(topleft, toprsubseg);
08133 }
08134 }
08135
08136
08137 setorg(*flipedge, botvertex);
08138 setdest(*flipedge, farvertex);
08139 setapex(*flipedge, leftvertex);
08140 setorg(top, farvertex);
08141 setdest(top, botvertex);
08142 setapex(top, rightvertex);
08143 if (b->verbose > 2) {
08144 printf(" Edge unflip results in left ");
08145 printtriangle(m, b, flipedge);
08146 printf(" and right ");
08147 printtriangle(m, b, &top);
08148 }
08149 }
08150
08151
08152
08153
08154
08155
08156
08157
08158
08159
08160
08161
08162
08163
08164
08165
08166
08167
08168
08169
08170
08171
08172
08173
08174
08175
08176
08177
08178
08179
08180
08181
08182
08183
08184
08185
08186
08187
08188
08189
08190
08191
08192
08193
08194
08195
08196
08197
08198 #ifdef ANSI_DECLARATORS
08199 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
08200 vertex newvertex, struct otri *searchtri,
08201 struct osub *splitseg,
08202 int segmentflaws, int triflaws)
08203 #else
08204 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
08205 segmentflaws, triflaws)
08206 struct mesh *m;
08207 struct behavior *b;
08208 vertex newvertex;
08209 struct otri *searchtri;
08210 struct osub *splitseg;
08211 int segmentflaws;
08212 int triflaws;
08213 #endif
08214
08215 {
08216 struct otri horiz;
08217 struct otri top;
08218 struct otri botleft, botright;
08219 struct otri topleft, topright;
08220 struct otri newbotleft, newbotright;
08221 struct otri newtopright;
08222 struct otri botlcasing, botrcasing;
08223 struct otri toplcasing, toprcasing;
08224 struct otri testtri;
08225 struct osub botlsubseg, botrsubseg;
08226 struct osub toplsubseg, toprsubseg;
08227 struct osub brokensubseg;
08228 struct osub checksubseg;
08229 struct osub rightsubseg;
08230 struct osub newsubseg;
08231 struct badsubseg *encroached;
08232 struct flipstacker *newflip;
08233 vertex first;
08234 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
08235 vertex segmentorg, segmentdest;
08236 REAL attrib;
08237 REAL area;
08238 enum insertvertexresult success;
08239 enum locateresult intersect;
08240 int doflip;
08241 int mirrorflag;
08242 int enq;
08243 int i;
08244 triangle ptr;
08245 subseg sptr;
08246
08247 if (b->verbose > 1) {
08248 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
08249 }
08250
08251 if (splitseg == (struct osub *) NULL) {
08252
08253
08254 if (searchtri->tri == m->dummytri) {
08255
08256 horiz.tri = m->dummytri;
08257 horiz.orient = 0;
08258 symself(horiz);
08259
08260 intersect = locate(m, b, newvertex, &horiz);
08261 } else {
08262
08263 otricopy(*searchtri, horiz);
08264 intersect = preciselocate(m, b, newvertex, &horiz, 1);
08265 }
08266 } else {
08267
08268
08269 otricopy(*searchtri, horiz);
08270 intersect = ONEDGE;
08271 }
08272
08273 if (intersect == ONVERTEX) {
08274
08275
08276 otricopy(horiz, *searchtri);
08277 otricopy(horiz, m->recenttri);
08278 return DUPLICATEVERTEX;
08279 }
08280 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
08281
08282 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
08283
08284 tspivot(horiz, brokensubseg);
08285 if (brokensubseg.ss != m->dummysub) {
08286
08287 if (segmentflaws) {
08288 enq = b->nobisect != 2;
08289 if (enq && (b->nobisect == 1)) {
08290
08291
08292 sym(horiz, testtri);
08293 enq = testtri.tri != m->dummytri;
08294 }
08295 if (enq) {
08296
08297 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
08298 encroached->encsubseg = sencode(brokensubseg);
08299 sorg(brokensubseg, encroached->subsegorg);
08300 sdest(brokensubseg, encroached->subsegdest);
08301 if (b->verbose > 2) {
08302 printf(
08303 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
08304 encroached->subsegorg[0], encroached->subsegorg[1],
08305 encroached->subsegdest[0], encroached->subsegdest[1]);
08306 }
08307 }
08308 }
08309
08310
08311 otricopy(horiz, *searchtri);
08312 otricopy(horiz, m->recenttri);
08313 return VIOLATINGVERTEX;
08314 }
08315 }
08316
08317
08318
08319 lprev(horiz, botright);
08320 sym(botright, botrcasing);
08321 sym(horiz, topright);
08322
08323 mirrorflag = topright.tri != m->dummytri;
08324 if (mirrorflag) {
08325 lnextself(topright);
08326 sym(topright, toprcasing);
08327 maketriangle(m, b, &newtopright);
08328 } else {
08329
08330 m->hullsize++;
08331 }
08332 maketriangle(m, b, &newbotright);
08333
08334
08335 org(horiz, rightvertex);
08336 dest(horiz, leftvertex);
08337 apex(horiz, botvertex);
08338 setorg(newbotright, botvertex);
08339 setdest(newbotright, rightvertex);
08340 setapex(newbotright, newvertex);
08341 setorg(horiz, newvertex);
08342 for (i = 0; i < m->eextras; i++) {
08343
08344 setelemattribute(newbotright, i, elemattribute(botright, i));
08345 }
08346 if (b->vararea) {
08347
08348 setareabound(newbotright, areabound(botright));
08349 }
08350 if (mirrorflag) {
08351 dest(topright, topvertex);
08352 setorg(newtopright, rightvertex);
08353 setdest(newtopright, topvertex);
08354 setapex(newtopright, newvertex);
08355 setorg(topright, newvertex);
08356 for (i = 0; i < m->eextras; i++) {
08357
08358 setelemattribute(newtopright, i, elemattribute(topright, i));
08359 }
08360 if (b->vararea) {
08361
08362 setareabound(newtopright, areabound(topright));
08363 }
08364 }
08365
08366
08367
08368 if (m->checksegments) {
08369 tspivot(botright, botrsubseg);
08370 if (botrsubseg.ss != m->dummysub) {
08371 tsdissolve(botright);
08372 tsbond(newbotright, botrsubseg);
08373 }
08374 if (mirrorflag) {
08375 tspivot(topright, toprsubseg);
08376 if (toprsubseg.ss != m->dummysub) {
08377 tsdissolve(topright);
08378 tsbond(newtopright, toprsubseg);
08379 }
08380 }
08381 }
08382
08383
08384 bond(newbotright, botrcasing);
08385 lprevself(newbotright);
08386 bond(newbotright, botright);
08387 lprevself(newbotright);
08388 if (mirrorflag) {
08389 bond(newtopright, toprcasing);
08390 lnextself(newtopright);
08391 bond(newtopright, topright);
08392 lnextself(newtopright);
08393 bond(newtopright, newbotright);
08394 }
08395
08396 if (splitseg != (struct osub *) NULL) {
08397
08398 setsdest(*splitseg, newvertex);
08399 segorg(*splitseg, segmentorg);
08400 segdest(*splitseg, segmentdest);
08401 ssymself(*splitseg);
08402 spivot(*splitseg, rightsubseg);
08403 insertsubseg(m, b, &newbotright, mark(*splitseg));
08404 tspivot(newbotright, newsubseg);
08405 setsegorg(newsubseg, segmentorg);
08406 setsegdest(newsubseg, segmentdest);
08407 sbond(*splitseg, newsubseg);
08408 ssymself(newsubseg);
08409 sbond(newsubseg, rightsubseg);
08410 ssymself(*splitseg);
08411
08412
08413 if (vertexmark(newvertex) == 0) {
08414 setvertexmark(newvertex, mark(*splitseg));
08415 }
08416 }
08417
08418 if (m->checkquality) {
08419 poolrestart(&m->flipstackers);
08420 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08421 m->lastflip->flippedtri = encode(horiz);
08422 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
08423 }
08424
08425 #ifdef SELF_CHECK
08426 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08427 printf("Internal error in insertvertex():\n");
08428 printf(
08429 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
08430 }
08431 if (mirrorflag) {
08432 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
08433 printf("Internal error in insertvertex():\n");
08434 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
08435 }
08436 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
08437 printf("Internal error in insertvertex():\n");
08438 printf(
08439 " Clockwise triangle after edge vertex insertion (top right).\n");
08440 }
08441 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
08442 printf("Internal error in insertvertex():\n");
08443 printf(
08444 " Clockwise triangle after edge vertex insertion (top left).\n");
08445 }
08446 }
08447 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08448 printf("Internal error in insertvertex():\n");
08449 printf(
08450 " Clockwise triangle after edge vertex insertion (bottom left).\n");
08451 }
08452 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08453 printf("Internal error in insertvertex():\n");
08454 printf(
08455 " Clockwise triangle after edge vertex insertion (bottom right).\n");
08456 }
08457 #endif
08458 if (b->verbose > 2) {
08459 printf(" Updating bottom left ");
08460 printtriangle(m, b, &botright);
08461 if (mirrorflag) {
08462 printf(" Updating top left ");
08463 printtriangle(m, b, &topright);
08464 printf(" Creating top right ");
08465 printtriangle(m, b, &newtopright);
08466 }
08467 printf(" Creating bottom right ");
08468 printtriangle(m, b, &newbotright);
08469 }
08470
08471
08472
08473 lnextself(horiz);
08474 } else {
08475
08476 lnext(horiz, botleft);
08477 lprev(horiz, botright);
08478 sym(botleft, botlcasing);
08479 sym(botright, botrcasing);
08480 maketriangle(m, b, &newbotleft);
08481 maketriangle(m, b, &newbotright);
08482
08483
08484 org(horiz, rightvertex);
08485 dest(horiz, leftvertex);
08486 apex(horiz, botvertex);
08487 setorg(newbotleft, leftvertex);
08488 setdest(newbotleft, botvertex);
08489 setapex(newbotleft, newvertex);
08490 setorg(newbotright, botvertex);
08491 setdest(newbotright, rightvertex);
08492 setapex(newbotright, newvertex);
08493 setapex(horiz, newvertex);
08494 for (i = 0; i < m->eextras; i++) {
08495
08496 attrib = elemattribute(horiz, i);
08497 setelemattribute(newbotleft, i, attrib);
08498 setelemattribute(newbotright, i, attrib);
08499 }
08500 if (b->vararea) {
08501
08502 area = areabound(horiz);
08503 setareabound(newbotleft, area);
08504 setareabound(newbotright, area);
08505 }
08506
08507
08508
08509 if (m->checksegments) {
08510 tspivot(botleft, botlsubseg);
08511 if (botlsubseg.ss != m->dummysub) {
08512 tsdissolve(botleft);
08513 tsbond(newbotleft, botlsubseg);
08514 }
08515 tspivot(botright, botrsubseg);
08516 if (botrsubseg.ss != m->dummysub) {
08517 tsdissolve(botright);
08518 tsbond(newbotright, botrsubseg);
08519 }
08520 }
08521
08522
08523 bond(newbotleft, botlcasing);
08524 bond(newbotright, botrcasing);
08525 lnextself(newbotleft);
08526 lprevself(newbotright);
08527 bond(newbotleft, newbotright);
08528 lnextself(newbotleft);
08529 bond(botleft, newbotleft);
08530 lprevself(newbotright);
08531 bond(botright, newbotright);
08532
08533 if (m->checkquality) {
08534 poolrestart(&m->flipstackers);
08535 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08536 m->lastflip->flippedtri = encode(horiz);
08537 m->lastflip->prevflip = (struct flipstacker *) NULL;
08538 }
08539
08540 #ifdef SELF_CHECK
08541 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08542 printf("Internal error in insertvertex():\n");
08543 printf(" Clockwise triangle prior to vertex insertion.\n");
08544 }
08545 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
08546 printf("Internal error in insertvertex():\n");
08547 printf(" Clockwise triangle after vertex insertion (top).\n");
08548 }
08549 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08550 printf("Internal error in insertvertex():\n");
08551 printf(" Clockwise triangle after vertex insertion (left).\n");
08552 }
08553 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08554 printf("Internal error in insertvertex():\n");
08555 printf(" Clockwise triangle after vertex insertion (right).\n");
08556 }
08557 #endif
08558 if (b->verbose > 2) {
08559 printf(" Updating top ");
08560 printtriangle(m, b, &horiz);
08561 printf(" Creating left ");
08562 printtriangle(m, b, &newbotleft);
08563 printf(" Creating right ");
08564 printtriangle(m, b, &newbotright);
08565 }
08566 }
08567
08568
08569
08570 success = SUCCESSFULVERTEX;
08571
08572
08573
08574
08575 org(horiz, first);
08576 rightvertex = first;
08577 dest(horiz, leftvertex);
08578
08579 while (1) {
08580
08581 doflip = 1;
08582
08583 if (m->checksegments) {
08584
08585 tspivot(horiz, checksubseg);
08586 if (checksubseg.ss != m->dummysub) {
08587
08588 doflip = 0;
08589 #ifndef CDT_ONLY
08590 if (segmentflaws) {
08591
08592 if (checkseg4encroach(m, b, &checksubseg)) {
08593 success = ENCROACHINGVERTEX;
08594 }
08595 }
08596 #endif
08597 }
08598 }
08599
08600 if (doflip) {
08601
08602 sym(horiz, top);
08603 if (top.tri == m->dummytri) {
08604
08605 doflip = 0;
08606 } else {
08607
08608 apex(top, farvertex);
08609
08610
08611
08612
08613
08614 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
08615 (leftvertex == m->infvertex3)) {
08616
08617
08618
08619
08620 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
08621 > 0.0;
08622 } else if ((rightvertex == m->infvertex1) ||
08623 (rightvertex == m->infvertex2) ||
08624 (rightvertex == m->infvertex3)) {
08625
08626
08627
08628
08629 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
08630 > 0.0;
08631 } else if ((farvertex == m->infvertex1) ||
08632 (farvertex == m->infvertex2) ||
08633 (farvertex == m->infvertex3)) {
08634
08635
08636 doflip = 0;
08637 } else {
08638
08639 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
08640 farvertex) > 0.0;
08641 }
08642 if (doflip) {
08643
08644
08645
08646 lprev(top, topleft);
08647 sym(topleft, toplcasing);
08648 lnext(top, topright);
08649 sym(topright, toprcasing);
08650 lnext(horiz, botleft);
08651 sym(botleft, botlcasing);
08652 lprev(horiz, botright);
08653 sym(botright, botrcasing);
08654
08655 bond(topleft, botlcasing);
08656 bond(botleft, botrcasing);
08657 bond(botright, toprcasing);
08658 bond(topright, toplcasing);
08659 if (m->checksegments) {
08660
08661 tspivot(topleft, toplsubseg);
08662 tspivot(botleft, botlsubseg);
08663 tspivot(botright, botrsubseg);
08664 tspivot(topright, toprsubseg);
08665 if (toplsubseg.ss == m->dummysub) {
08666 tsdissolve(topright);
08667 } else {
08668 tsbond(topright, toplsubseg);
08669 }
08670 if (botlsubseg.ss == m->dummysub) {
08671 tsdissolve(topleft);
08672 } else {
08673 tsbond(topleft, botlsubseg);
08674 }
08675 if (botrsubseg.ss == m->dummysub) {
08676 tsdissolve(botleft);
08677 } else {
08678 tsbond(botleft, botrsubseg);
08679 }
08680 if (toprsubseg.ss == m->dummysub) {
08681 tsdissolve(botright);
08682 } else {
08683 tsbond(botright, toprsubseg);
08684 }
08685 }
08686
08687 setorg(horiz, farvertex);
08688 setdest(horiz, newvertex);
08689 setapex(horiz, rightvertex);
08690 setorg(top, newvertex);
08691 setdest(top, farvertex);
08692 setapex(top, leftvertex);
08693 for (i = 0; i < m->eextras; i++) {
08694
08695 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
08696 setelemattribute(top, i, attrib);
08697 setelemattribute(horiz, i, attrib);
08698 }
08699 if (b->vararea) {
08700 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
08701 area = -1.0;
08702 } else {
08703
08704
08705
08706 area = 0.5 * (areabound(top) + areabound(horiz));
08707 }
08708 setareabound(top, area);
08709 setareabound(horiz, area);
08710 }
08711
08712 if (m->checkquality) {
08713 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08714 newflip->flippedtri = encode(horiz);
08715 newflip->prevflip = m->lastflip;
08716 m->lastflip = newflip;
08717 }
08718
08719 #ifdef SELF_CHECK
08720 if (newvertex != (vertex) NULL) {
08721 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
08722 0.0) {
08723 printf("Internal error in insertvertex():\n");
08724 printf(" Clockwise triangle prior to edge flip (bottom).\n");
08725 }
08726
08727
08728
08729
08730
08731
08732
08733
08734
08735
08736 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
08737 0.0) {
08738 printf("Internal error in insertvertex():\n");
08739 printf(" Clockwise triangle after edge flip (left).\n");
08740 }
08741 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
08742 0.0) {
08743 printf("Internal error in insertvertex():\n");
08744 printf(" Clockwise triangle after edge flip (right).\n");
08745 }
08746 }
08747 #endif
08748 if (b->verbose > 2) {
08749 printf(" Edge flip results in left ");
08750 lnextself(topleft);
08751 printtriangle(m, b, &topleft);
08752 printf(" and right ");
08753 printtriangle(m, b, &horiz);
08754 }
08755
08756
08757
08758 lprevself(horiz);
08759 leftvertex = farvertex;
08760 }
08761 }
08762 }
08763 if (!doflip) {
08764
08765 #ifndef CDT_ONLY
08766 if (triflaws) {
08767
08768 testtriangle(m, b, &horiz);
08769 }
08770 #endif
08771
08772 lnextself(horiz);
08773 sym(horiz, testtri);
08774
08775
08776
08777 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
08778
08779 lnext(horiz, *searchtri);
08780 lnext(horiz, m->recenttri);
08781 return success;
08782 }
08783
08784 lnext(testtri, horiz);
08785 rightvertex = leftvertex;
08786 dest(horiz, leftvertex);
08787 }
08788 }
08789 }
08790
08791
08792
08793
08794
08795
08796
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822
08823
08824
08825
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837
08838
08839
08840
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852
08853
08854
08855 #ifdef ANSI_DECLARATORS
08856 void triangulatepolygon(struct mesh *m, struct behavior *b,
08857 struct otri *firstedge, struct otri *lastedge,
08858 int edgecount, int doflip, int triflaws)
08859 #else
08860 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
08861 struct mesh *m;
08862 struct behavior *b;
08863 struct otri *firstedge;
08864 struct otri *lastedge;
08865 int edgecount;
08866 int doflip;
08867 int triflaws;
08868 #endif
08869
08870 {
08871 struct otri testtri;
08872 struct otri besttri;
08873 struct otri tempedge;
08874 vertex leftbasevertex, rightbasevertex;
08875 vertex testvertex;
08876 vertex bestvertex;
08877 int bestnumber;
08878 int i;
08879 triangle ptr;
08880
08881
08882 apex(*lastedge, leftbasevertex);
08883 dest(*firstedge, rightbasevertex);
08884 if (b->verbose > 2) {
08885 printf(" Triangulating interior polygon at edge\n");
08886 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
08887 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
08888 }
08889
08890 onext(*firstedge, besttri);
08891 dest(besttri, bestvertex);
08892 otricopy(besttri, testtri);
08893 bestnumber = 1;
08894 for (i = 2; i <= edgecount - 2; i++) {
08895 onextself(testtri);
08896 dest(testtri, testvertex);
08897
08898 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
08899 testvertex) > 0.0) {
08900 otricopy(testtri, besttri);
08901 bestvertex = testvertex;
08902 bestnumber = i;
08903 }
08904 }
08905 if (b->verbose > 2) {
08906 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
08907 bestvertex[1]);
08908 }
08909 if (bestnumber > 1) {
08910
08911 oprev(besttri, tempedge);
08912 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
08913 triflaws);
08914 }
08915 if (bestnumber < edgecount - 2) {
08916
08917 sym(besttri, tempedge);
08918 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
08919 triflaws);
08920
08921 sym(tempedge, besttri);
08922 }
08923 if (doflip) {
08924
08925 flip(m, b, &besttri);
08926 #ifndef CDT_ONLY
08927 if (triflaws) {
08928
08929 sym(besttri, testtri);
08930 testtriangle(m, b, &testtri);
08931 }
08932 #endif
08933 }
08934
08935 otricopy(besttri, *lastedge);
08936 }
08937
08938
08939
08940
08941
08942
08943
08944
08945
08946
08947
08948
08949
08950
08951
08952 #ifndef CDT_ONLY
08953
08954 #ifdef ANSI_DECLARATORS
08955 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
08956 #else
08957 void deletevertex(m, b, deltri)
08958 struct mesh *m;
08959 struct behavior *b;
08960 struct otri *deltri;
08961 #endif
08962
08963 {
08964 struct otri countingtri;
08965 struct otri firstedge, lastedge;
08966 struct otri deltriright;
08967 struct otri lefttri, righttri;
08968 struct otri leftcasing, rightcasing;
08969 struct osub leftsubseg, rightsubseg;
08970 vertex delvertex;
08971 vertex neworg;
08972 int edgecount;
08973 triangle ptr;
08974 subseg sptr;
08975
08976 org(*deltri, delvertex);
08977 if (b->verbose > 1) {
08978 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
08979 }
08980 vertexdealloc(m, delvertex);
08981
08982
08983 onext(*deltri, countingtri);
08984 edgecount = 1;
08985 while (!otriequal(*deltri, countingtri)) {
08986 #ifdef SELF_CHECK
08987 if (countingtri.tri == m->dummytri) {
08988 printf("Internal error in deletevertex():\n");
08989 printf(" Attempt to delete boundary vertex.\n");
08990 internalerror();
08991 }
08992 #endif
08993 edgecount++;
08994 onextself(countingtri);
08995 }
08996
08997 #ifdef SELF_CHECK
08998 if (edgecount < 3) {
08999 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
09000 edgecount);
09001 internalerror();
09002 }
09003 #endif
09004 if (edgecount > 3) {
09005
09006
09007
09008 onext(*deltri, firstedge);
09009 oprev(*deltri, lastedge);
09010 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
09011 !b->nobisect);
09012 }
09013
09014 lprev(*deltri, deltriright);
09015 dnext(*deltri, lefttri);
09016 sym(lefttri, leftcasing);
09017 oprev(deltriright, righttri);
09018 sym(righttri, rightcasing);
09019 bond(*deltri, leftcasing);
09020 bond(deltriright, rightcasing);
09021 tspivot(lefttri, leftsubseg);
09022 if (leftsubseg.ss != m->dummysub) {
09023 tsbond(*deltri, leftsubseg);
09024 }
09025 tspivot(righttri, rightsubseg);
09026 if (rightsubseg.ss != m->dummysub) {
09027 tsbond(deltriright, rightsubseg);
09028 }
09029
09030
09031 org(lefttri, neworg);
09032 setorg(*deltri, neworg);
09033 if (!b->nobisect) {
09034 testtriangle(m, b, deltri);
09035 }
09036
09037
09038 triangledealloc(m, lefttri.tri);
09039 triangledealloc(m, righttri.tri);
09040 }
09041
09042 #endif
09043
09044
09045
09046
09047
09048
09049
09050
09051
09052
09053
09054
09055 #ifndef CDT_ONLY
09056
09057 #ifdef ANSI_DECLARATORS
09058 void undovertex(struct mesh *m, struct behavior *b)
09059 #else
09060 void undovertex(m, b)
09061 struct mesh *m;
09062 struct behavior *b;
09063 #endif
09064
09065 {
09066 struct otri fliptri;
09067 struct otri botleft, botright, topright;
09068 struct otri botlcasing, botrcasing, toprcasing;
09069 struct otri gluetri;
09070 struct osub botlsubseg, botrsubseg, toprsubseg;
09071 vertex botvertex, rightvertex;
09072 triangle ptr;
09073 subseg sptr;
09074
09075
09076
09077 while (m->lastflip != (struct flipstacker *) NULL) {
09078
09079 decode(m->lastflip->flippedtri, fliptri);
09080
09081
09082
09083
09084
09085 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
09086
09087
09088 dprev(fliptri, botleft);
09089 lnextself(botleft);
09090 onext(fliptri, botright);
09091 lprevself(botright);
09092 sym(botleft, botlcasing);
09093 sym(botright, botrcasing);
09094 dest(botleft, botvertex);
09095
09096 setapex(fliptri, botvertex);
09097 lnextself(fliptri);
09098 bond(fliptri, botlcasing);
09099 tspivot(botleft, botlsubseg);
09100 tsbond(fliptri, botlsubseg);
09101 lnextself(fliptri);
09102 bond(fliptri, botrcasing);
09103 tspivot(botright, botrsubseg);
09104 tsbond(fliptri, botrsubseg);
09105
09106
09107 triangledealloc(m, botleft.tri);
09108 triangledealloc(m, botright.tri);
09109 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
09110
09111
09112 lprev(fliptri, gluetri);
09113 sym(gluetri, botright);
09114 lnextself(botright);
09115 sym(botright, botrcasing);
09116 dest(botright, rightvertex);
09117
09118 setorg(fliptri, rightvertex);
09119 bond(gluetri, botrcasing);
09120 tspivot(botright, botrsubseg);
09121 tsbond(gluetri, botrsubseg);
09122
09123
09124 triangledealloc(m, botright.tri);
09125
09126 sym(fliptri, gluetri);
09127 if (gluetri.tri != m->dummytri) {
09128 lnextself(gluetri);
09129 dnext(gluetri, topright);
09130 sym(topright, toprcasing);
09131
09132 setorg(gluetri, rightvertex);
09133 bond(gluetri, toprcasing);
09134 tspivot(topright, toprsubseg);
09135 tsbond(gluetri, toprsubseg);
09136
09137
09138 triangledealloc(m, topright.tri);
09139 }
09140
09141
09142 m->lastflip->prevflip = (struct flipstacker *) NULL;
09143 } else {
09144
09145 unflip(m, b, &fliptri);
09146 }
09147
09148
09149 m->lastflip = m->lastflip->prevflip;
09150 }
09151 }
09152
09153 #endif
09154
09157
09158
09159
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172
09173
09174
09175
09176
09177
09178
09179
09180
09181
09182
09183
09184
09185
09186
09187
09188
09189
09190
09191
09192
09193
09194
09195
09196
09197
09198
09199
09200
09201
09202
09203
09204 #ifdef ANSI_DECLARATORS
09205 void vertexsort(vertex *sortarray, int arraysize)
09206 #else
09207 void vertexsort(sortarray, arraysize)
09208 vertex *sortarray;
09209 int arraysize;
09210 #endif
09211
09212 {
09213 int left, right;
09214 int pivot;
09215 REAL pivotx, pivoty;
09216 vertex temp;
09217
09218 if (arraysize == 2) {
09219
09220 if ((sortarray[0][0] > sortarray[1][0]) ||
09221 ((sortarray[0][0] == sortarray[1][0]) &&
09222 (sortarray[0][1] > sortarray[1][1]))) {
09223 temp = sortarray[1];
09224 sortarray[1] = sortarray[0];
09225 sortarray[0] = temp;
09226 }
09227 return;
09228 }
09229
09230 pivot = (int) randomnation((unsigned int) arraysize);
09231 pivotx = sortarray[pivot][0];
09232 pivoty = sortarray[pivot][1];
09233
09234 left = -1;
09235 right = arraysize;
09236 while (left < right) {
09237
09238 do {
09239 left++;
09240 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
09241 ((sortarray[left][0] == pivotx) &&
09242 (sortarray[left][1] < pivoty))));
09243
09244 do {
09245 right--;
09246 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
09247 ((sortarray[right][0] == pivotx) &&
09248 (sortarray[right][1] > pivoty))));
09249 if (left < right) {
09250
09251 temp = sortarray[left];
09252 sortarray[left] = sortarray[right];
09253 sortarray[right] = temp;
09254 }
09255 }
09256 if (left > 1) {
09257
09258 vertexsort(sortarray, left);
09259 }
09260 if (right < arraysize - 2) {
09261
09262 vertexsort(&sortarray[right + 1], arraysize - right - 1);
09263 }
09264 }
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278 #ifdef ANSI_DECLARATORS
09279 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
09280 #else
09281 void vertexmedian(sortarray, arraysize, median, axis)
09282 vertex *sortarray;
09283 int arraysize;
09284 int median;
09285 int axis;
09286 #endif
09287
09288 {
09289 int left, right;
09290 int pivot;
09291 REAL pivot1, pivot2;
09292 vertex temp;
09293
09294 if (arraysize == 2) {
09295
09296 if ((sortarray[0][axis] > sortarray[1][axis]) ||
09297 ((sortarray[0][axis] == sortarray[1][axis]) &&
09298 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
09299 temp = sortarray[1];
09300 sortarray[1] = sortarray[0];
09301 sortarray[0] = temp;
09302 }
09303 return;
09304 }
09305
09306 pivot = (int) randomnation((unsigned int) arraysize);
09307 pivot1 = sortarray[pivot][axis];
09308 pivot2 = sortarray[pivot][1 - axis];
09309
09310 left = -1;
09311 right = arraysize;
09312 while (left < right) {
09313
09314 do {
09315 left++;
09316 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
09317 ((sortarray[left][axis] == pivot1) &&
09318 (sortarray[left][1 - axis] < pivot2))));
09319
09320 do {
09321 right--;
09322 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
09323 ((sortarray[right][axis] == pivot1) &&
09324 (sortarray[right][1 - axis] > pivot2))));
09325 if (left < right) {
09326
09327 temp = sortarray[left];
09328 sortarray[left] = sortarray[right];
09329 sortarray[right] = temp;
09330 }
09331 }
09332
09333
09334 if (left > median) {
09335
09336 vertexmedian(sortarray, left, median, axis);
09337 }
09338 if (right < median - 1) {
09339
09340 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
09341 median - right - 1, axis);
09342 }
09343 }
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353
09354
09355
09356 #ifdef ANSI_DECLARATORS
09357 void alternateaxes(vertex *sortarray, int arraysize, int axis)
09358 #else
09359 void alternateaxes(sortarray, arraysize, axis)
09360 vertex *sortarray;
09361 int arraysize;
09362 int axis;
09363 #endif
09364
09365 {
09366 int divider;
09367
09368 divider = arraysize >> 1;
09369 if (arraysize <= 3) {
09370
09371
09372 axis = 0;
09373 }
09374
09375 vertexmedian(sortarray, arraysize, divider, axis);
09376
09377 if (arraysize - divider >= 2) {
09378 if (divider >= 2) {
09379 alternateaxes(sortarray, divider, 1 - axis);
09380 }
09381 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
09382 }
09383 }
09384
09385
09386
09387
09388
09389
09390
09391
09392
09393
09394
09395
09396
09397
09398
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
09409
09410
09411
09412
09413
09414
09415
09416
09417
09418
09419
09420 #ifdef ANSI_DECLARATORS
09421 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
09422 struct otri *innerleft, struct otri *innerright,
09423 struct otri *farright, int axis)
09424 #else
09425 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
09426 struct mesh *m;
09427 struct behavior *b;
09428 struct otri *farleft;
09429 struct otri *innerleft;
09430 struct otri *innerright;
09431 struct otri *farright;
09432 int axis;
09433 #endif
09434
09435 {
09436 struct otri leftcand, rightcand;
09437 struct otri baseedge;
09438 struct otri nextedge;
09439 struct otri sidecasing, topcasing, outercasing;
09440 struct otri checkedge;
09441 vertex innerleftdest;
09442 vertex innerrightorg;
09443 vertex innerleftapex, innerrightapex;
09444 vertex farleftpt, farrightpt;
09445 vertex farleftapex, farrightapex;
09446 vertex lowerleft, lowerright;
09447 vertex upperleft, upperright;
09448 vertex nextapex;
09449 vertex checkvertex;
09450 int changemade;
09451 int badedge;
09452 int leftfinished, rightfinished;
09453 triangle ptr;
09454
09455 dest(*innerleft, innerleftdest);
09456 apex(*innerleft, innerleftapex);
09457 org(*innerright, innerrightorg);
09458 apex(*innerright, innerrightapex);
09459
09460 if (b->dwyer && (axis == 1)) {
09461 org(*farleft, farleftpt);
09462 apex(*farleft, farleftapex);
09463 dest(*farright, farrightpt);
09464 apex(*farright, farrightapex);
09465
09466
09467
09468 while (farleftapex[1] < farleftpt[1]) {
09469 lnextself(*farleft);
09470 symself(*farleft);
09471 farleftpt = farleftapex;
09472 apex(*farleft, farleftapex);
09473 }
09474 sym(*innerleft, checkedge);
09475 apex(checkedge, checkvertex);
09476 while (checkvertex[1] > innerleftdest[1]) {
09477 lnext(checkedge, *innerleft);
09478 innerleftapex = innerleftdest;
09479 innerleftdest = checkvertex;
09480 sym(*innerleft, checkedge);
09481 apex(checkedge, checkvertex);
09482 }
09483 while (innerrightapex[1] < innerrightorg[1]) {
09484 lnextself(*innerright);
09485 symself(*innerright);
09486 innerrightorg = innerrightapex;
09487 apex(*innerright, innerrightapex);
09488 }
09489 sym(*farright, checkedge);
09490 apex(checkedge, checkvertex);
09491 while (checkvertex[1] > farrightpt[1]) {
09492 lnext(checkedge, *farright);
09493 farrightapex = farrightpt;
09494 farrightpt = checkvertex;
09495 sym(*farright, checkedge);
09496 apex(checkedge, checkvertex);
09497 }
09498 }
09499
09500 do {
09501 changemade = 0;
09502
09503 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
09504 0.0) {
09505 lprevself(*innerleft);
09506 symself(*innerleft);
09507 innerleftdest = innerleftapex;
09508 apex(*innerleft, innerleftapex);
09509 changemade = 1;
09510 }
09511
09512 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
09513 0.0) {
09514 lnextself(*innerright);
09515 symself(*innerright);
09516 innerrightorg = innerrightapex;
09517 apex(*innerright, innerrightapex);
09518 changemade = 1;
09519 }
09520 } while (changemade);
09521
09522 sym(*innerleft, leftcand);
09523 sym(*innerright, rightcand);
09524
09525 maketriangle(m, b, &baseedge);
09526
09527 bond(baseedge, *innerleft);
09528 lnextself(baseedge);
09529 bond(baseedge, *innerright);
09530 lnextself(baseedge);
09531 setorg(baseedge, innerrightorg);
09532 setdest(baseedge, innerleftdest);
09533
09534 if (b->verbose > 2) {
09535 printf(" Creating base bounding ");
09536 printtriangle(m, b, &baseedge);
09537 }
09538
09539 org(*farleft, farleftpt);
09540 if (innerleftdest == farleftpt) {
09541 lnext(baseedge, *farleft);
09542 }
09543 dest(*farright, farrightpt);
09544 if (innerrightorg == farrightpt) {
09545 lprev(baseedge, *farright);
09546 }
09547
09548 lowerleft = innerleftdest;
09549 lowerright = innerrightorg;
09550
09551 apex(leftcand, upperleft);
09552 apex(rightcand, upperright);
09553
09554 while (1) {
09555
09556
09557
09558
09559 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
09560 0.0;
09561 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
09562 <= 0.0;
09563 if (leftfinished && rightfinished) {
09564
09565 maketriangle(m, b, &nextedge);
09566 setorg(nextedge, lowerleft);
09567 setdest(nextedge, lowerright);
09568
09569
09570 bond(nextedge, baseedge);
09571 lnextself(nextedge);
09572 bond(nextedge, rightcand);
09573 lnextself(nextedge);
09574 bond(nextedge, leftcand);
09575 if (b->verbose > 2) {
09576 printf(" Creating top bounding ");
09577 printtriangle(m, b, &nextedge);
09578 }
09579
09580 if (b->dwyer && (axis == 1)) {
09581 org(*farleft, farleftpt);
09582 apex(*farleft, farleftapex);
09583 dest(*farright, farrightpt);
09584 apex(*farright, farrightapex);
09585 sym(*farleft, checkedge);
09586 apex(checkedge, checkvertex);
09587
09588
09589
09590 while (checkvertex[0] < farleftpt[0]) {
09591 lprev(checkedge, *farleft);
09592 farleftapex = farleftpt;
09593 farleftpt = checkvertex;
09594 sym(*farleft, checkedge);
09595 apex(checkedge, checkvertex);
09596 }
09597 while (farrightapex[0] > farrightpt[0]) {
09598 lprevself(*farright);
09599 symself(*farright);
09600 farrightpt = farrightapex;
09601 apex(*farright, farrightapex);
09602 }
09603 }
09604 return;
09605 }
09606
09607 if (!leftfinished) {
09608
09609 lprev(leftcand, nextedge);
09610 symself(nextedge);
09611 apex(nextedge, nextapex);
09612
09613
09614 if (nextapex != (vertex) NULL) {
09615
09616 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
09617 0.0;
09618 while (badedge) {
09619
09620
09621 lnextself(nextedge);
09622 sym(nextedge, topcasing);
09623 lnextself(nextedge);
09624 sym(nextedge, sidecasing);
09625 bond(nextedge, topcasing);
09626 bond(leftcand, sidecasing);
09627 lnextself(leftcand);
09628 sym(leftcand, outercasing);
09629 lprevself(nextedge);
09630 bond(nextedge, outercasing);
09631
09632 setorg(leftcand, lowerleft);
09633 setdest(leftcand, NULL);
09634 setapex(leftcand, nextapex);
09635 setorg(nextedge, NULL);
09636 setdest(nextedge, upperleft);
09637 setapex(nextedge, nextapex);
09638
09639 upperleft = nextapex;
09640
09641 otricopy(sidecasing, nextedge);
09642 apex(nextedge, nextapex);
09643 if (nextapex != (vertex) NULL) {
09644
09645 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
09646 nextapex) > 0.0;
09647 } else {
09648
09649 badedge = 0;
09650 }
09651 }
09652 }
09653 }
09654
09655 if (!rightfinished) {
09656
09657 lnext(rightcand, nextedge);
09658 symself(nextedge);
09659 apex(nextedge, nextapex);
09660
09661
09662 if (nextapex != (vertex) NULL) {
09663
09664 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
09665 0.0;
09666 while (badedge) {
09667
09668
09669 lprevself(nextedge);
09670 sym(nextedge, topcasing);
09671 lprevself(nextedge);
09672 sym(nextedge, sidecasing);
09673 bond(nextedge, topcasing);
09674 bond(rightcand, sidecasing);
09675 lprevself(rightcand);
09676 sym(rightcand, outercasing);
09677 lnextself(nextedge);
09678 bond(nextedge, outercasing);
09679
09680 setorg(rightcand, NULL);
09681 setdest(rightcand, lowerright);
09682 setapex(rightcand, nextapex);
09683 setorg(nextedge, upperright);
09684 setdest(nextedge, NULL);
09685 setapex(nextedge, nextapex);
09686
09687 upperright = nextapex;
09688
09689 otricopy(sidecasing, nextedge);
09690 apex(nextedge, nextapex);
09691 if (nextapex != (vertex) NULL) {
09692
09693 badedge = incircle(m, b, lowerleft, lowerright, upperright,
09694 nextapex) > 0.0;
09695 } else {
09696
09697 badedge = 0;
09698 }
09699 }
09700 }
09701 }
09702 if (leftfinished || (!rightfinished &&
09703 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
09704 0.0))) {
09705
09706
09707 bond(baseedge, rightcand);
09708 lprev(rightcand, baseedge);
09709 setdest(baseedge, lowerleft);
09710 lowerright = upperright;
09711 sym(baseedge, rightcand);
09712 apex(rightcand, upperright);
09713 } else {
09714
09715
09716 bond(baseedge, leftcand);
09717 lnext(leftcand, baseedge);
09718 setorg(baseedge, lowerright);
09719 lowerleft = upperleft;
09720 sym(baseedge, leftcand);
09721 apex(leftcand, upperleft);
09722 }
09723 if (b->verbose > 2) {
09724 printf(" Connecting ");
09725 printtriangle(m, b, &baseedge);
09726 }
09727 }
09728 }
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744
09745
09746
09747 #ifdef ANSI_DECLARATORS
09748 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
09749 int vertices, int axis,
09750 struct otri *farleft, struct otri *farright)
09751 #else
09752 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
09753 struct mesh *m;
09754 struct behavior *b;
09755 vertex *sortarray;
09756 int vertices;
09757 int axis;
09758 struct otri *farleft;
09759 struct otri *farright;
09760 #endif
09761
09762 {
09763 struct otri midtri, tri1, tri2, tri3;
09764 struct otri innerleft, innerright;
09765 REAL area;
09766 int divider;
09767
09768 if (b->verbose > 2) {
09769 printf(" Triangulating %d vertices.\n", vertices);
09770 }
09771 if (vertices == 2) {
09772
09773
09774 maketriangle(m, b, farleft);
09775 setorg(*farleft, sortarray[0]);
09776 setdest(*farleft, sortarray[1]);
09777
09778 maketriangle(m, b, farright);
09779 setorg(*farright, sortarray[1]);
09780 setdest(*farright, sortarray[0]);
09781
09782 bond(*farleft, *farright);
09783 lprevself(*farleft);
09784 lnextself(*farright);
09785 bond(*farleft, *farright);
09786 lprevself(*farleft);
09787 lnextself(*farright);
09788 bond(*farleft, *farright);
09789 if (b->verbose > 2) {
09790 printf(" Creating ");
09791 printtriangle(m, b, farleft);
09792 printf(" Creating ");
09793 printtriangle(m, b, farright);
09794 }
09795
09796 lprev(*farright, *farleft);
09797 return;
09798 } else if (vertices == 3) {
09799
09800
09801
09802 maketriangle(m, b, &midtri);
09803 maketriangle(m, b, &tri1);
09804 maketriangle(m, b, &tri2);
09805 maketriangle(m, b, &tri3);
09806 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
09807 if (area == 0.0) {
09808
09809 setorg(midtri, sortarray[0]);
09810 setdest(midtri, sortarray[1]);
09811 setorg(tri1, sortarray[1]);
09812 setdest(tri1, sortarray[0]);
09813 setorg(tri2, sortarray[2]);
09814 setdest(tri2, sortarray[1]);
09815 setorg(tri3, sortarray[1]);
09816 setdest(tri3, sortarray[2]);
09817
09818 bond(midtri, tri1);
09819 bond(tri2, tri3);
09820 lnextself(midtri);
09821 lprevself(tri1);
09822 lnextself(tri2);
09823 lprevself(tri3);
09824 bond(midtri, tri3);
09825 bond(tri1, tri2);
09826 lnextself(midtri);
09827 lprevself(tri1);
09828 lnextself(tri2);
09829 lprevself(tri3);
09830 bond(midtri, tri1);
09831 bond(tri2, tri3);
09832
09833 otricopy(tri1, *farleft);
09834
09835 otricopy(tri2, *farright);
09836 } else {
09837
09838
09839 setorg(midtri, sortarray[0]);
09840 setdest(tri1, sortarray[0]);
09841 setorg(tri3, sortarray[0]);
09842
09843 if (area > 0.0) {
09844
09845 setdest(midtri, sortarray[1]);
09846 setorg(tri1, sortarray[1]);
09847 setdest(tri2, sortarray[1]);
09848 setapex(midtri, sortarray[2]);
09849 setorg(tri2, sortarray[2]);
09850 setdest(tri3, sortarray[2]);
09851 } else {
09852
09853 setdest(midtri, sortarray[2]);
09854 setorg(tri1, sortarray[2]);
09855 setdest(tri2, sortarray[2]);
09856 setapex(midtri, sortarray[1]);
09857 setorg(tri2, sortarray[1]);
09858 setdest(tri3, sortarray[1]);
09859 }
09860
09861 bond(midtri, tri1);
09862 lnextself(midtri);
09863 bond(midtri, tri2);
09864 lnextself(midtri);
09865 bond(midtri, tri3);
09866 lprevself(tri1);
09867 lnextself(tri2);
09868 bond(tri1, tri2);
09869 lprevself(tri1);
09870 lprevself(tri3);
09871 bond(tri1, tri3);
09872 lnextself(tri2);
09873 lprevself(tri3);
09874 bond(tri2, tri3);
09875
09876 otricopy(tri1, *farleft);
09877
09878 if (area > 0.0) {
09879 otricopy(tri2, *farright);
09880 } else {
09881 lnext(*farleft, *farright);
09882 }
09883 }
09884 if (b->verbose > 2) {
09885 printf(" Creating ");
09886 printtriangle(m, b, &midtri);
09887 printf(" Creating ");
09888 printtriangle(m, b, &tri1);
09889 printf(" Creating ");
09890 printtriangle(m, b, &tri2);
09891 printf(" Creating ");
09892 printtriangle(m, b, &tri3);
09893 }
09894 return;
09895 } else {
09896
09897 divider = vertices >> 1;
09898
09899 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
09900 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
09901 &innerright, farright);
09902 if (b->verbose > 1) {
09903 printf(" Joining triangulations with %d and %d vertices.\n", divider,
09904 vertices - divider);
09905 }
09906
09907 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
09908 }
09909 }
09910
09911 #ifdef ANSI_DECLARATORS
09912 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
09913 #else
09914 long removeghosts(m, b, startghost)
09915 struct mesh *m;
09916 struct behavior *b;
09917 struct otri *startghost;
09918 #endif
09919
09920 {
09921 struct otri searchedge;
09922 struct otri dissolveedge;
09923 struct otri deadtriangle;
09924 vertex markorg;
09925 long hullsize;
09926 triangle ptr;
09927
09928 if (b->verbose) {
09929 printf(" Removing ghost triangles.\n");
09930 }
09931
09932 lprev(*startghost, searchedge);
09933 symself(searchedge);
09934 m->dummytri[0] = encode(searchedge);
09935
09936 otricopy(*startghost, dissolveedge);
09937 hullsize = 0;
09938 do {
09939 hullsize++;
09940 lnext(dissolveedge, deadtriangle);
09941 lprevself(dissolveedge);
09942 symself(dissolveedge);
09943
09944
09945 if (!b->poly) {
09946
09947 if (dissolveedge.tri != m->dummytri) {
09948 org(dissolveedge, markorg);
09949 if (vertexmark(markorg) == 0) {
09950 setvertexmark(markorg, 1);
09951 }
09952 }
09953 }
09954
09955 dissolve(dissolveedge);
09956
09957 sym(deadtriangle, dissolveedge);
09958
09959 triangledealloc(m, deadtriangle.tri);
09960 } while (!otriequal(dissolveedge, *startghost));
09961 return hullsize;
09962 }
09963
09964
09965
09966
09967
09968
09969
09970
09971
09972
09973
09974 #ifdef ANSI_DECLARATORS
09975 long divconqdelaunay(struct mesh *m, struct behavior *b)
09976 #else
09977 long divconqdelaunay(m, b)
09978 struct mesh *m;
09979 struct behavior *b;
09980 #endif
09981
09982 {
09983 vertex *sortarray;
09984 struct otri hullleft, hullright;
09985 int divider;
09986 int i, j;
09987
09988 if (b->verbose) {
09989 printf(" Sorting vertices.\n");
09990 }
09991
09992
09993 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
09994 traversalinit(&m->vertices);
09995 for (i = 0; i < m->invertices; i++) {
09996 sortarray[i] = vertextraverse(m);
09997 }
09998
09999 vertexsort(sortarray, m->invertices);
10000
10001 i = 0;
10002 for (j = 1; j < m->invertices; j++) {
10003 if ((sortarray[i][0] == sortarray[j][0])
10004 && (sortarray[i][1] == sortarray[j][1])) {
10005 if (!b->quiet) {
10006 printf(
10007 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10008 sortarray[j][0], sortarray[j][1]);
10009 }
10010 setvertextype(sortarray[j], UNDEADVERTEX);
10011 m->undeads++;
10012 } else {
10013 i++;
10014 sortarray[i] = sortarray[j];
10015 }
10016 }
10017 i++;
10018 if (b->dwyer) {
10019
10020 divider = i >> 1;
10021 if (i - divider >= 2) {
10022 if (divider >= 2) {
10023 alternateaxes(sortarray, divider, 1);
10024 }
10025 alternateaxes(&sortarray[divider], i - divider, 1);
10026 }
10027 }
10028
10029 if (b->verbose) {
10030 printf(" Forming triangulation.\n");
10031 }
10032
10033
10034 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10035 trifree((VOID *) sortarray);
10036
10037 return removeghosts(m, b, &hullleft);
10038 }
10039
10042
10043
10044
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059 #ifndef REDUCED
10060
10061 #ifdef ANSI_DECLARATORS
10062 void boundingbox(struct mesh *m, struct behavior *b)
10063 #else
10064 void boundingbox(m, b)
10065 struct mesh *m;
10066 struct behavior *b;
10067 #endif
10068
10069 {
10070 struct otri inftri;
10071 REAL width;
10072
10073 if (b->verbose) {
10074 printf(" Creating triangular bounding box.\n");
10075 }
10076
10077 width = m->xmax - m->xmin;
10078 if (m->ymax - m->ymin > width) {
10079 width = m->ymax - m->ymin;
10080 }
10081 if (width == 0.0) {
10082 width = 1.0;
10083 }
10084
10085 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10086 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10087 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10088 m->infvertex1[0] = m->xmin - 50.0 * width;
10089 m->infvertex1[1] = m->ymin - 40.0 * width;
10090 m->infvertex2[0] = m->xmax + 50.0 * width;
10091 m->infvertex2[1] = m->ymin - 40.0 * width;
10092 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10093 m->infvertex3[1] = m->ymax + 60.0 * width;
10094
10095
10096 maketriangle(m, b, &inftri);
10097 setorg(inftri, m->infvertex1);
10098 setdest(inftri, m->infvertex2);
10099 setapex(inftri, m->infvertex3);
10100
10101
10102 m->dummytri[0] = (triangle) inftri.tri;
10103 if (b->verbose > 2) {
10104 printf(" Creating ");
10105 printtriangle(m, b, &inftri);
10106 }
10107 }
10108
10109 #endif
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125 #ifndef REDUCED
10126
10127 #ifdef ANSI_DECLARATORS
10128 long removebox(struct mesh *m, struct behavior *b)
10129 #else
10130 long removebox(m, b)
10131 struct mesh *m;
10132 struct behavior *b;
10133 #endif
10134
10135 {
10136 struct otri deadtriangle;
10137 struct otri searchedge;
10138 struct otri checkedge;
10139 struct otri nextedge, finaledge, dissolveedge;
10140 vertex markorg;
10141 long hullsize;
10142 triangle ptr;
10143
10144 if (b->verbose) {
10145 printf(" Removing triangular bounding box.\n");
10146 }
10147
10148 nextedge.tri = m->dummytri;
10149 nextedge.orient = 0;
10150 symself(nextedge);
10151
10152 lprev(nextedge, finaledge);
10153 lnextself(nextedge);
10154 symself(nextedge);
10155
10156
10157 lprev(nextedge, searchedge);
10158 symself(searchedge);
10159
10160
10161 lnext(nextedge, checkedge);
10162 symself(checkedge);
10163 if (checkedge.tri == m->dummytri) {
10164
10165
10166
10167 lprevself(searchedge);
10168 symself(searchedge);
10169 }
10170
10171
10172 m->dummytri[0] = encode(searchedge);
10173 hullsize = -2l;
10174 while (!otriequal(nextedge, finaledge)) {
10175 hullsize++;
10176 lprev(nextedge, dissolveedge);
10177 symself(dissolveedge);
10178
10179
10180 if (!b->poly) {
10181
10182
10183
10184
10185 if (dissolveedge.tri != m->dummytri) {
10186 org(dissolveedge, markorg);
10187 if (vertexmark(markorg) == 0) {
10188 setvertexmark(markorg, 1);
10189 }
10190 }
10191 }
10192
10193 dissolve(dissolveedge);
10194 lnext(nextedge, deadtriangle);
10195 sym(deadtriangle, nextedge);
10196
10197 triangledealloc(m, deadtriangle.tri);
10198
10199 if (nextedge.tri == m->dummytri) {
10200
10201 otricopy(dissolveedge, nextedge);
10202 }
10203 }
10204 triangledealloc(m, finaledge.tri);
10205
10206 trifree((VOID *) m->infvertex1);
10207 trifree((VOID *) m->infvertex2);
10208 trifree((VOID *) m->infvertex3);
10209
10210 return hullsize;
10211 }
10212
10213 #endif
10214
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224 #ifndef REDUCED
10225
10226 #ifdef ANSI_DECLARATORS
10227 long incrementaldelaunay(struct mesh *m, struct behavior *b)
10228 #else
10229 long incrementaldelaunay(m, b)
10230 struct mesh *m;
10231 struct behavior *b;
10232 #endif
10233
10234 {
10235 struct otri starttri;
10236 vertex vertexloop;
10237
10238
10239 boundingbox(m, b);
10240 if (b->verbose) {
10241 printf(" Incrementally inserting vertices.\n");
10242 }
10243 traversalinit(&m->vertices);
10244 vertexloop = vertextraverse(m);
10245 while (vertexloop != (vertex) NULL) {
10246 starttri.tri = m->dummytri;
10247 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10248 == DUPLICATEVERTEX) {
10249 if (!b->quiet) {
10250 printf(
10251 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10252 vertexloop[0], vertexloop[1]);
10253 }
10254 setvertextype(vertexloop, UNDEADVERTEX);
10255 m->undeads++;
10256 }
10257 vertexloop = vertextraverse(m);
10258 }
10259
10260 return removebox(m, b);
10261 }
10262
10263 #endif
10264
10267
10268
10269
10273 #ifndef REDUCED
10274
10275 #ifdef ANSI_DECLARATORS
10276 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10277 #else
10278 void eventheapinsert(heap, heapsize, newevent)
10279 struct event **heap;
10280 int heapsize;
10281 struct event *newevent;
10282 #endif
10283
10284 {
10285 REAL eventx, eventy;
10286 int eventnum;
10287 int parent;
10288 int notdone;
10289
10290 eventx = newevent->xkey;
10291 eventy = newevent->ykey;
10292 eventnum = heapsize;
10293 notdone = eventnum > 0;
10294 while (notdone) {
10295 parent = (eventnum - 1) >> 1;
10296 if ((heap[parent]->ykey < eventy) ||
10297 ((heap[parent]->ykey == eventy)
10298 && (heap[parent]->xkey <= eventx))) {
10299 notdone = 0;
10300 } else {
10301 heap[eventnum] = heap[parent];
10302 heap[eventnum]->heapposition = eventnum;
10303
10304 eventnum = parent;
10305 notdone = eventnum > 0;
10306 }
10307 }
10308 heap[eventnum] = newevent;
10309 newevent->heapposition = eventnum;
10310 }
10311
10312 #endif
10313
10314 #ifndef REDUCED
10315
10316 #ifdef ANSI_DECLARATORS
10317 void eventheapify(struct event **heap, int heapsize, int eventnum)
10318 #else
10319 void eventheapify(heap, heapsize, eventnum)
10320 struct event **heap;
10321 int heapsize;
10322 int eventnum;
10323 #endif
10324
10325 {
10326 struct event *thisevent;
10327 REAL eventx, eventy;
10328 int leftchild, rightchild;
10329 int smallest;
10330 int notdone;
10331
10332 thisevent = heap[eventnum];
10333 eventx = thisevent->xkey;
10334 eventy = thisevent->ykey;
10335 leftchild = 2 * eventnum + 1;
10336 notdone = leftchild < heapsize;
10337 while (notdone) {
10338 if ((heap[leftchild]->ykey < eventy) ||
10339 ((heap[leftchild]->ykey == eventy)
10340 && (heap[leftchild]->xkey < eventx))) {
10341 smallest = leftchild;
10342 } else {
10343 smallest = eventnum;
10344 }
10345 rightchild = leftchild + 1;
10346 if (rightchild < heapsize) {
10347 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10348 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10349 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10350 smallest = rightchild;
10351 }
10352 }
10353 if (smallest == eventnum) {
10354 notdone = 0;
10355 } else {
10356 heap[eventnum] = heap[smallest];
10357 heap[eventnum]->heapposition = eventnum;
10358 heap[smallest] = thisevent;
10359 thisevent->heapposition = smallest;
10360
10361 eventnum = smallest;
10362 leftchild = 2 * eventnum + 1;
10363 notdone = leftchild < heapsize;
10364 }
10365 }
10366 }
10367
10368 #endif
10369
10370 #ifndef REDUCED
10371
10372 #ifdef ANSI_DECLARATORS
10373 void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10374 #else
10375 void eventheapdelete(heap, heapsize, eventnum)
10376 struct event **heap;
10377 int heapsize;
10378 int eventnum;
10379 #endif
10380
10381 {
10382 struct event *moveevent;
10383 REAL eventx, eventy;
10384 int parent;
10385 int notdone;
10386
10387 moveevent = heap[heapsize - 1];
10388 if (eventnum > 0) {
10389 eventx = moveevent->xkey;
10390 eventy = moveevent->ykey;
10391 do {
10392 parent = (eventnum - 1) >> 1;
10393 if ((heap[parent]->ykey < eventy) ||
10394 ((heap[parent]->ykey == eventy)
10395 && (heap[parent]->xkey <= eventx))) {
10396 notdone = 0;
10397 } else {
10398 heap[eventnum] = heap[parent];
10399 heap[eventnum]->heapposition = eventnum;
10400
10401 eventnum = parent;
10402 notdone = eventnum > 0;
10403 }
10404 } while (notdone);
10405 }
10406 heap[eventnum] = moveevent;
10407 moveevent->heapposition = eventnum;
10408 eventheapify(heap, heapsize - 1, eventnum);
10409 }
10410
10411 #endif
10412
10413 #ifndef REDUCED
10414
10415 #ifdef ANSI_DECLARATORS
10416 void createeventheap(struct mesh *m, struct event ***eventheap,
10417 struct event **events, struct event **freeevents)
10418 #else
10419 void createeventheap(m, eventheap, events, freeevents)
10420 struct mesh *m;
10421 struct event ***eventheap;
10422 struct event **events;
10423 struct event **freeevents;
10424 #endif
10425
10426 {
10427 vertex thisvertex;
10428 int maxevents;
10429 int i;
10430
10431 maxevents = (3 * m->invertices) / 2;
10432 *eventheap = (struct event **) trimalloc(maxevents *
10433 (int) sizeof(struct event *));
10434 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10435 traversalinit(&m->vertices);
10436 for (i = 0; i < m->invertices; i++) {
10437 thisvertex = vertextraverse(m);
10438 (*events)[i].eventptr = (VOID *) thisvertex;
10439 (*events)[i].xkey = thisvertex[0];
10440 (*events)[i].ykey = thisvertex[1];
10441 eventheapinsert(*eventheap, i, *events + i);
10442 }
10443 *freeevents = (struct event *) NULL;
10444 for (i = maxevents - 1; i >= m->invertices; i--) {
10445 (*events)[i].eventptr = (VOID *) *freeevents;
10446 *freeevents = *events + i;
10447 }
10448 }
10449
10450 #endif
10451
10452 #ifndef REDUCED
10453
10454 #ifdef ANSI_DECLARATORS
10455 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10456 #else
10457 int rightofhyperbola(m, fronttri, newsite)
10458 struct mesh *m;
10459 struct otri *fronttri;
10460 vertex newsite;
10461 #endif
10462
10463 {
10464 vertex leftvertex, rightvertex;
10465 REAL dxa, dya, dxb, dyb;
10466
10467 m->hyperbolacount++;
10468
10469 dest(*fronttri, leftvertex);
10470 apex(*fronttri, rightvertex);
10471 if ((leftvertex[1] < rightvertex[1]) ||
10472 ((leftvertex[1] == rightvertex[1]) &&
10473 (leftvertex[0] < rightvertex[0]))) {
10474 if (newsite[0] >= rightvertex[0]) {
10475 return 1;
10476 }
10477 } else {
10478 if (newsite[0] <= leftvertex[0]) {
10479 return 0;
10480 }
10481 }
10482 dxa = leftvertex[0] - newsite[0];
10483 dya = leftvertex[1] - newsite[1];
10484 dxb = rightvertex[0] - newsite[0];
10485 dyb = rightvertex[1] - newsite[1];
10486 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10487 }
10488
10489 #endif
10490
10491 #ifndef REDUCED
10492
10493 #ifdef ANSI_DECLARATORS
10494 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10495 #else
10496 REAL circletop(m, pa, pb, pc, ccwabc)
10497 struct mesh *m;
10498 vertex pa;
10499 vertex pb;
10500 vertex pc;
10501 REAL ccwabc;
10502 #endif
10503
10504 {
10505 REAL xac, yac, xbc, ybc, xab, yab;
10506 REAL aclen2, bclen2, ablen2;
10507
10508 m->circletopcount++;
10509
10510 xac = pa[0] - pc[0];
10511 yac = pa[1] - pc[1];
10512 xbc = pb[0] - pc[0];
10513 ybc = pb[1] - pc[1];
10514 xab = pa[0] - pb[0];
10515 yab = pa[1] - pb[1];
10516 aclen2 = xac * xac + yac * yac;
10517 bclen2 = xbc * xbc + ybc * ybc;
10518 ablen2 = xab * xab + yab * yab;
10519 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10520 / (2.0 * ccwabc);
10521 }
10522
10523 #endif
10524
10525 #ifndef REDUCED
10526
10527 #ifdef ANSI_DECLARATORS
10528 void check4deadevent(struct otri *checktri, struct event **freeevents,
10529 struct event **eventheap, int *heapsize)
10530 #else
10531 void check4deadevent(checktri, freeevents, eventheap, heapsize)
10532 struct otri *checktri;
10533 struct event **freeevents;
10534 struct event **eventheap;
10535 int *heapsize;
10536 #endif
10537
10538 {
10539 struct event *deadevent;
10540 vertex eventvertex;
10541 int eventnum;
10542
10543 org(*checktri, eventvertex);
10544 if (eventvertex != (vertex) NULL) {
10545 deadevent = (struct event *) eventvertex;
10546 eventnum = deadevent->heapposition;
10547 deadevent->eventptr = (VOID *) *freeevents;
10548 *freeevents = deadevent;
10549 eventheapdelete(eventheap, *heapsize, eventnum);
10550 (*heapsize)--;
10551 setorg(*checktri, NULL);
10552 }
10553 }
10554
10555 #endif
10556
10557 #ifndef REDUCED
10558
10559 #ifdef ANSI_DECLARATORS
10560 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10561 vertex searchpoint, struct otri *searchtri)
10562 #else
10563 struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10564 struct mesh *m;
10565 struct splaynode *splaytree;
10566 vertex searchpoint;
10567 struct otri *searchtri;
10568 #endif
10569
10570 {
10571 struct splaynode *child, *grandchild;
10572 struct splaynode *lefttree, *righttree;
10573 struct splaynode *leftright;
10574 vertex checkvertex;
10575 int rightofroot, rightofchild;
10576
10577 if (splaytree == (struct splaynode *) NULL) {
10578 return (struct splaynode *) NULL;
10579 }
10580 dest(splaytree->keyedge, checkvertex);
10581 if (checkvertex == splaytree->keydest) {
10582 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10583 if (rightofroot) {
10584 otricopy(splaytree->keyedge, *searchtri);
10585 child = splaytree->rchild;
10586 } else {
10587 child = splaytree->lchild;
10588 }
10589 if (child == (struct splaynode *) NULL) {
10590 return splaytree;
10591 }
10592 dest(child->keyedge, checkvertex);
10593 if (checkvertex != child->keydest) {
10594 child = splay(m, child, searchpoint, searchtri);
10595 if (child == (struct splaynode *) NULL) {
10596 if (rightofroot) {
10597 splaytree->rchild = (struct splaynode *) NULL;
10598 } else {
10599 splaytree->lchild = (struct splaynode *) NULL;
10600 }
10601 return splaytree;
10602 }
10603 }
10604 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10605 if (rightofchild) {
10606 otricopy(child->keyedge, *searchtri);
10607 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10608 child->rchild = grandchild;
10609 } else {
10610 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10611 child->lchild = grandchild;
10612 }
10613 if (grandchild == (struct splaynode *) NULL) {
10614 if (rightofroot) {
10615 splaytree->rchild = child->lchild;
10616 child->lchild = splaytree;
10617 } else {
10618 splaytree->lchild = child->rchild;
10619 child->rchild = splaytree;
10620 }
10621 return child;
10622 }
10623 if (rightofchild) {
10624 if (rightofroot) {
10625 splaytree->rchild = child->lchild;
10626 child->lchild = splaytree;
10627 } else {
10628 splaytree->lchild = grandchild->rchild;
10629 grandchild->rchild = splaytree;
10630 }
10631 child->rchild = grandchild->lchild;
10632 grandchild->lchild = child;
10633 } else {
10634 if (rightofroot) {
10635 splaytree->rchild = grandchild->lchild;
10636 grandchild->lchild = splaytree;
10637 } else {
10638 splaytree->lchild = child->rchild;
10639 child->rchild = splaytree;
10640 }
10641 child->lchild = grandchild->rchild;
10642 grandchild->rchild = child;
10643 }
10644 return grandchild;
10645 } else {
10646 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10647 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10648
10649 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10650 if (lefttree == (struct splaynode *) NULL) {
10651 return righttree;
10652 } else if (righttree == (struct splaynode *) NULL) {
10653 return lefttree;
10654 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10655 lefttree->rchild = righttree->lchild;
10656 righttree->lchild = lefttree;
10657 return righttree;
10658 } else if (righttree->lchild == (struct splaynode *) NULL) {
10659 righttree->lchild = lefttree->rchild;
10660 lefttree->rchild = righttree;
10661 return lefttree;
10662 } else {
10663
10664 leftright = lefttree->rchild;
10665 while (leftright->rchild != (struct splaynode *) NULL) {
10666 leftright = leftright->rchild;
10667 }
10668 leftright->rchild = righttree;
10669 return lefttree;
10670 }
10671 }
10672 }
10673
10674 #endif
10675
10676 #ifndef REDUCED
10677
10678 #ifdef ANSI_DECLARATORS
10679 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10680 struct otri *newkey, vertex searchpoint)
10681 #else
10682 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10683 struct mesh *m;
10684 struct splaynode *splayroot;
10685 struct otri *newkey;
10686 vertex searchpoint;
10687 #endif
10688
10689 {
10690 struct splaynode *newsplaynode;
10691
10692 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10693 otricopy(*newkey, newsplaynode->keyedge);
10694 dest(*newkey, newsplaynode->keydest);
10695 if (splayroot == (struct splaynode *) NULL) {
10696 newsplaynode->lchild = (struct splaynode *) NULL;
10697 newsplaynode->rchild = (struct splaynode *) NULL;
10698 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10699 newsplaynode->lchild = splayroot;
10700 newsplaynode->rchild = splayroot->rchild;
10701 splayroot->rchild = (struct splaynode *) NULL;
10702 } else {
10703 newsplaynode->lchild = splayroot->lchild;
10704 newsplaynode->rchild = splayroot;
10705 splayroot->lchild = (struct splaynode *) NULL;
10706 }
10707 return newsplaynode;
10708 }
10709
10710 #endif
10711
10712 #ifndef REDUCED
10713
10714 #ifdef ANSI_DECLARATORS
10715 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10716 struct splaynode *splayroot,
10717 struct otri *newkey,
10718 vertex pa, vertex pb, vertex pc, REAL topy)
10719 #else
10720 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10721 struct mesh *m;
10722 struct behavior *b;
10723 struct splaynode *splayroot;
10724 struct otri *newkey;
10725 vertex pa;
10726 vertex pb;
10727 vertex pc;
10728 REAL topy;
10729 #endif
10730
10731 {
10732 REAL ccwabc;
10733 REAL xac, yac, xbc, ybc;
10734 REAL aclen2, bclen2;
10735 REAL searchpoint[2];
10736 struct otri dummytri;
10737
10738 ccwabc = counterclockwise(m, b, pa, pb, pc);
10739 xac = pa[0] - pc[0];
10740 yac = pa[1] - pc[1];
10741 xbc = pb[0] - pc[0];
10742 ybc = pb[1] - pc[1];
10743 aclen2 = xac * xac + yac * yac;
10744 bclen2 = xbc * xbc + ybc * ybc;
10745 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10746 searchpoint[1] = topy;
10747 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10748 newkey, (vertex) searchpoint);
10749 }
10750
10751 #endif
10752
10753 #ifndef REDUCED
10754
10755 #ifdef ANSI_DECLARATORS
10756 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10757 struct otri *bottommost, vertex searchvertex,
10758 struct otri *searchtri, int *farright)
10759 #else
10760 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10761 searchtri, farright)
10762 struct mesh *m;
10763 struct splaynode *splayroot;
10764 struct otri *bottommost;
10765 vertex searchvertex;
10766 struct otri *searchtri;
10767 int *farright;
10768 #endif
10769
10770 {
10771 int farrightflag;
10772 triangle ptr;
10773
10774 otricopy(*bottommost, *searchtri);
10775 splayroot = splay(m, splayroot, searchvertex, searchtri);
10776
10777 farrightflag = 0;
10778 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10779 onextself(*searchtri);
10780 farrightflag = otriequal(*searchtri, *bottommost);
10781 }
10782 *farright = farrightflag;
10783 return splayroot;
10784 }
10785
10786 #endif
10787
10788 #ifndef REDUCED
10789
10790 #ifdef ANSI_DECLARATORS
10791 long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10792 #else
10793 long sweeplinedelaunay(m, b)
10794 struct mesh *m;
10795 struct behavior *b;
10796 #endif
10797
10798 {
10799 struct event **eventheap;
10800 struct event *events;
10801 struct event *freeevents;
10802 struct event *nextevent;
10803 struct event *newevent;
10804 struct splaynode *splayroot;
10805 struct otri bottommost;
10806 struct otri searchtri;
10807 struct otri fliptri;
10808 struct otri lefttri, righttri, farlefttri, farrighttri;
10809 struct otri inserttri;
10810 vertex firstvertex, secondvertex;
10811 vertex nextvertex, lastvertex;
10812 vertex connectvertex;
10813 vertex leftvertex, midvertex, rightvertex;
10814 REAL lefttest, righttest;
10815 int heapsize;
10816 int check4events, farrightflag;
10817 triangle ptr;
10818
10819 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10820 SPLAYNODEPERBLOCK, 0);
10821 splayroot = (struct splaynode *) NULL;
10822
10823 if (b->verbose) {
10824 printf(" Placing vertices in event heap.\n");
10825 }
10826 createeventheap(m, &eventheap, &events, &freeevents);
10827 heapsize = m->invertices;
10828
10829 if (b->verbose) {
10830 printf(" Forming triangulation.\n");
10831 }
10832 maketriangle(m, b, &lefttri);
10833 maketriangle(m, b, &righttri);
10834 bond(lefttri, righttri);
10835 lnextself(lefttri);
10836 lprevself(righttri);
10837 bond(lefttri, righttri);
10838 lnextself(lefttri);
10839 lprevself(righttri);
10840 bond(lefttri, righttri);
10841 firstvertex = (vertex) eventheap[0]->eventptr;
10842 eventheap[0]->eventptr = (VOID *) freeevents;
10843 freeevents = eventheap[0];
10844 eventheapdelete(eventheap, heapsize, 0);
10845 heapsize--;
10846 do {
10847 if (heapsize == 0) {
10848 printf("Error: Input vertices are all identical.\n");
10849 triexit(1);
10850 }
10851 secondvertex = (vertex) eventheap[0]->eventptr;
10852 eventheap[0]->eventptr = (VOID *) freeevents;
10853 freeevents = eventheap[0];
10854 eventheapdelete(eventheap, heapsize, 0);
10855 heapsize--;
10856 if ((firstvertex[0] == secondvertex[0]) &&
10857 (firstvertex[1] == secondvertex[1])) {
10858 if (!b->quiet) {
10859 printf(
10860 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10861 secondvertex[0], secondvertex[1]);
10862 }
10863 setvertextype(secondvertex, UNDEADVERTEX);
10864 m->undeads++;
10865 }
10866 } while ((firstvertex[0] == secondvertex[0]) &&
10867 (firstvertex[1] == secondvertex[1]));
10868 setorg(lefttri, firstvertex);
10869 setdest(lefttri, secondvertex);
10870 setorg(righttri, secondvertex);
10871 setdest(righttri, firstvertex);
10872 lprev(lefttri, bottommost);
10873 lastvertex = secondvertex;
10874 while (heapsize > 0) {
10875 nextevent = eventheap[0];
10876 eventheapdelete(eventheap, heapsize, 0);
10877 heapsize--;
10878 check4events = 1;
10879 if (nextevent->xkey < m->xmin) {
10880 decode(nextevent->eventptr, fliptri);
10881 oprev(fliptri, farlefttri);
10882 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10883 onext(fliptri, farrighttri);
10884 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10885
10886 if (otriequal(farlefttri, bottommost)) {
10887 lprev(fliptri, bottommost);
10888 }
10889 flip(m, b, &fliptri);
10890 setapex(fliptri, NULL);
10891 lprev(fliptri, lefttri);
10892 lnext(fliptri, righttri);
10893 sym(lefttri, farlefttri);
10894
10895 if (randomnation(SAMPLERATE) == 0) {
10896 symself(fliptri);
10897 dest(fliptri, leftvertex);
10898 apex(fliptri, midvertex);
10899 org(fliptri, rightvertex);
10900 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10901 midvertex, rightvertex, nextevent->ykey);
10902 }
10903 } else {
10904 nextvertex = (vertex) nextevent->eventptr;
10905 if ((nextvertex[0] == lastvertex[0]) &&
10906 (nextvertex[1] == lastvertex[1])) {
10907 if (!b->quiet) {
10908 printf(
10909 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10910 nextvertex[0], nextvertex[1]);
10911 }
10912 setvertextype(nextvertex, UNDEADVERTEX);
10913 m->undeads++;
10914 check4events = 0;
10915 } else {
10916 lastvertex = nextvertex;
10917
10918 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10919 &searchtri, &farrightflag);
10920
10921
10922
10923
10924
10925
10926
10927
10928
10929 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
10930
10931 otricopy(searchtri, farrighttri);
10932 sym(searchtri, farlefttri);
10933 maketriangle(m, b, &lefttri);
10934 maketriangle(m, b, &righttri);
10935 dest(farrighttri, connectvertex);
10936 setorg(lefttri, connectvertex);
10937 setdest(lefttri, nextvertex);
10938 setorg(righttri, nextvertex);
10939 setdest(righttri, connectvertex);
10940 bond(lefttri, righttri);
10941 lnextself(lefttri);
10942 lprevself(righttri);
10943 bond(lefttri, righttri);
10944 lnextself(lefttri);
10945 lprevself(righttri);
10946 bond(lefttri, farlefttri);
10947 bond(righttri, farrighttri);
10948 if (!farrightflag && otriequal(farrighttri, bottommost)) {
10949 otricopy(lefttri, bottommost);
10950 }
10951
10952 if (randomnation(SAMPLERATE) == 0) {
10953 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
10954 } else if (randomnation(SAMPLERATE) == 0) {
10955 lnext(righttri, inserttri);
10956 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
10957 }
10958 }
10959 }
10960 nextevent->eventptr = (VOID *) freeevents;
10961 freeevents = nextevent;
10962
10963 if (check4events) {
10964 apex(farlefttri, leftvertex);
10965 dest(lefttri, midvertex);
10966 apex(lefttri, rightvertex);
10967 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10968 if (lefttest > 0.0) {
10969 newevent = freeevents;
10970 freeevents = (struct event *) freeevents->eventptr;
10971 newevent->xkey = m->xminextreme;
10972 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10973 lefttest);
10974 newevent->eventptr = (VOID *) encode(lefttri);
10975 eventheapinsert(eventheap, heapsize, newevent);
10976 heapsize++;
10977 setorg(lefttri, newevent);
10978 }
10979 apex(righttri, leftvertex);
10980 org(righttri, midvertex);
10981 apex(farrighttri, rightvertex);
10982 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
10983 if (righttest > 0.0) {
10984 newevent = freeevents;
10985 freeevents = (struct event *) freeevents->eventptr;
10986 newevent->xkey = m->xminextreme;
10987 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
10988 righttest);
10989 newevent->eventptr = (VOID *) encode(farrighttri);
10990 eventheapinsert(eventheap, heapsize, newevent);
10991 heapsize++;
10992 setorg(farrighttri, newevent);
10993 }
10994 }
10995 }
10996
10997 pooldeinit(&m->splaynodes);
10998 lprevself(bottommost);
10999 return removeghosts(m, b, &bottommost);
11000 }
11001
11002 #endif
11003
11006
11007
11008
11012
11013
11014
11015
11016
11017
11018 #ifdef ANSI_DECLARATORS
11019 long delaunay(struct mesh *m, struct behavior *b)
11020 #else
11021 long delaunay(m, b)
11022 struct mesh *m;
11023 struct behavior *b;
11024 #endif
11025
11026 {
11027 long hulledges;
11028
11029 m->eextras = 0;
11030 initializetrisubpools(m, b);
11031
11032 #ifdef REDUCED
11033 if (!b->quiet) {
11034 printf(
11035 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11036 }
11037 hulledges = divconqdelaunay(m, b);
11038 #else
11039 if (!b->quiet) {
11040 printf("Constructing Delaunay triangulation ");
11041 if (b->incremental) {
11042 printf("by incremental method.\n");
11043 } else if (b->sweepline) {
11044 printf("by sweepline method.\n");
11045 } else {
11046 printf("by divide-and-conquer method.\n");
11047 }
11048 }
11049 if (b->incremental) {
11050 hulledges = incrementaldelaunay(m, b);
11051 } else if (b->sweepline) {
11052 hulledges = sweeplinedelaunay(m, b);
11053 } else {
11054 hulledges = divconqdelaunay(m, b);
11055 }
11056 #endif
11057
11058 if (m->triangles.items == 0) {
11059
11060 return 0l;
11061 } else {
11062 return hulledges;
11063 }
11064 }
11065
11066
11067
11068
11069
11070
11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
11087
11088
11089
11090
11091 #ifndef CDT_ONLY
11092
11093 #ifdef TRILIBRARY
11094
11095 #ifdef ANSI_DECLARATORS
11096 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11097 REAL *triangleattriblist, REAL *trianglearealist,
11098 int elements, int corners, int attribs,
11099 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11100 #else
11101 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11102 elements, corners, attribs, segmentlist, segmentmarkerlist,
11103 numberofsegments)
11104 struct mesh *m;
11105 struct behavior *b;
11106 int *trianglelist;
11107 REAL *triangleattriblist;
11108 REAL *trianglearealist;
11109 int elements;
11110 int corners;
11111 int attribs;
11112 int *segmentlist;
11113 int *segmentmarkerlist;
11114 int numberofsegments;
11115 #endif
11116
11117 #else
11118
11119 #ifdef ANSI_DECLARATORS
11120 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11121 char *areafilename, char *polyfilename, FILE *polyfile)
11122 #else
11123 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11124 struct mesh *m;
11125 struct behavior *b;
11126 char *elefilename;
11127 char *areafilename;
11128 char *polyfilename;
11129 FILE *polyfile;
11130 #endif
11131
11132 #endif
11133
11134 {
11135 #ifdef TRILIBRARY
11136 int vertexindex;
11137 int attribindex;
11138 #else
11139 FILE *elefile;
11140 FILE *areafile;
11141 char inputline[INPUTLINESIZE];
11142 char *stringptr;
11143 int areaelements;
11144 #endif
11145 struct otri triangleloop;
11146 struct otri triangleleft;
11147 struct otri checktri;
11148 struct otri checkleft;
11149 struct otri checkneighbor;
11150 struct osub subsegloop;
11151 triangle *vertexarray;
11152 triangle *prevlink;
11153 triangle nexttri;
11154 vertex tdest, tapex;
11155 vertex checkdest, checkapex;
11156 vertex shorg;
11157 vertex killvertex;
11158 vertex segmentorg, segmentdest;
11159 REAL area;
11160 int corner[3];
11161 int end[2];
11162 int killvertexindex;
11163 int incorners;
11164 int segmentmarkers;
11165 int boundmarker;
11166 int aroundvertex;
11167 long hullsize;
11168 int notfound;
11169 long elementnumber, segmentnumber;
11170 int i, j;
11171 triangle ptr;
11172
11173 #ifdef TRILIBRARY
11174 m->inelements = elements;
11175 incorners = corners;
11176 if (incorners < 3) {
11177 printf("Error: Triangles must have at least 3 vertices.\n");
11178 triexit(1);
11179 }
11180 m->eextras = attribs;
11181 #else
11182
11183 if (!b->quiet) {
11184 printf("Opening %s.\n", elefilename);
11185 }
11186 elefile = fopen(elefilename, "r");
11187 if (elefile == (FILE *) NULL) {
11188 printf(" Error: Cannot access file %s.\n", elefilename);
11189 triexit(1);
11190 }
11191
11192
11193 stringptr = readline(inputline, elefile, elefilename);
11194 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11195 stringptr = findfield(stringptr);
11196 if (*stringptr == '\0') {
11197 incorners = 3;
11198 } else {
11199 incorners = (int) strtol(stringptr, &stringptr, 0);
11200 if (incorners < 3) {
11201 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11202 elefilename);
11203 triexit(1);
11204 }
11205 }
11206 stringptr = findfield(stringptr);
11207 if (*stringptr == '\0') {
11208 m->eextras = 0;
11209 } else {
11210 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11211 }
11212 #endif
11213
11214 initializetrisubpools(m, b);
11215
11216
11217 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11218 maketriangle(m, b, &triangleloop);
11219
11220 triangleloop.tri[3] = (triangle) triangleloop.tri;
11221 }
11222
11223 segmentmarkers = 0;
11224 if (b->poly) {
11225 #ifdef TRILIBRARY
11226 m->insegments = numberofsegments;
11227 segmentmarkers = segmentmarkerlist != (int *) NULL;
11228 #else
11229
11230
11231 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11232 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11233 stringptr = findfield(stringptr);
11234 if (*stringptr != '\0') {
11235 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11236 }
11237 #endif
11238
11239
11240 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11241 makesubseg(m, &subsegloop);
11242
11243 subsegloop.ss[2] = (subseg) subsegloop.ss;
11244 }
11245 }
11246
11247 #ifdef TRILIBRARY
11248 vertexindex = 0;
11249 attribindex = 0;
11250 #else
11251 if (b->vararea) {
11252
11253 if (!b->quiet) {
11254 printf("Opening %s.\n", areafilename);
11255 }
11256 areafile = fopen(areafilename, "r");
11257 if (areafile == (FILE *) NULL) {
11258 printf(" Error: Cannot access file %s.\n", areafilename);
11259 triexit(1);
11260 }
11261 stringptr = readline(inputline, areafile, areafilename);
11262 areaelements = (int) strtol(stringptr, &stringptr, 0);
11263 if (areaelements != m->inelements) {
11264 printf("Error: %s and %s disagree on number of triangles.\n",
11265 elefilename, areafilename);
11266 triexit(1);
11267 }
11268 }
11269 #endif
11270
11271 if (!b->quiet) {
11272 printf("Reconstructing mesh.\n");
11273 }
11274
11275
11276
11277 vertexarray = (triangle *) trimalloc(m->vertices.items *
11278 (int) sizeof(triangle));
11279
11280 for (i = 0; i < m->vertices.items; i++) {
11281 vertexarray[i] = (triangle) m->dummytri;
11282 }
11283
11284 if (b->verbose) {
11285 printf(" Assembling triangles.\n");
11286 }
11287
11288
11289 traversalinit(&m->triangles);
11290 triangleloop.tri = triangletraverse(m);
11291 elementnumber = b->firstnumber;
11292 while (triangleloop.tri != (triangle *) NULL) {
11293 #ifdef TRILIBRARY
11294
11295 for (j = 0; j < 3; j++) {
11296 corner[j] = trianglelist[vertexindex++];
11297 if ((corner[j] < b->firstnumber) ||
11298 (corner[j] >= b->firstnumber + m->invertices)) {
11299 printf("Error: Triangle %ld has an invalid vertex index.\n",
11300 elementnumber);
11301 triexit(1);
11302 }
11303 }
11304 #else
11305
11306 stringptr = readline(inputline, elefile, elefilename);
11307 for (j = 0; j < 3; j++) {
11308 stringptr = findfield(stringptr);
11309 if (*stringptr == '\0') {
11310 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11311 elementnumber, j + 1, elefilename);
11312 triexit(1);
11313 } else {
11314 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11315 if ((corner[j] < b->firstnumber) ||
11316 (corner[j] >= b->firstnumber + m->invertices)) {
11317 printf("Error: Triangle %ld has an invalid vertex index.\n",
11318 elementnumber);
11319 triexit(1);
11320 }
11321 }
11322 }
11323 #endif
11324
11325
11326 for (j = 3; j < incorners; j++) {
11327 #ifdef TRILIBRARY
11328 killvertexindex = trianglelist[vertexindex++];
11329 #else
11330 stringptr = findfield(stringptr);
11331 if (*stringptr != '\0') {
11332 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11333 #endif
11334 if ((killvertexindex >= b->firstnumber) &&
11335 (killvertexindex < b->firstnumber + m->invertices)) {
11336
11337 killvertex = getvertex(m, b, killvertexindex);
11338 if (vertextype(killvertex) != DEADVERTEX) {
11339 vertexdealloc(m, killvertex);
11340 }
11341 }
11342 #ifndef TRILIBRARY
11343 }
11344 #endif
11345 }
11346
11347
11348 for (j = 0; j < m->eextras; j++) {
11349 #ifdef TRILIBRARY
11350 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11351 #else
11352 stringptr = findfield(stringptr);
11353 if (*stringptr == '\0') {
11354 setelemattribute(triangleloop, j, 0);
11355 } else {
11356 setelemattribute(triangleloop, j,
11357 (REAL) strtod(stringptr, &stringptr));
11358 }
11359 #endif
11360 }
11361
11362 if (b->vararea) {
11363 #ifdef TRILIBRARY
11364 area = trianglearealist[elementnumber - b->firstnumber];
11365 #else
11366
11367 stringptr = readline(inputline, areafile, areafilename);
11368 stringptr = findfield(stringptr);
11369 if (*stringptr == '\0') {
11370 area = -1.0;
11371 } else {
11372 area = (REAL) strtod(stringptr, &stringptr);
11373 }
11374 #endif
11375 setareabound(triangleloop, area);
11376 }
11377
11378
11379 triangleloop.orient = 0;
11380 setorg(triangleloop, getvertex(m, b, corner[0]));
11381 setdest(triangleloop, getvertex(m, b, corner[1]));
11382 setapex(triangleloop, getvertex(m, b, corner[2]));
11383
11384 for (triangleloop.orient = 0; triangleloop.orient < 3;
11385 triangleloop.orient++) {
11386
11387 aroundvertex = corner[triangleloop.orient];
11388
11389 nexttri = vertexarray[aroundvertex - b->firstnumber];
11390
11391 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11392
11393 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11394 decode(nexttri, checktri);
11395 if (checktri.tri != m->dummytri) {
11396 dest(triangleloop, tdest);
11397 apex(triangleloop, tapex);
11398
11399 do {
11400 dest(checktri, checkdest);
11401 apex(checktri, checkapex);
11402 if (tapex == checkdest) {
11403
11404 lprev(triangleloop, triangleleft);
11405 bond(triangleleft, checktri);
11406 }
11407 if (tdest == checkapex) {
11408
11409 lprev(checktri, checkleft);
11410 bond(triangleloop, checkleft);
11411 }
11412
11413 nexttri = checktri.tri[6 + checktri.orient];
11414 decode(nexttri, checktri);
11415 } while (checktri.tri != m->dummytri);
11416 }
11417 }
11418 triangleloop.tri = triangletraverse(m);
11419 elementnumber++;
11420 }
11421
11422 #ifdef TRILIBRARY
11423 vertexindex = 0;
11424 #else
11425 fclose(elefile);
11426 if (b->vararea) {
11427 fclose(areafile);
11428 }
11429 #endif
11430
11431 hullsize = 0;
11432 if (b->poly) {
11433 if (b->verbose) {
11434 printf(" Marking segments in triangulation.\n");
11435 }
11436
11437
11438 boundmarker = 0;
11439 traversalinit(&m->subsegs);
11440 subsegloop.ss = subsegtraverse(m);
11441 segmentnumber = b->firstnumber;
11442 while (subsegloop.ss != (subseg *) NULL) {
11443 #ifdef TRILIBRARY
11444 end[0] = segmentlist[vertexindex++];
11445 end[1] = segmentlist[vertexindex++];
11446 if (segmentmarkers) {
11447 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11448 }
11449 #else
11450
11451 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11452
11453 stringptr = findfield(stringptr);
11454 if (*stringptr == '\0') {
11455 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11456 polyfilename);
11457 triexit(1);
11458 } else {
11459 end[0] = (int) strtol(stringptr, &stringptr, 0);
11460 }
11461 stringptr = findfield(stringptr);
11462 if (*stringptr == '\0') {
11463 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11464 segmentnumber, polyfilename);
11465 triexit(1);
11466 } else {
11467 end[1] = (int) strtol(stringptr, &stringptr, 0);
11468 }
11469 if (segmentmarkers) {
11470 stringptr = findfield(stringptr);
11471 if (*stringptr == '\0') {
11472 boundmarker = 0;
11473 } else {
11474 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11475 }
11476 }
11477 #endif
11478 for (j = 0; j < 2; j++) {
11479 if ((end[j] < b->firstnumber) ||
11480 (end[j] >= b->firstnumber + m->invertices)) {
11481 printf("Error: Segment %ld has an invalid vertex index.\n",
11482 segmentnumber);
11483 triexit(1);
11484 }
11485 }
11486
11487
11488 subsegloop.ssorient = 0;
11489 segmentorg = getvertex(m, b, end[0]);
11490 segmentdest = getvertex(m, b, end[1]);
11491 setsorg(subsegloop, segmentorg);
11492 setsdest(subsegloop, segmentdest);
11493 setsegorg(subsegloop, segmentorg);
11494 setsegdest(subsegloop, segmentdest);
11495 setmark(subsegloop, boundmarker);
11496
11497 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11498 subsegloop.ssorient++) {
11499
11500 aroundvertex = end[1 - subsegloop.ssorient];
11501
11502 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11503 nexttri = vertexarray[aroundvertex - b->firstnumber];
11504 decode(nexttri, checktri);
11505 sorg(subsegloop, shorg);
11506 notfound = 1;
11507
11508
11509
11510
11511
11512
11513
11514 while (notfound && (checktri.tri != m->dummytri)) {
11515 dest(checktri, checkdest);
11516 if (shorg == checkdest) {
11517
11518 *prevlink = checktri.tri[6 + checktri.orient];
11519
11520 tsbond(checktri, subsegloop);
11521
11522 sym(checktri, checkneighbor);
11523 if (checkneighbor.tri == m->dummytri) {
11524
11525
11526
11527 insertsubseg(m, b, &checktri, 1);
11528 hullsize++;
11529 }
11530 notfound = 0;
11531 }
11532
11533 prevlink = &checktri.tri[6 + checktri.orient];
11534 nexttri = checktri.tri[6 + checktri.orient];
11535 decode(nexttri, checktri);
11536 }
11537 }
11538 subsegloop.ss = subsegtraverse(m);
11539 segmentnumber++;
11540 }
11541 }
11542
11543
11544
11545 for (i = 0; i < m->vertices.items; i++) {
11546
11547 nexttri = vertexarray[i];
11548 decode(nexttri, checktri);
11549 while (checktri.tri != m->dummytri) {
11550
11551
11552 nexttri = checktri.tri[6 + checktri.orient];
11553
11554 tsdissolve(checktri);
11555 sym(checktri, checkneighbor);
11556 if (checkneighbor.tri == m->dummytri) {
11557 insertsubseg(m, b, &checktri, 1);
11558 hullsize++;
11559 }
11560 decode(nexttri, checktri);
11561 }
11562 }
11563
11564 trifree((VOID *) vertexarray);
11565 return hullsize;
11566 }
11567
11568 #endif
11569
11572
11573
11574
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595 #ifdef ANSI_DECLARATORS
11596 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11597 struct otri *searchtri,
11598 vertex searchpoint)
11599 #else
11600 enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11601 struct mesh *m;
11602 struct behavior *b;
11603 struct otri *searchtri;
11604 vertex searchpoint;
11605 #endif
11606
11607 {
11608 struct otri checktri;
11609 vertex startvertex;
11610 vertex leftvertex, rightvertex;
11611 REAL leftccw, rightccw;
11612 int leftflag, rightflag;
11613 triangle ptr;
11614
11615 org(*searchtri, startvertex);
11616 dest(*searchtri, rightvertex);
11617 apex(*searchtri, leftvertex);
11618
11619 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11620 leftflag = leftccw > 0.0;
11621
11622 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11623 rightflag = rightccw > 0.0;
11624 if (leftflag && rightflag) {
11625
11626
11627 onext(*searchtri, checktri);
11628 if (checktri.tri == m->dummytri) {
11629 leftflag = 0;
11630 } else {
11631 rightflag = 0;
11632 }
11633 }
11634 while (leftflag) {
11635
11636 onextself(*searchtri);
11637 if (searchtri->tri == m->dummytri) {
11638 printf("Internal error in finddirection(): Unable to find a\n");
11639 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11640 startvertex[1]);
11641 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11642 internalerror();
11643 }
11644 apex(*searchtri, leftvertex);
11645 rightccw = leftccw;
11646 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11647 leftflag = leftccw > 0.0;
11648 }
11649 while (rightflag) {
11650
11651 oprevself(*searchtri);
11652 if (searchtri->tri == m->dummytri) {
11653 printf("Internal error in finddirection(): Unable to find a\n");
11654 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11655 startvertex[1]);
11656 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11657 internalerror();
11658 }
11659 dest(*searchtri, rightvertex);
11660 leftccw = rightccw;
11661 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11662 rightflag = rightccw > 0.0;
11663 }
11664 if (leftccw == 0.0) {
11665 return LEFTCOLLINEAR;
11666 } else if (rightccw == 0.0) {
11667 return RIGHTCOLLINEAR;
11668 } else {
11669 return WITHIN;
11670 }
11671 }
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690 #ifdef ANSI_DECLARATORS
11691 void segmentintersection(struct mesh *m, struct behavior *b,
11692 struct otri *splittri, struct osub *splitsubseg,
11693 vertex endpoint2)
11694 #else
11695 void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11696 struct mesh *m;
11697 struct behavior *b;
11698 struct otri *splittri;
11699 struct osub *splitsubseg;
11700 vertex endpoint2;
11701 #endif
11702
11703 {
11704 struct osub opposubseg;
11705 vertex endpoint1;
11706 vertex torg, tdest;
11707 vertex leftvertex, rightvertex;
11708 vertex newvertex;
11709 enum insertvertexresult success;
11710 enum finddirectionresult collinear;
11711 REAL ex, ey;
11712 REAL tx, ty;
11713 REAL etx, ety;
11714 REAL split, denom;
11715 int i;
11716 triangle ptr;
11717 subseg sptr;
11718
11719
11720 apex(*splittri, endpoint1);
11721 org(*splittri, torg);
11722 dest(*splittri, tdest);
11723
11724 tx = tdest[0] - torg[0];
11725 ty = tdest[1] - torg[1];
11726 ex = endpoint2[0] - endpoint1[0];
11727 ey = endpoint2[1] - endpoint1[1];
11728 etx = torg[0] - endpoint2[0];
11729 ety = torg[1] - endpoint2[1];
11730 denom = ty * ex - tx * ey;
11731 if (denom == 0.0) {
11732 printf("Internal error in segmentintersection():");
11733 printf(" Attempt to find intersection of parallel segments.\n");
11734 internalerror();
11735 }
11736 split = (ey * etx - ex * ety) / denom;
11737
11738 newvertex = (vertex) poolalloc(&m->vertices);
11739
11740 for (i = 0; i < 2 + m->nextras; i++) {
11741 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11742 }
11743 setvertexmark(newvertex, mark(*splitsubseg));
11744 setvertextype(newvertex, INPUTVERTEX);
11745 if (b->verbose > 1) {
11746 printf(
11747 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11748 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11749 }
11750
11751 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11752 if (success != SUCCESSFULVERTEX) {
11753 printf("Internal error in segmentintersection():\n");
11754 printf(" Failure to split a segment.\n");
11755 internalerror();
11756 }
11757
11758 setvertex2tri(newvertex, encode(*splittri));
11759 if (m->steinerleft > 0) {
11760 m->steinerleft--;
11761 }
11762
11763
11764 ssymself(*splitsubseg);
11765 spivot(*splitsubseg, opposubseg);
11766 sdissolve(*splitsubseg);
11767 sdissolve(opposubseg);
11768 do {
11769 setsegorg(*splitsubseg, newvertex);
11770 snextself(*splitsubseg);
11771 } while (splitsubseg->ss != m->dummysub);
11772 do {
11773 setsegorg(opposubseg, newvertex);
11774 snextself(opposubseg);
11775 } while (opposubseg.ss != m->dummysub);
11776
11777
11778
11779 collinear = finddirection(m, b, splittri, endpoint1);
11780 dest(*splittri, rightvertex);
11781 apex(*splittri, leftvertex);
11782 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11783 onextself(*splittri);
11784 } else if ((rightvertex[0] != endpoint1[0]) ||
11785 (rightvertex[1] != endpoint1[1])) {
11786 printf("Internal error in segmentintersection():\n");
11787 printf(" Topological inconsistency after splitting a segment.\n");
11788 internalerror();
11789 }
11790
11791 }
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817 #ifdef ANSI_DECLARATORS
11818 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11819 vertex endpoint2, int newmark)
11820 #else
11821 int scoutsegment(m, b, searchtri, endpoint2, newmark)
11822 struct mesh *m;
11823 struct behavior *b;
11824 struct otri *searchtri;
11825 vertex endpoint2;
11826 int newmark;
11827 #endif
11828
11829 {
11830 struct otri crosstri;
11831 struct osub crosssubseg;
11832 vertex leftvertex, rightvertex;
11833 enum finddirectionresult collinear;
11834 subseg sptr;
11835
11836 collinear = finddirection(m, b, searchtri, endpoint2);
11837 dest(*searchtri, rightvertex);
11838 apex(*searchtri, leftvertex);
11839 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11840 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11841
11842 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11843 lprevself(*searchtri);
11844 }
11845
11846 insertsubseg(m, b, searchtri, newmark);
11847 return 1;
11848 } else if (collinear == LEFTCOLLINEAR) {
11849
11850
11851 lprevself(*searchtri);
11852 insertsubseg(m, b, searchtri, newmark);
11853
11854 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11855 } else if (collinear == RIGHTCOLLINEAR) {
11856
11857 insertsubseg(m, b, searchtri, newmark);
11858
11859 lnextself(*searchtri);
11860
11861 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11862 } else {
11863 lnext(*searchtri, crosstri);
11864 tspivot(crosstri, crosssubseg);
11865
11866 if (crosssubseg.ss == m->dummysub) {
11867 return 0;
11868 } else {
11869
11870 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11871 otricopy(crosstri, *searchtri);
11872 insertsubseg(m, b, searchtri, newmark);
11873
11874 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11875 }
11876 }
11877 }
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898 #ifndef REDUCED
11899 #ifndef CDT_ONLY
11900
11901 #ifdef ANSI_DECLARATORS
11902 void conformingedge(struct mesh *m, struct behavior *b,
11903 vertex endpoint1, vertex endpoint2, int newmark)
11904 #else
11905 void conformingedge(m, b, endpoint1, endpoint2, newmark)
11906 struct mesh *m;
11907 struct behavior *b;
11908 vertex endpoint1;
11909 vertex endpoint2;
11910 int newmark;
11911 #endif
11912
11913 {
11914 struct otri searchtri1, searchtri2;
11915 struct osub brokensubseg;
11916 vertex newvertex;
11917 vertex midvertex1, midvertex2;
11918 enum insertvertexresult success;
11919 int i;
11920 subseg sptr;
11921
11922 if (b->verbose > 2) {
11923 printf("Forcing segment into triangulation by recursive splitting:\n");
11924 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
11925 endpoint2[0], endpoint2[1]);
11926 }
11927
11928 newvertex = (vertex) poolalloc(&m->vertices);
11929
11930 for (i = 0; i < 2 + m->nextras; i++) {
11931 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
11932 }
11933 setvertexmark(newvertex, newmark);
11934 setvertextype(newvertex, SEGMENTVERTEX);
11935
11936 searchtri1.tri = m->dummytri;
11937
11938 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
11939 0, 0);
11940 if (success == DUPLICATEVERTEX) {
11941 if (b->verbose > 2) {
11942 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
11943 newvertex[0], newvertex[1]);
11944 }
11945
11946 vertexdealloc(m, newvertex);
11947 org(searchtri1, newvertex);
11948 } else {
11949 if (success == VIOLATINGVERTEX) {
11950 if (b->verbose > 2) {
11951 printf(" Two segments intersect at (%.12g, %.12g).\n",
11952 newvertex[0], newvertex[1]);
11953 }
11954
11955 tspivot(searchtri1, brokensubseg);
11956 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
11957 0, 0);
11958 if (success != SUCCESSFULVERTEX) {
11959 printf("Internal error in conformingedge():\n");
11960 printf(" Failure to split a segment.\n");
11961 internalerror();
11962 }
11963 }
11964
11965 if (m->steinerleft > 0) {
11966 m->steinerleft--;
11967 }
11968 }
11969 otricopy(searchtri1, searchtri2);
11970
11971
11972
11973
11974
11975 finddirection(m, b, &searchtri2, endpoint2);
11976 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
11977
11978
11979 org(searchtri1, midvertex1);
11980 conformingedge(m, b, midvertex1, endpoint1, newmark);
11981 }
11982 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
11983
11984
11985 org(searchtri2, midvertex2);
11986 conformingedge(m, b, midvertex2, endpoint2, newmark);
11987 }
11988 }
11989
11990 #endif
11991 #endif
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031 #ifdef ANSI_DECLARATORS
12032 void delaunayfixup(struct mesh *m, struct behavior *b,
12033 struct otri *fixuptri, int leftside)
12034 #else
12035 void delaunayfixup(m, b, fixuptri, leftside)
12036 struct mesh *m;
12037 struct behavior *b;
12038 struct otri *fixuptri;
12039 int leftside;
12040 #endif
12041
12042 {
12043 struct otri neartri;
12044 struct otri fartri;
12045 struct osub faredge;
12046 vertex nearvertex, leftvertex, rightvertex, farvertex;
12047 triangle ptr;
12048 subseg sptr;
12049
12050 lnext(*fixuptri, neartri);
12051 sym(neartri, fartri);
12052
12053 if (fartri.tri == m->dummytri) {
12054 return;
12055 }
12056 tspivot(neartri, faredge);
12057 if (faredge.ss != m->dummysub) {
12058 return;
12059 }
12060
12061 apex(neartri, nearvertex);
12062 org(neartri, leftvertex);
12063 dest(neartri, rightvertex);
12064 apex(fartri, farvertex);
12065
12066 if (leftside) {
12067 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12068
12069
12070 return;
12071 }
12072 } else {
12073 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12074
12075
12076 return;
12077 }
12078 }
12079 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12080
12081
12082
12083
12084 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12085 0.0) {
12086 return;
12087 }
12088
12089 }
12090 flip(m, b, &neartri);
12091 lprevself(*fixuptri);
12092
12093 delaunayfixup(m, b, fixuptri, leftside);
12094 delaunayfixup(m, b, &fartri, leftside);
12095 }
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151 #ifdef ANSI_DECLARATORS
12152 void constrainededge(struct mesh *m, struct behavior *b,
12153 struct otri *starttri, vertex endpoint2, int newmark)
12154 #else
12155 void constrainededge(m, b, starttri, endpoint2, newmark)
12156 struct mesh *m;
12157 struct behavior *b;
12158 struct otri *starttri;
12159 vertex endpoint2;
12160 int newmark;
12161 #endif
12162
12163 {
12164 struct otri fixuptri, fixuptri2;
12165 struct osub crosssubseg;
12166 vertex endpoint1;
12167 vertex farvertex;
12168 REAL area;
12169 int collision;
12170 int done;
12171 triangle ptr;
12172 subseg sptr;
12173
12174 org(*starttri, endpoint1);
12175 lnext(*starttri, fixuptri);
12176 flip(m, b, &fixuptri);
12177
12178
12179 collision = 0;
12180 done = 0;
12181 do {
12182 org(fixuptri, farvertex);
12183
12184
12185 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12186 oprev(fixuptri, fixuptri2);
12187
12188 delaunayfixup(m, b, &fixuptri, 0);
12189 delaunayfixup(m, b, &fixuptri2, 1);
12190 done = 1;
12191 } else {
12192
12193
12194
12195 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12196 if (area == 0.0) {
12197
12198 collision = 1;
12199 oprev(fixuptri, fixuptri2);
12200
12201 delaunayfixup(m, b, &fixuptri, 0);
12202 delaunayfixup(m, b, &fixuptri2, 1);
12203 done = 1;
12204 } else {
12205 if (area > 0.0) {
12206 oprev(fixuptri, fixuptri2);
12207
12208
12209 delaunayfixup(m, b, &fixuptri2, 1);
12210
12211
12212
12213 lprevself(fixuptri);
12214 } else {
12215 delaunayfixup(m, b, &fixuptri, 0);
12216
12217
12218
12219 oprevself(fixuptri);
12220 }
12221
12222 tspivot(fixuptri, crosssubseg);
12223 if (crosssubseg.ss == m->dummysub) {
12224 flip(m, b, &fixuptri);
12225 } else {
12226
12227 collision = 1;
12228
12229 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12230 done = 1;
12231 }
12232 }
12233 }
12234 } while (!done);
12235
12236 insertsubseg(m, b, &fixuptri, newmark);
12237
12238
12239 if (collision) {
12240
12241 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12242 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12243 }
12244 }
12245 }
12246
12247
12248
12249
12250
12251
12252
12253 #ifdef ANSI_DECLARATORS
12254 void insertsegment(struct mesh *m, struct behavior *b,
12255 vertex endpoint1, vertex endpoint2, int newmark)
12256 #else
12257 void insertsegment(m, b, endpoint1, endpoint2, newmark)
12258 struct mesh *m;
12259 struct behavior *b;
12260 vertex endpoint1;
12261 vertex endpoint2;
12262 int newmark;
12263 #endif
12264
12265 {
12266 struct otri searchtri1, searchtri2;
12267 triangle encodedtri;
12268 vertex checkvertex;
12269 triangle ptr;
12270
12271 if (b->verbose > 1) {
12272 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12273 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12274 }
12275
12276
12277 checkvertex = (vertex) NULL;
12278 encodedtri = vertex2tri(endpoint1);
12279 if (encodedtri != (triangle) NULL) {
12280 decode(encodedtri, searchtri1);
12281 org(searchtri1, checkvertex);
12282 }
12283 if (checkvertex != endpoint1) {
12284
12285 searchtri1.tri = m->dummytri;
12286 searchtri1.orient = 0;
12287 symself(searchtri1);
12288
12289 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12290 printf(
12291 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12292 printf(" (%.12g, %.12g) in triangulation.\n",
12293 endpoint1[0], endpoint1[1]);
12294 internalerror();
12295 }
12296 }
12297
12298 otricopy(searchtri1, m->recenttri);
12299
12300
12301 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12302
12303 return;
12304 }
12305
12306
12307 org(searchtri1, endpoint1);
12308
12309
12310 checkvertex = (vertex) NULL;
12311 encodedtri = vertex2tri(endpoint2);
12312 if (encodedtri != (triangle) NULL) {
12313 decode(encodedtri, searchtri2);
12314 org(searchtri2, checkvertex);
12315 }
12316 if (checkvertex != endpoint2) {
12317
12318 searchtri2.tri = m->dummytri;
12319 searchtri2.orient = 0;
12320 symself(searchtri2);
12321
12322 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12323 printf(
12324 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12325 printf(" (%.12g, %.12g) in triangulation.\n",
12326 endpoint2[0], endpoint2[1]);
12327 internalerror();
12328 }
12329 }
12330
12331 otricopy(searchtri2, m->recenttri);
12332
12333
12334 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12335
12336 return;
12337 }
12338
12339
12340 org(searchtri2, endpoint2);
12341
12342 #ifndef REDUCED
12343 #ifndef CDT_ONLY
12344 if (b->splitseg) {
12345
12346 conformingedge(m, b, endpoint1, endpoint2, newmark);
12347 } else {
12348 #endif
12349 #endif
12350
12351 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12352 #ifndef REDUCED
12353 #ifndef CDT_ONLY
12354 }
12355 #endif
12356 #endif
12357 }
12358
12359
12360
12361
12362
12363
12364
12365 #ifdef ANSI_DECLARATORS
12366 void markhull(struct mesh *m, struct behavior *b)
12367 #else
12368 void markhull(m, b)
12369 struct mesh *m;
12370 struct behavior *b;
12371 #endif
12372
12373 {
12374 struct otri hulltri;
12375 struct otri nexttri;
12376 struct otri starttri;
12377 triangle ptr;
12378
12379
12380 hulltri.tri = m->dummytri;
12381 hulltri.orient = 0;
12382 symself(hulltri);
12383
12384 otricopy(hulltri, starttri);
12385
12386 do {
12387
12388 insertsubseg(m, b, &hulltri, 1);
12389
12390 lnextself(hulltri);
12391 oprev(hulltri, nexttri);
12392 while (nexttri.tri != m->dummytri) {
12393 otricopy(nexttri, hulltri);
12394 oprev(hulltri, nexttri);
12395 }
12396 } while (!otriequal(hulltri, starttri));
12397 }
12398
12399
12400
12401
12402
12403
12404
12405
12406
12407
12408
12409 #ifdef TRILIBRARY
12410
12411 #ifdef ANSI_DECLARATORS
12412 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12413 int *segmentmarkerlist, int numberofsegments)
12414 #else
12415 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12416 struct mesh *m;
12417 struct behavior *b;
12418 int *segmentlist;
12419 int *segmentmarkerlist;
12420 int numberofsegments;
12421 #endif
12422
12423 #else
12424
12425 #ifdef ANSI_DECLARATORS
12426 void formskeleton(struct mesh *m, struct behavior *b,
12427 FILE *polyfile, char *polyfilename)
12428 #else
12429 void formskeleton(m, b, polyfile, polyfilename)
12430 struct mesh *m;
12431 struct behavior *b;
12432 FILE *polyfile;
12433 char *polyfilename;
12434 #endif
12435
12436 #endif
12437
12438 {
12439 #ifdef TRILIBRARY
12440 char polyfilename[6];
12441 int index;
12442 #else
12443 char inputline[INPUTLINESIZE];
12444 char *stringptr;
12445 #endif
12446 vertex endpoint1, endpoint2;
12447 int segmentmarkers;
12448 int end1, end2;
12449 int boundmarker;
12450 int i;
12451
12452 if (b->poly) {
12453 if (!b->quiet) {
12454 printf("Recovering segments in Delaunay triangulation.\n");
12455 }
12456 #ifdef TRILIBRARY
12457 strcpy(polyfilename, "input");
12458 m->insegments = numberofsegments;
12459 segmentmarkers = segmentmarkerlist != (int *) NULL;
12460 index = 0;
12461 #else
12462
12463
12464 stringptr = readline(inputline, polyfile, polyfilename);
12465 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12466 stringptr = findfield(stringptr);
12467 if (*stringptr == '\0') {
12468 segmentmarkers = 0;
12469 } else {
12470 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12471 }
12472 #endif
12473
12474
12475 if (m->triangles.items == 0) {
12476 return;
12477 }
12478
12479
12480
12481 if (m->insegments > 0) {
12482 makevertexmap(m, b);
12483 if (b->verbose) {
12484 printf(" Recovering PSLG segments.\n");
12485 }
12486 }
12487
12488 boundmarker = 0;
12489
12490 for (i = 0; i < m->insegments; i++) {
12491 #ifdef TRILIBRARY
12492 end1 = segmentlist[index++];
12493 end2 = segmentlist[index++];
12494 if (segmentmarkers) {
12495 boundmarker = segmentmarkerlist[i];
12496 }
12497 #else
12498 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12499 stringptr = findfield(stringptr);
12500 if (*stringptr == '\0') {
12501 printf("Error: Segment %d has no endpoints in %s.\n",
12502 b->firstnumber + i, polyfilename);
12503 triexit(1);
12504 } else {
12505 end1 = (int) strtol(stringptr, &stringptr, 0);
12506 }
12507 stringptr = findfield(stringptr);
12508 if (*stringptr == '\0') {
12509 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12510 b->firstnumber + i, polyfilename);
12511 triexit(1);
12512 } else {
12513 end2 = (int) strtol(stringptr, &stringptr, 0);
12514 }
12515 if (segmentmarkers) {
12516 stringptr = findfield(stringptr);
12517 if (*stringptr == '\0') {
12518 boundmarker = 0;
12519 } else {
12520 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12521 }
12522 }
12523 #endif
12524 if ((end1 < b->firstnumber) ||
12525 (end1 >= b->firstnumber + m->invertices)) {
12526 if (!b->quiet) {
12527 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12528 b->firstnumber + i, polyfilename);
12529 }
12530 } else if ((end2 < b->firstnumber) ||
12531 (end2 >= b->firstnumber + m->invertices)) {
12532 if (!b->quiet) {
12533 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12534 b->firstnumber + i, polyfilename);
12535 }
12536 } else {
12537
12538 endpoint1 = getvertex(m, b, end1);
12539 endpoint2 = getvertex(m, b, end2);
12540 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12541 if (!b->quiet) {
12542 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12543 b->firstnumber + i, polyfilename);
12544 }
12545 } else {
12546 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12547 }
12548 }
12549 }
12550 } else {
12551 m->insegments = 0;
12552 }
12553 if (b->convex || !b->poly) {
12554
12555 if (b->verbose) {
12556 printf(" Enclosing convex hull with segments.\n");
12557 }
12558 markhull(m, b);
12559 }
12560 }
12561
12564
12565
12566
12570
12571
12572
12573
12574
12575
12576
12577
12578 #ifdef ANSI_DECLARATORS
12579 void infecthull(struct mesh *m, struct behavior *b)
12580 #else
12581 void infecthull(m, b)
12582 struct mesh *m;
12583 struct behavior *b;
12584 #endif
12585
12586 {
12587 struct otri hulltri;
12588 struct otri nexttri;
12589 struct otri starttri;
12590 struct osub hullsubseg;
12591 triangle **deadtriangle;
12592 vertex horg, hdest;
12593 triangle ptr;
12594 subseg sptr;
12595
12596 if (b->verbose) {
12597 printf(" Marking concavities (external triangles) for elimination.\n");
12598 }
12599
12600 hulltri.tri = m->dummytri;
12601 hulltri.orient = 0;
12602 symself(hulltri);
12603
12604 otricopy(hulltri, starttri);
12605
12606 do {
12607
12608 if (!infected(hulltri)) {
12609
12610 tspivot(hulltri, hullsubseg);
12611 if (hullsubseg.ss == m->dummysub) {
12612
12613 if (!infected(hulltri)) {
12614 infect(hulltri);
12615 deadtriangle = (triangle **) poolalloc(&m->viri);
12616 *deadtriangle = hulltri.tri;
12617 }
12618 } else {
12619
12620 if (mark(hullsubseg) == 0) {
12621 setmark(hullsubseg, 1);
12622 org(hulltri, horg);
12623 dest(hulltri, hdest);
12624 if (vertexmark(horg) == 0) {
12625 setvertexmark(horg, 1);
12626 }
12627 if (vertexmark(hdest) == 0) {
12628 setvertexmark(hdest, 1);
12629 }
12630 }
12631 }
12632 }
12633
12634 lnextself(hulltri);
12635 oprev(hulltri, nexttri);
12636 while (nexttri.tri != m->dummytri) {
12637 otricopy(nexttri, hulltri);
12638 oprev(hulltri, nexttri);
12639 }
12640 } while (!otriequal(hulltri, starttri));
12641 }
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653
12654
12655
12656
12657
12658
12659
12660 #ifdef ANSI_DECLARATORS
12661 void plague(struct mesh *m, struct behavior *b)
12662 #else
12663 void plague(m, b)
12664 struct mesh *m;
12665 struct behavior *b;
12666 #endif
12667
12668 {
12669 struct otri testtri;
12670 struct otri neighbor;
12671 triangle **virusloop;
12672 triangle **deadtriangle;
12673 struct osub neighborsubseg;
12674 vertex testvertex;
12675 vertex norg, ndest;
12676 vertex deadorg, deaddest, deadapex;
12677 int killorg;
12678 triangle ptr;
12679 subseg sptr;
12680
12681 if (b->verbose) {
12682 printf(" Marking neighbors of marked triangles.\n");
12683 }
12684
12685
12686 traversalinit(&m->viri);
12687 virusloop = (triangle **) traverse(&m->viri);
12688 while (virusloop != (triangle **) NULL) {
12689 testtri.tri = *virusloop;
12690
12691
12692
12693
12694 uninfect(testtri);
12695 if (b->verbose > 2) {
12696
12697
12698 testtri.orient = 0;
12699 org(testtri, deadorg);
12700 dest(testtri, deaddest);
12701 apex(testtri, deadapex);
12702 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12703 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12704 deadapex[0], deadapex[1]);
12705 }
12706
12707 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12708
12709 sym(testtri, neighbor);
12710
12711 tspivot(testtri, neighborsubseg);
12712
12713 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12714 if (neighborsubseg.ss != m->dummysub) {
12715
12716
12717
12718 subsegdealloc(m, neighborsubseg.ss);
12719 if (neighbor.tri != m->dummytri) {
12720
12721
12722 uninfect(neighbor);
12723 tsdissolve(neighbor);
12724 infect(neighbor);
12725 }
12726 }
12727 } else {
12728 if (neighborsubseg.ss == m->dummysub) {
12729
12730
12731 if (b->verbose > 2) {
12732 org(neighbor, deadorg);
12733 dest(neighbor, deaddest);
12734 apex(neighbor, deadapex);
12735 printf(
12736 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12737 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12738 deadapex[0], deadapex[1]);
12739 }
12740 infect(neighbor);
12741
12742 deadtriangle = (triangle **) poolalloc(&m->viri);
12743 *deadtriangle = neighbor.tri;
12744 } else {
12745
12746 stdissolve(neighborsubseg);
12747
12748 if (mark(neighborsubseg) == 0) {
12749 setmark(neighborsubseg, 1);
12750 }
12751 org(neighbor, norg);
12752 dest(neighbor, ndest);
12753 if (vertexmark(norg) == 0) {
12754 setvertexmark(norg, 1);
12755 }
12756 if (vertexmark(ndest) == 0) {
12757 setvertexmark(ndest, 1);
12758 }
12759 }
12760 }
12761 }
12762
12763
12764 infect(testtri);
12765 virusloop = (triangle **) traverse(&m->viri);
12766 }
12767
12768 if (b->verbose) {
12769 printf(" Deleting marked triangles.\n");
12770 }
12771
12772 traversalinit(&m->viri);
12773 virusloop = (triangle **) traverse(&m->viri);
12774 while (virusloop != (triangle **) NULL) {
12775 testtri.tri = *virusloop;
12776
12777
12778
12779
12780 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12781 org(testtri, testvertex);
12782
12783 if (testvertex != (vertex) NULL) {
12784 killorg = 1;
12785
12786 setorg(testtri, NULL);
12787
12788 onext(testtri, neighbor);
12789
12790 while ((neighbor.tri != m->dummytri) &&
12791 (!otriequal(neighbor, testtri))) {
12792 if (infected(neighbor)) {
12793
12794 setorg(neighbor, NULL);
12795 } else {
12796
12797 killorg = 0;
12798 }
12799
12800 onextself(neighbor);
12801 }
12802
12803 if (neighbor.tri == m->dummytri) {
12804
12805 oprev(testtri, neighbor);
12806
12807 while (neighbor.tri != m->dummytri) {
12808 if (infected(neighbor)) {
12809
12810 setorg(neighbor, NULL);
12811 } else {
12812
12813 killorg = 0;
12814 }
12815
12816 oprevself(neighbor);
12817 }
12818 }
12819 if (killorg) {
12820 if (b->verbose > 1) {
12821 printf(" Deleting vertex (%.12g, %.12g)\n",
12822 testvertex[0], testvertex[1]);
12823 }
12824 setvertextype(testvertex, UNDEADVERTEX);
12825 m->undeads++;
12826 }
12827 }
12828 }
12829
12830
12831
12832 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12833 sym(testtri, neighbor);
12834 if (neighbor.tri == m->dummytri) {
12835
12836
12837
12838 m->hullsize--;
12839 } else {
12840
12841 dissolve(neighbor);
12842
12843
12844 m->hullsize++;
12845 }
12846 }
12847
12848 triangledealloc(m, testtri.tri);
12849 virusloop = (triangle **) traverse(&m->viri);
12850 }
12851
12852 poolrestart(&m->viri);
12853 }
12854
12855
12856
12857
12858
12859
12860
12861
12862
12863
12864
12865
12866
12867
12868
12869
12870 #ifdef ANSI_DECLARATORS
12871 void regionplague(struct mesh *m, struct behavior *b,
12872 REAL attribute, REAL area)
12873 #else
12874 void regionplague(m, b, attribute, area)
12875 struct mesh *m;
12876 struct behavior *b;
12877 REAL attribute;
12878 REAL area;
12879 #endif
12880
12881 {
12882 struct otri testtri;
12883 struct otri neighbor;
12884 triangle **virusloop;
12885 triangle **regiontri;
12886 struct osub neighborsubseg;
12887 vertex regionorg, regiondest, regionapex;
12888 triangle ptr;
12889 subseg sptr;
12890
12891 if (b->verbose > 1) {
12892 printf(" Marking neighbors of marked triangles.\n");
12893 }
12894
12895
12896
12897 traversalinit(&m->viri);
12898 virusloop = (triangle **) traverse(&m->viri);
12899 while (virusloop != (triangle **) NULL) {
12900 testtri.tri = *virusloop;
12901
12902
12903
12904
12905 uninfect(testtri);
12906 if (b->regionattrib) {
12907
12908 setelemattribute(testtri, m->eextras, attribute);
12909 }
12910 if (b->vararea) {
12911
12912 setareabound(testtri, area);
12913 }
12914 if (b->verbose > 2) {
12915
12916
12917 testtri.orient = 0;
12918 org(testtri, regionorg);
12919 dest(testtri, regiondest);
12920 apex(testtri, regionapex);
12921 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12922 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12923 regionapex[0], regionapex[1]);
12924 }
12925
12926 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12927
12928 sym(testtri, neighbor);
12929
12930 tspivot(testtri, neighborsubseg);
12931
12932
12933 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
12934 && (neighborsubseg.ss == m->dummysub)) {
12935 if (b->verbose > 2) {
12936 org(neighbor, regionorg);
12937 dest(neighbor, regiondest);
12938 apex(neighbor, regionapex);
12939 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12940 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
12941 regionapex[0], regionapex[1]);
12942 }
12943
12944 infect(neighbor);
12945
12946 regiontri = (triangle **) poolalloc(&m->viri);
12947 *regiontri = neighbor.tri;
12948 }
12949 }
12950
12951
12952 infect(testtri);
12953 virusloop = (triangle **) traverse(&m->viri);
12954 }
12955
12956
12957 if (b->verbose > 1) {
12958 printf(" Unmarking marked triangles.\n");
12959 }
12960 traversalinit(&m->viri);
12961 virusloop = (triangle **) traverse(&m->viri);
12962 while (virusloop != (triangle **) NULL) {
12963 testtri.tri = *virusloop;
12964 uninfect(testtri);
12965 virusloop = (triangle **) traverse(&m->viri);
12966 }
12967
12968 poolrestart(&m->viri);
12969 }
12970
12971
12972
12973
12974
12975
12976
12977
12978
12979
12980
12981
12982
12983 #ifdef ANSI_DECLARATORS
12984 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
12985 REAL *regionlist, int regions)
12986 #else
12987 void carveholes(m, b, holelist, holes, regionlist, regions)
12988 struct mesh *m;
12989 struct behavior *b;
12990 REAL *holelist;
12991 int holes;
12992 REAL *regionlist;
12993 int regions;
12994 #endif
12995
12996 {
12997 struct otri searchtri;
12998 struct otri triangleloop;
12999 struct otri *regiontris;
13000 triangle **holetri;
13001 triangle **regiontri;
13002 vertex searchorg, searchdest;
13003 enum locateresult intersect;
13004 int i;
13005 triangle ptr;
13006
13007 if (!(b->quiet || (b->noholes && b->convex))) {
13008 printf("Removing unwanted triangles.\n");
13009 if (b->verbose && (holes > 0)) {
13010 printf(" Marking holes for elimination.\n");
13011 }
13012 }
13013
13014 if (regions > 0) {
13015
13016 regiontris = (struct otri *) trimalloc(regions *
13017 (int) sizeof(struct otri));
13018 } else {
13019 regiontris = (struct otri *) NULL;
13020 }
13021
13022 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13023
13024
13025 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13026 }
13027
13028 if (!b->convex) {
13029
13030
13031 infecthull(m, b);
13032 }
13033
13034 if ((holes > 0) && !b->noholes) {
13035
13036 for (i = 0; i < 2 * holes; i += 2) {
13037
13038 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13039 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13040
13041 searchtri.tri = m->dummytri;
13042 searchtri.orient = 0;
13043 symself(searchtri);
13044
13045
13046
13047 org(searchtri, searchorg);
13048 dest(searchtri, searchdest);
13049 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13050 0.0) {
13051
13052 intersect = locate(m, b, &holelist[i], &searchtri);
13053 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13054
13055
13056 infect(searchtri);
13057 holetri = (triangle **) poolalloc(&m->viri);
13058 *holetri = searchtri.tri;
13059 }
13060 }
13061 }
13062 }
13063 }
13064
13065
13066
13067
13068
13069
13070
13071 if (regions > 0) {
13072
13073 for (i = 0; i < regions; i++) {
13074 regiontris[i].tri = m->dummytri;
13075
13076 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13077 (regionlist[4 * i + 1] >= m->ymin) &&
13078 (regionlist[4 * i + 1] <= m->ymax)) {
13079
13080 searchtri.tri = m->dummytri;
13081 searchtri.orient = 0;
13082 symself(searchtri);
13083
13084
13085
13086 org(searchtri, searchorg);
13087 dest(searchtri, searchdest);
13088 if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) >
13089 0.0) {
13090
13091 intersect = locate(m, b, ®ionlist[4 * i], &searchtri);
13092 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13093
13094
13095 otricopy(searchtri, regiontris[i]);
13096 }
13097 }
13098 }
13099 }
13100 }
13101
13102 if (m->viri.items > 0) {
13103
13104 plague(m, b);
13105 }
13106
13107
13108 if (regions > 0) {
13109 if (!b->quiet) {
13110 if (b->regionattrib) {
13111 if (b->vararea) {
13112 printf("Spreading regional attributes and area constraints.\n");
13113 } else {
13114 printf("Spreading regional attributes.\n");
13115 }
13116 } else {
13117 printf("Spreading regional area constraints.\n");
13118 }
13119 }
13120 if (b->regionattrib && !b->refine) {
13121
13122 traversalinit(&m->triangles);
13123 triangleloop.orient = 0;
13124 triangleloop.tri = triangletraverse(m);
13125 while (triangleloop.tri != (triangle *) NULL) {
13126 setelemattribute(triangleloop, m->eextras, 0.0);
13127 triangleloop.tri = triangletraverse(m);
13128 }
13129 }
13130 for (i = 0; i < regions; i++) {
13131 if (regiontris[i].tri != m->dummytri) {
13132
13133
13134 if (!deadtri(regiontris[i].tri)) {
13135
13136 infect(regiontris[i]);
13137 regiontri = (triangle **) poolalloc(&m->viri);
13138 *regiontri = regiontris[i].tri;
13139
13140 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13141
13142 }
13143 }
13144 }
13145 if (b->regionattrib && !b->refine) {
13146
13147 m->eextras++;
13148 }
13149 }
13150
13151
13152 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13153 pooldeinit(&m->viri);
13154 }
13155 if (regions > 0) {
13156 trifree((VOID *) regiontris);
13157 }
13158 }
13159
13162
13163
13164
13168
13169
13170
13171
13172
13173
13174
13175 #ifndef CDT_ONLY
13176
13177 #ifdef ANSI_DECLARATORS
13178 void tallyencs(struct mesh *m, struct behavior *b)
13179 #else
13180 void tallyencs(m, b)
13181 struct mesh *m;
13182 struct behavior *b;
13183 #endif
13184
13185 {
13186 struct osub subsegloop;
13187 int dummy;
13188
13189 traversalinit(&m->subsegs);
13190 subsegloop.ssorient = 0;
13191 subsegloop.ss = subsegtraverse(m);
13192 while (subsegloop.ss != (subseg *) NULL) {
13193
13194 dummy = checkseg4encroach(m, b, &subsegloop);
13195 subsegloop.ss = subsegtraverse(m);
13196 }
13197 }
13198
13199 #endif
13200
13201
13202
13203
13204
13205
13206
13207 #ifndef CDT_ONLY
13208
13209 void precisionerror()
13210 {
13211 printf("Try increasing the area criterion and/or reducing the minimum\n");
13212 printf(" allowable angle so that tiny triangles are not created.\n");
13213 #ifdef SINGLE
13214 printf("Alternatively, try recompiling me with double precision\n");
13215 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13216 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13217 #endif
13218 }
13219
13220 #endif
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236 #ifndef CDT_ONLY
13237
13238 #ifdef ANSI_DECLARATORS
13239 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13240 #else
13241 void splitencsegs(m, b, triflaws)
13242 struct mesh *m;
13243 struct behavior *b;
13244 int triflaws;
13245 #endif
13246
13247 {
13248 struct otri enctri;
13249 struct otri testtri;
13250 struct osub testsh;
13251 struct osub currentenc;
13252 struct badsubseg *encloop;
13253 vertex eorg, edest, eapex;
13254 vertex newvertex;
13255 enum insertvertexresult success;
13256 REAL segmentlength, nearestpoweroftwo;
13257 REAL split;
13258 REAL multiplier, divisor;
13259 int acuteorg, acuteorg2, acutedest, acutedest2;
13260 int dummy;
13261 int i;
13262 triangle ptr;
13263 subseg sptr;
13264
13265
13266
13267 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13268 traversalinit(&m->badsubsegs);
13269 encloop = badsubsegtraverse(m);
13270 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13271 sdecode(encloop->encsubseg, currentenc);
13272 sorg(currentenc, eorg);
13273 sdest(currentenc, edest);
13274
13275
13276
13277
13278 if (!deadsubseg(currentenc.ss) &&
13279 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296 stpivot(currentenc, enctri);
13297 lnext(enctri, testtri);
13298 tspivot(testtri, testsh);
13299 acuteorg = testsh.ss != m->dummysub;
13300
13301 lnextself(testtri);
13302 tspivot(testtri, testsh);
13303 acutedest = testsh.ss != m->dummysub;
13304
13305
13306
13307
13308 if (!b->conformdel && !acuteorg && !acutedest) {
13309 apex(enctri, eapex);
13310 while ((vertextype(eapex) == FREEVERTEX) &&
13311 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13312 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13313 deletevertex(m, b, &testtri);
13314 stpivot(currentenc, enctri);
13315 apex(enctri, eapex);
13316 lprev(enctri, testtri);
13317 }
13318 }
13319
13320
13321
13322 sym(enctri, testtri);
13323 if (testtri.tri != m->dummytri) {
13324
13325 lnextself(testtri);
13326 tspivot(testtri, testsh);
13327 acutedest2 = testsh.ss != m->dummysub;
13328 acutedest = acutedest || acutedest2;
13329
13330 lnextself(testtri);
13331 tspivot(testtri, testsh);
13332 acuteorg2 = testsh.ss != m->dummysub;
13333 acuteorg = acuteorg || acuteorg2;
13334
13335
13336 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13337 org(testtri, eapex);
13338 while ((vertextype(eapex) == FREEVERTEX) &&
13339 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13340 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13341 deletevertex(m, b, &testtri);
13342 sym(enctri, testtri);
13343 apex(testtri, eapex);
13344 lprevself(testtri);
13345 }
13346 }
13347 }
13348
13349
13350
13351 if (acuteorg || acutedest) {
13352 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13353 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13354
13355
13356 nearestpoweroftwo = 1.0;
13357 while (segmentlength > 3.0 * nearestpoweroftwo) {
13358 nearestpoweroftwo *= 2.0;
13359 }
13360 while (segmentlength < 1.5 * nearestpoweroftwo) {
13361 nearestpoweroftwo *= 0.5;
13362 }
13363
13364 split = nearestpoweroftwo / segmentlength;
13365 if (acutedest) {
13366 split = 1.0 - split;
13367 }
13368 } else {
13369
13370
13371 split = 0.5;
13372 }
13373
13374
13375 newvertex = (vertex) poolalloc(&m->vertices);
13376
13377 for (i = 0; i < 2 + m->nextras; i++) {
13378 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13379 }
13380
13381 if (!b->noexact) {
13382
13383
13384
13385 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13386 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13387 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13388 if ((multiplier != 0.0) && (divisor != 0.0)) {
13389 multiplier = multiplier / divisor;
13390
13391 if (multiplier == multiplier) {
13392 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13393 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13394 }
13395 }
13396 }
13397
13398 setvertexmark(newvertex, mark(currentenc));
13399 setvertextype(newvertex, SEGMENTVERTEX);
13400 if (b->verbose > 1) {
13401 printf(
13402 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13403 eorg[0], eorg[1], edest[0], edest[1],
13404 newvertex[0], newvertex[1]);
13405 }
13406
13407 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13408 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13409 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13410 newvertex[0], newvertex[1]);
13411 printf("I attempted to split a segment to a smaller size than\n");
13412 printf(" can be accommodated by the finite precision of\n");
13413 printf(" floating point arithmetic.\n");
13414 precisionerror();
13415 triexit(1);
13416 }
13417
13418 success = insertvertex(m, b, newvertex, &enctri, ¤tenc,
13419 1, triflaws);
13420 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13421 printf("Internal error in splitencsegs():\n");
13422 printf(" Failure to split a segment.\n");
13423 internalerror();
13424 }
13425 if (m->steinerleft > 0) {
13426 m->steinerleft--;
13427 }
13428
13429 dummy = checkseg4encroach(m, b, ¤tenc);
13430 snextself(currentenc);
13431 dummy = checkseg4encroach(m, b, ¤tenc);
13432 }
13433
13434 badsubsegdealloc(m, encloop);
13435 encloop = badsubsegtraverse(m);
13436 }
13437 }
13438 }
13439
13440 #endif
13441
13442
13443
13444
13445
13446
13447
13448 #ifndef CDT_ONLY
13449
13450 #ifdef ANSI_DECLARATORS
13451 void tallyfaces(struct mesh *m, struct behavior *b)
13452 #else
13453 void tallyfaces(m, b)
13454 struct mesh *m;
13455 struct behavior *b;
13456 #endif
13457
13458 {
13459 struct otri triangleloop;
13460
13461 if (b->verbose) {
13462 printf(" Making a list of bad triangles.\n");
13463 }
13464 traversalinit(&m->triangles);
13465 triangleloop.orient = 0;
13466 triangleloop.tri = triangletraverse(m);
13467 while (triangleloop.tri != (triangle *) NULL) {
13468
13469 testtriangle(m, b, &triangleloop);
13470 triangleloop.tri = triangletraverse(m);
13471 }
13472 }
13473
13474 #endif
13475
13476
13477
13478
13479
13480
13481
13482
13483
13484 #ifndef CDT_ONLY
13485
13486 #ifdef ANSI_DECLARATORS
13487 void splittriangle(struct mesh *m, struct behavior *b,
13488 struct badtriang *badtri)
13489 #else
13490 void splittriangle(m, b, badtri)
13491 struct mesh *m;
13492 struct behavior *b;
13493 struct badtriang *badtri;
13494 #endif
13495
13496 {
13497 struct otri badotri;
13498 vertex borg, bdest, bapex;
13499 vertex newvertex;
13500 REAL xi, eta;
13501 enum insertvertexresult success;
13502 int errorflag;
13503 int i;
13504
13505 decode(badtri->poortri, badotri);
13506 org(badotri, borg);
13507 dest(badotri, bdest);
13508 apex(badotri, bapex);
13509
13510
13511
13512 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13513 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13514 if (b->verbose > 1) {
13515 printf(" Splitting this triangle at its circumcenter:\n");
13516 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13517 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13518 }
13519
13520 errorflag = 0;
13521
13522 newvertex = (vertex) poolalloc(&m->vertices);
13523 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13524
13525
13526 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13527 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13528 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13529 if (!b->quiet) {
13530 printf(
13531 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13532 newvertex[0], newvertex[1]);
13533 errorflag = 1;
13534 }
13535 vertexdealloc(m, newvertex);
13536 } else {
13537 for (i = 2; i < 2 + m->nextras; i++) {
13538
13539 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13540 + eta * (bapex[i] - borg[i]);
13541 }
13542
13543
13544 setvertexmark(newvertex, 0);
13545 setvertextype(newvertex, FREEVERTEX);
13546
13547
13548
13549
13550
13551
13552
13553
13554 if (eta < xi) {
13555 lprevself(badotri);
13556 }
13557
13558
13559
13560 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13561 1, 1);
13562 if (success == SUCCESSFULVERTEX) {
13563 if (m->steinerleft > 0) {
13564 m->steinerleft--;
13565 }
13566 } else if (success == ENCROACHINGVERTEX) {
13567
13568
13569 undovertex(m, b);
13570 if (b->verbose > 1) {
13571 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13572 }
13573 vertexdealloc(m, newvertex);
13574 } else if (success == VIOLATINGVERTEX) {
13575
13576
13577 vertexdealloc(m, newvertex);
13578 } else {
13579
13580 if (!b->quiet) {
13581 printf(
13582 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13583 newvertex[0], newvertex[1]);
13584 errorflag = 1;
13585 }
13586 vertexdealloc(m, newvertex);
13587 }
13588 }
13589 if (errorflag) {
13590 if (b->verbose) {
13591 printf(" The new vertex is at the circumcenter of triangle\n");
13592 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13593 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13594 }
13595 printf("This probably means that I am trying to refine triangles\n");
13596 printf(" to a smaller size than can be accommodated by the finite\n");
13597 printf(" precision of floating point arithmetic. (You can be\n");
13598 printf(" sure of this if I fail to terminate.)\n");
13599 precisionerror();
13600 }
13601 }
13602 }
13603
13604 #endif
13605
13606
13607
13608
13609
13610
13611
13612
13613 #ifndef CDT_ONLY
13614
13615 #ifdef ANSI_DECLARATORS
13616 void enforcequality(struct mesh *m, struct behavior *b)
13617 #else
13618 void enforcequality(m, b)
13619 struct mesh *m;
13620 struct behavior *b;
13621 #endif
13622
13623 {
13624 struct badtriang *badtri;
13625 int i;
13626
13627 if (!b->quiet) {
13628 printf("Adding Steiner points to enforce quality.\n");
13629 }
13630
13631 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13632 BADSUBSEGPERBLOCK, 0);
13633 if (b->verbose) {
13634 printf(" Looking for encroached subsegments.\n");
13635 }
13636
13637 tallyencs(m, b);
13638 if (b->verbose && (m->badsubsegs.items > 0)) {
13639 printf(" Splitting encroached subsegments.\n");
13640 }
13641
13642 splitencsegs(m, b, 0);
13643
13644
13645
13646
13647 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13648
13649 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13650 BADTRIPERBLOCK, 0);
13651
13652 for (i = 0; i < 4096; i++) {
13653 m->queuefront[i] = (struct badtriang *) NULL;
13654 }
13655 m->firstnonemptyq = -1;
13656
13657 tallyfaces(m, b);
13658
13659 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13660 FLIPSTACKERPERBLOCK, 0);
13661 m->checkquality = 1;
13662 if (b->verbose) {
13663 printf(" Splitting bad triangles.\n");
13664 }
13665 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13666
13667 badtri = dequeuebadtriang(m);
13668 splittriangle(m, b, badtri);
13669 if (m->badsubsegs.items > 0) {
13670
13671 enqueuebadtriang(m, b, badtri);
13672
13673
13674 splitencsegs(m, b, 1);
13675 } else {
13676
13677 pooldealloc(&m->badtriangles, (VOID *) badtri);
13678 }
13679 }
13680 }
13681
13682
13683
13684
13685
13686 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13687 (m->steinerleft == 0)) {
13688 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13689 if (m->badsubsegs.items == 1) {
13690 printf(" one encroached subsegment, and therefore might not be truly\n"
13691 );
13692 } else {
13693 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13694 , m->badsubsegs.items);
13695 }
13696 printf(" Delaunay. If the Delaunay property is important to you,\n");
13697 printf(" try increasing the number of Steiner points (controlled by\n");
13698 printf(" the -S switch) slightly and try again.\n\n");
13699 }
13700 }
13701
13702 #endif
13703
13706
13707
13708
13709
13710
13711
13712
13713
13714 #ifdef ANSI_DECLARATORS
13715 void highorder(struct mesh *m, struct behavior *b)
13716 #else
13717 void highorder(m, b)
13718 struct mesh *m;
13719 struct behavior *b;
13720 #endif
13721
13722 {
13723 struct otri triangleloop, trisym;
13724 struct osub checkmark;
13725 vertex newvertex;
13726 vertex torg, tdest;
13727 int i;
13728 triangle ptr;
13729 subseg sptr;
13730
13731 if (!b->quiet) {
13732 printf("Adding vertices for second-order triangles.\n");
13733 }
13734
13735
13736
13737
13738
13739 m->vertices.deaditemstack = (VOID *) NULL;
13740
13741 traversalinit(&m->triangles);
13742 triangleloop.tri = triangletraverse(m);
13743
13744
13745
13746
13747
13748
13749 while (triangleloop.tri != (triangle *) NULL) {
13750 for (triangleloop.orient = 0; triangleloop.orient < 3;
13751 triangleloop.orient++) {
13752 sym(triangleloop, trisym);
13753 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13754 org(triangleloop, torg);
13755 dest(triangleloop, tdest);
13756
13757
13758 newvertex = (vertex) poolalloc(&m->vertices);
13759 for (i = 0; i < 2 + m->nextras; i++) {
13760 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13761 }
13762
13763
13764 setvertexmark(newvertex, trisym.tri == m->dummytri);
13765 setvertextype(newvertex,
13766 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13767 if (b->usesegments) {
13768 tspivot(triangleloop, checkmark);
13769
13770 if (checkmark.ss != m->dummysub) {
13771 setvertexmark(newvertex, mark(checkmark));
13772 setvertextype(newvertex, SEGMENTVERTEX);
13773 }
13774 }
13775 if (b->verbose > 1) {
13776 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13777 }
13778
13779 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13780 (triangle) newvertex;
13781 if (trisym.tri != m->dummytri) {
13782 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13783 }
13784 }
13785 }
13786 triangleloop.tri = triangletraverse(m);
13787 }
13788 }
13789
13790
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803 #ifndef TRILIBRARY
13804
13805 #ifdef ANSI_DECLARATORS
13806 char *readline(char *string, FILE *infile, char *infilename)
13807 #else
13808 char *readline(string, infile, infilename)
13809 char *string;
13810 FILE *infile;
13811 char *infilename;
13812 #endif
13813
13814 {
13815 char *result;
13816
13817
13818 do {
13819 result = fgets(string, INPUTLINESIZE, infile);
13820 if (result == (char *) NULL) {
13821 printf(" Error: Unexpected end of file in %s.\n", infilename);
13822 triexit(1);
13823 }
13824
13825
13826 while ((*result != '\0') && (*result != '#')
13827 && (*result != '.') && (*result != '+') && (*result != '-')
13828 && ((*result < '0') || (*result > '9'))) {
13829 result++;
13830 }
13831
13832 } while ((*result == '#') || (*result == '\0'));
13833 return result;
13834 }
13835
13836 #endif
13837
13838
13839
13840
13841
13842
13843
13844
13845
13846
13847 #ifndef TRILIBRARY
13848
13849 #ifdef ANSI_DECLARATORS
13850 char *findfield(char *string)
13851 #else
13852 char *findfield(string)
13853 char *string;
13854 #endif
13855
13856 {
13857 char *result;
13858
13859 result = string;
13860
13861 while ((*result != '\0') && (*result != '#')
13862 && (*result != ' ') && (*result != '\t')) {
13863 result++;
13864 }
13865
13866
13867 while ((*result != '\0') && (*result != '#')
13868 && (*result != '.') && (*result != '+') && (*result != '-')
13869 && ((*result < '0') || (*result > '9'))) {
13870 result++;
13871 }
13872
13873 if (*result == '#') {
13874 *result = '\0';
13875 }
13876 return result;
13877 }
13878
13879 #endif
13880
13881
13882
13883
13884
13885
13886
13887
13888 #ifndef TRILIBRARY
13889
13890 #ifdef ANSI_DECLARATORS
13891 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13892 char *polyfilename, FILE **polyfile)
13893 #else
13894 void readnodes(m, b, nodefilename, polyfilename, polyfile)
13895 struct mesh *m;
13896 struct behavior *b;
13897 char *nodefilename;
13898 char *polyfilename;
13899 FILE **polyfile;
13900 #endif
13901
13902 {
13903 FILE *infile;
13904 vertex vertexloop;
13905 char inputline[INPUTLINESIZE];
13906 char *stringptr;
13907 char *infilename;
13908 REAL x, y;
13909 int firstnode;
13910 int nodemarkers;
13911 int currentmarker;
13912 int i, j;
13913
13914 if (b->poly) {
13915
13916 if (!b->quiet) {
13917 printf("Opening %s.\n", polyfilename);
13918 }
13919 *polyfile = fopen(polyfilename, "r");
13920 if (*polyfile == (FILE *) NULL) {
13921 printf(" Error: Cannot access file %s.\n", polyfilename);
13922 triexit(1);
13923 }
13924
13925
13926 stringptr = readline(inputline, *polyfile, polyfilename);
13927 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13928 stringptr = findfield(stringptr);
13929 if (*stringptr == '\0') {
13930 m->mesh_dim = 2;
13931 } else {
13932 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13933 }
13934 stringptr = findfield(stringptr);
13935 if (*stringptr == '\0') {
13936 m->nextras = 0;
13937 } else {
13938 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13939 }
13940 stringptr = findfield(stringptr);
13941 if (*stringptr == '\0') {
13942 nodemarkers = 0;
13943 } else {
13944 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13945 }
13946 if (m->invertices > 0) {
13947 infile = *polyfile;
13948 infilename = polyfilename;
13949 m->readnodefile = 0;
13950 } else {
13951
13952
13953 m->readnodefile = 1;
13954 infilename = nodefilename;
13955 }
13956 } else {
13957 m->readnodefile = 1;
13958 infilename = nodefilename;
13959 *polyfile = (FILE *) NULL;
13960 }
13961
13962 if (m->readnodefile) {
13963
13964 if (!b->quiet) {
13965 printf("Opening %s.\n", nodefilename);
13966 }
13967 infile = fopen(nodefilename, "r");
13968 if (infile == (FILE *) NULL) {
13969 printf(" Error: Cannot access file %s.\n", nodefilename);
13970 triexit(1);
13971 }
13972
13973
13974 stringptr = readline(inputline, infile, nodefilename);
13975 m->invertices = (int) strtol(stringptr, &stringptr, 0);
13976 stringptr = findfield(stringptr);
13977 if (*stringptr == '\0') {
13978 m->mesh_dim = 2;
13979 } else {
13980 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
13981 }
13982 stringptr = findfield(stringptr);
13983 if (*stringptr == '\0') {
13984 m->nextras = 0;
13985 } else {
13986 m->nextras = (int) strtol(stringptr, &stringptr, 0);
13987 }
13988 stringptr = findfield(stringptr);
13989 if (*stringptr == '\0') {
13990 nodemarkers = 0;
13991 } else {
13992 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
13993 }
13994 }
13995
13996 if (m->invertices < 3) {
13997 printf("Error: Input must have at least three input vertices.\n");
13998 triexit(1);
13999 }
14000 if (m->mesh_dim != 2) {
14001 printf("Error: Triangle only works with two-dimensional meshes.\n");
14002 triexit(1);
14003 }
14004 if (m->nextras == 0) {
14005 b->weighted = 0;
14006 }
14007
14008 initializevertexpool(m, b);
14009
14010
14011 for (i = 0; i < m->invertices; i++) {
14012 vertexloop = (vertex) poolalloc(&m->vertices);
14013 stringptr = readline(inputline, infile, infilename);
14014 if (i == 0) {
14015 firstnode = (int) strtol(stringptr, &stringptr, 0);
14016 if ((firstnode == 0) || (firstnode == 1)) {
14017 b->firstnumber = firstnode;
14018 }
14019 }
14020 stringptr = findfield(stringptr);
14021 if (*stringptr == '\0') {
14022 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14023 triexit(1);
14024 }
14025 x = (REAL) strtod(stringptr, &stringptr);
14026 stringptr = findfield(stringptr);
14027 if (*stringptr == '\0') {
14028 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14029 triexit(1);
14030 }
14031 y = (REAL) strtod(stringptr, &stringptr);
14032 vertexloop[0] = x;
14033 vertexloop[1] = y;
14034
14035 for (j = 2; j < 2 + m->nextras; j++) {
14036 stringptr = findfield(stringptr);
14037 if (*stringptr == '\0') {
14038 vertexloop[j] = 0.0;
14039 } else {
14040 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14041 }
14042 }
14043 if (nodemarkers) {
14044
14045 stringptr = findfield(stringptr);
14046 if (*stringptr == '\0') {
14047 setvertexmark(vertexloop, 0);
14048 } else {
14049 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14050 setvertexmark(vertexloop, currentmarker);
14051 }
14052 } else {
14053
14054 setvertexmark(vertexloop, 0);
14055 }
14056 setvertextype(vertexloop, INPUTVERTEX);
14057
14058 if (i == 0) {
14059 m->xmin = m->xmax = x;
14060 m->ymin = m->ymax = y;
14061 } else {
14062 m->xmin = (x < m->xmin) ? x : m->xmin;
14063 m->xmax = (x > m->xmax) ? x : m->xmax;
14064 m->ymin = (y < m->ymin) ? y : m->ymin;
14065 m->ymax = (y > m->ymax) ? y : m->ymax;
14066 }
14067 }
14068 if (m->readnodefile) {
14069 fclose(infile);
14070 }
14071
14072
14073
14074 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14075 }
14076
14077 #endif
14078
14079
14080
14081
14082
14083
14084
14085 #ifdef TRILIBRARY
14086
14087 #ifdef ANSI_DECLARATORS
14088 void transfernodes(struct mesh *m, struct behavior *b, REAL *pointlist,
14089 REAL *pointattriblist, int *pointmarkerlist,
14090 int numberofpoints, int numberofpointattribs)
14091 #else
14092 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14093 numberofpoints, numberofpointattribs)
14094 struct mesh *m;
14095 struct behavior *b;
14096 REAL *pointlist;
14097 REAL *pointattriblist;
14098 int *pointmarkerlist;
14099 int numberofpoints;
14100 int numberofpointattribs;
14101 #endif
14102
14103 {
14104 vertex vertexloop;
14105 REAL x, y;
14106 int i, j;
14107 int coordindex;
14108 int attribindex;
14109
14110 m->invertices = numberofpoints;
14111 m->mesh_dim = 2;
14112 m->nextras = numberofpointattribs;
14113 m->readnodefile = 0;
14114 if (m->invertices < 3) {
14115 printf("Error: Input must have at least three input vertices.\n");
14116 triexit(1);
14117 }
14118 if (m->nextras == 0) {
14119 b->weighted = 0;
14120 }
14121
14122 initializevertexpool(m, b);
14123
14124
14125 coordindex = 0;
14126 attribindex = 0;
14127 for (i = 0; i < m->invertices; i++) {
14128 vertexloop = (vertex) poolalloc(&m->vertices);
14129
14130 x = vertexloop[0] = pointlist[coordindex++];
14131 y = vertexloop[1] = pointlist[coordindex++];
14132
14133 for (j = 0; j < numberofpointattribs; j++) {
14134 vertexloop[2 + j] = pointattriblist[attribindex++];
14135 }
14136 if (pointmarkerlist != (int *) NULL) {
14137
14138 setvertexmark(vertexloop, pointmarkerlist[i]);
14139 } else {
14140
14141 setvertexmark(vertexloop, 0);
14142 }
14143 setvertextype(vertexloop, INPUTVERTEX);
14144
14145 if (i == 0) {
14146 m->xmin = m->xmax = x;
14147 m->ymin = m->ymax = y;
14148 } else {
14149 m->xmin = (x < m->xmin) ? x : m->xmin;
14150 m->xmax = (x > m->xmax) ? x : m->xmax;
14151 m->ymin = (y < m->ymin) ? y : m->ymin;
14152 m->ymax = (y > m->ymax) ? y : m->ymax;
14153 }
14154 }
14155
14156
14157
14158 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14159 }
14160
14161 #endif
14162
14163
14164
14165
14166
14167
14168
14169
14170 #ifndef TRILIBRARY
14171
14172 #ifdef ANSI_DECLARATORS
14173 void readholes(struct mesh *m, struct behavior *b,
14174 FILE *polyfile, char *polyfilename, REAL **hlist, int *holes,
14175 REAL **rlist, int *regions)
14176 #else
14177 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14178 struct mesh *m;
14179 struct behavior *b;
14180 FILE *polyfile;
14181 char *polyfilename;
14182 REAL **hlist;
14183 int *holes;
14184 REAL **rlist;
14185 int *regions;
14186 #endif
14187
14188 {
14189 REAL *holelist;
14190 REAL *regionlist;
14191 char inputline[INPUTLINESIZE];
14192 char *stringptr;
14193 int index;
14194 int i;
14195
14196
14197 stringptr = readline(inputline, polyfile, polyfilename);
14198 *holes = (int) strtol(stringptr, &stringptr, 0);
14199 if (*holes > 0) {
14200 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14201 *hlist = holelist;
14202 for (i = 0; i < 2 * *holes; i += 2) {
14203 stringptr = readline(inputline, polyfile, polyfilename);
14204 stringptr = findfield(stringptr);
14205 if (*stringptr == '\0') {
14206 printf("Error: Hole %d has no x coordinate.\n",
14207 b->firstnumber + (i >> 1));
14208 triexit(1);
14209 } else {
14210 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14211 }
14212 stringptr = findfield(stringptr);
14213 if (*stringptr == '\0') {
14214 printf("Error: Hole %d has no y coordinate.\n",
14215 b->firstnumber + (i >> 1));
14216 triexit(1);
14217 } else {
14218 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14219 }
14220 }
14221 } else {
14222 *hlist = (REAL *) NULL;
14223 }
14224
14225 #ifndef CDT_ONLY
14226 if ((b->regionattrib || b->vararea) && !b->refine) {
14227
14228 stringptr = readline(inputline, polyfile, polyfilename);
14229 *regions = (int) strtol(stringptr, &stringptr, 0);
14230 if (*regions > 0) {
14231 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14232 *rlist = regionlist;
14233 index = 0;
14234 for (i = 0; i < *regions; i++) {
14235 stringptr = readline(inputline, polyfile, polyfilename);
14236 stringptr = findfield(stringptr);
14237 if (*stringptr == '\0') {
14238 printf("Error: Region %d has no x coordinate.\n",
14239 b->firstnumber + i);
14240 triexit(1);
14241 } else {
14242 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14243 }
14244 stringptr = findfield(stringptr);
14245 if (*stringptr == '\0') {
14246 printf("Error: Region %d has no y coordinate.\n",
14247 b->firstnumber + i);
14248 triexit(1);
14249 } else {
14250 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14251 }
14252 stringptr = findfield(stringptr);
14253 if (*stringptr == '\0') {
14254 printf(
14255 "Error: Region %d has no region attribute or area constraint.\n",
14256 b->firstnumber + i);
14257 triexit(1);
14258 } else {
14259 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14260 }
14261 stringptr = findfield(stringptr);
14262 if (*stringptr == '\0') {
14263 regionlist[index] = regionlist[index - 1];
14264 } else {
14265 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14266 }
14267 index++;
14268 }
14269 }
14270 } else {
14271
14272 *regions = 0;
14273 *rlist = (REAL *) NULL;
14274 }
14275 #endif
14276
14277 fclose(polyfile);
14278 }
14279
14280 #endif
14281
14282
14283
14284
14285
14286
14287
14288
14289 #ifndef TRILIBRARY
14290
14291 #ifdef ANSI_DECLARATORS
14292 void finishfile(FILE *outfile, int argc, char **argv)
14293 #else
14294 void finishfile(outfile, argc, argv)
14295 FILE *outfile;
14296 int argc;
14297 char **argv;
14298 #endif
14299
14300 {
14301 int i;
14302
14303 fprintf(outfile, "# Generated by");
14304 for (i = 0; i < argc; i++) {
14305 fprintf(outfile, " ");
14306 fputs(argv[i], outfile);
14307 }
14308 fprintf(outfile, "\n");
14309 fclose(outfile);
14310 }
14311
14312 #endif
14313
14314
14315
14316
14317
14318
14319
14320
14321
14322
14323 #ifdef TRILIBRARY
14324
14325 #ifdef ANSI_DECLARATORS
14326 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14327 REAL **pointattriblist, int **pointmarkerlist)
14328 #else
14329 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14330 struct mesh *m;
14331 struct behavior *b;
14332 REAL **pointlist;
14333 REAL **pointattriblist;
14334 int **pointmarkerlist;
14335 #endif
14336
14337 #else
14338
14339 #ifdef ANSI_DECLARATORS
14340 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14341 int argc, char **argv)
14342 #else
14343 void writenodes(m, b, nodefilename, argc, argv)
14344 struct mesh *m;
14345 struct behavior *b;
14346 char *nodefilename;
14347 int argc;
14348 char **argv;
14349 #endif
14350
14351 #endif
14352
14353 {
14354 #ifdef TRILIBRARY
14355 REAL *plist;
14356 REAL *palist;
14357 int *pmlist;
14358 int coordindex;
14359 int attribindex;
14360 #else
14361 FILE *outfile;
14362 #endif
14363 vertex vertexloop;
14364 long outvertices;
14365 int vertexnumber;
14366 int i;
14367
14368 if (b->jettison) {
14369 outvertices = m->vertices.items - m->undeads;
14370 } else {
14371 outvertices = m->vertices.items;
14372 }
14373
14374 #ifdef TRILIBRARY
14375 if (!b->quiet) {
14376 printf("Writing vertices.\n");
14377 }
14378
14379 if (*pointlist == (REAL *) NULL) {
14380 *pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14381 }
14382
14383 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14384 *pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14385 sizeof(REAL)));
14386 }
14387
14388 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14389 *pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14390 }
14391 plist = *pointlist;
14392 palist = *pointattriblist;
14393 pmlist = *pointmarkerlist;
14394 coordindex = 0;
14395 attribindex = 0;
14396 #else
14397 if (!b->quiet) {
14398 printf("Writing %s.\n", nodefilename);
14399 }
14400 outfile = fopen(nodefilename, "w");
14401 if (outfile == (FILE *) NULL) {
14402 printf(" Error: Cannot create file %s.\n", nodefilename);
14403 triexit(1);
14404 }
14405
14406
14407 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14408 m->nextras, 1 - b->nobound);
14409 #endif
14410
14411 traversalinit(&m->vertices);
14412 vertexnumber = b->firstnumber;
14413 vertexloop = vertextraverse(m);
14414 while (vertexloop != (vertex) NULL) {
14415 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14416 #ifdef TRILIBRARY
14417
14418 plist[coordindex++] = vertexloop[0];
14419 plist[coordindex++] = vertexloop[1];
14420
14421 for (i = 0; i < m->nextras; i++) {
14422 palist[attribindex++] = vertexloop[2 + i];
14423 }
14424 if (!b->nobound) {
14425
14426 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14427 }
14428 #else
14429
14430 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14431 vertexloop[1]);
14432 for (i = 0; i < m->nextras; i++) {
14433
14434 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14435 }
14436 if (b->nobound) {
14437 fprintf(outfile, "\n");
14438 } else {
14439
14440 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14441 }
14442 #endif
14443
14444 setvertexmark(vertexloop, vertexnumber);
14445 vertexnumber++;
14446 }
14447 vertexloop = vertextraverse(m);
14448 }
14449
14450 #ifndef TRILIBRARY
14451 finishfile(outfile, argc, argv);
14452 #endif
14453 }
14454
14455
14456
14457
14458
14459
14460
14461
14462
14463
14464
14465 #ifdef ANSI_DECLARATORS
14466 void numbernodes(struct mesh *m, struct behavior *b)
14467 #else
14468 void numbernodes(m, b)
14469 struct mesh *m;
14470 struct behavior *b;
14471 #endif
14472
14473 {
14474 vertex vertexloop;
14475 int vertexnumber;
14476
14477 traversalinit(&m->vertices);
14478 vertexnumber = b->firstnumber;
14479 vertexloop = vertextraverse(m);
14480 while (vertexloop != (vertex) NULL) {
14481 setvertexmark(vertexloop, vertexnumber);
14482 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14483 vertexnumber++;
14484 }
14485 vertexloop = vertextraverse(m);
14486 }
14487 }
14488
14489
14490
14491
14492
14493
14494
14495 #ifdef TRILIBRARY
14496
14497 #ifdef ANSI_DECLARATORS
14498 void writeelements(struct mesh *m, struct behavior *b,
14499 int **trianglelist, REAL **triangleattriblist)
14500 #else
14501 void writeelements(m, b, trianglelist, triangleattriblist)
14502 struct mesh *m;
14503 struct behavior *b;
14504 int **trianglelist;
14505 REAL **triangleattriblist;
14506 #endif
14507
14508 #else
14509
14510 #ifdef ANSI_DECLARATORS
14511 void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14512 int argc, char **argv)
14513 #else
14514 void writeelements(m, b, elefilename, argc, argv)
14515 struct mesh *m;
14516 struct behavior *b;
14517 char *elefilename;
14518 int argc;
14519 char **argv;
14520 #endif
14521
14522 #endif
14523
14524 {
14525 #ifdef TRILIBRARY
14526 int *tlist;
14527 REAL *talist;
14528 int vertexindex;
14529 int attribindex;
14530 #else
14531 FILE *outfile;
14532 #endif
14533 struct otri triangleloop;
14534 vertex p1, p2, p3;
14535 vertex mid1, mid2, mid3;
14536 long elementnumber;
14537 int i;
14538
14539 #ifdef TRILIBRARY
14540 if (!b->quiet) {
14541 printf("Writing triangles.\n");
14542 }
14543
14544 if (*trianglelist == (int *) NULL) {
14545 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14546 ((b->order + 1) * (b->order + 2) /
14547 2) * sizeof(int)));
14548 }
14549
14550 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14551 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14552 m->eextras *
14553 sizeof(REAL)));
14554 }
14555 tlist = *trianglelist;
14556 talist = *triangleattriblist;
14557 vertexindex = 0;
14558 attribindex = 0;
14559 #else
14560 if (!b->quiet) {
14561 printf("Writing %s.\n", elefilename);
14562 }
14563 outfile = fopen(elefilename, "w");
14564 if (outfile == (FILE *) NULL) {
14565 printf(" Error: Cannot create file %s.\n", elefilename);
14566 triexit(1);
14567 }
14568
14569 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14570 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14571 #endif
14572
14573 traversalinit(&m->triangles);
14574 triangleloop.tri = triangletraverse(m);
14575 triangleloop.orient = 0;
14576 elementnumber = b->firstnumber;
14577 while (triangleloop.tri != (triangle *) NULL) {
14578 org(triangleloop, p1);
14579 dest(triangleloop, p2);
14580 apex(triangleloop, p3);
14581 if (b->order == 1) {
14582 #ifdef TRILIBRARY
14583 tlist[vertexindex++] = vertexmark(p1);
14584 tlist[vertexindex++] = vertexmark(p2);
14585 tlist[vertexindex++] = vertexmark(p3);
14586 #else
14587
14588 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14589 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14590 #endif
14591 } else {
14592 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14593 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14594 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14595 #ifdef TRILIBRARY
14596 tlist[vertexindex++] = vertexmark(p1);
14597 tlist[vertexindex++] = vertexmark(p2);
14598 tlist[vertexindex++] = vertexmark(p3);
14599 tlist[vertexindex++] = vertexmark(mid1);
14600 tlist[vertexindex++] = vertexmark(mid2);
14601 tlist[vertexindex++] = vertexmark(mid3);
14602 #else
14603
14604 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14605 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14606 vertexmark(mid2), vertexmark(mid3));
14607 #endif
14608 }
14609
14610 #ifdef TRILIBRARY
14611 for (i = 0; i < m->eextras; i++) {
14612 talist[attribindex++] = elemattribute(triangleloop, i);
14613 }
14614 #else
14615 for (i = 0; i < m->eextras; i++) {
14616 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14617 }
14618 fprintf(outfile, "\n");
14619 #endif
14620
14621 triangleloop.tri = triangletraverse(m);
14622 elementnumber++;
14623 }
14624
14625 #ifndef TRILIBRARY
14626 finishfile(outfile, argc, argv);
14627 #endif
14628 }
14629
14630
14631
14632
14633
14634
14635
14636 #ifdef TRILIBRARY
14637
14638 #ifdef ANSI_DECLARATORS
14639 void writepoly(struct mesh *m, struct behavior *b,
14640 int **segmentlist, int **segmentmarkerlist)
14641 #else
14642 void writepoly(m, b, segmentlist, segmentmarkerlist)
14643 struct mesh *m;
14644 struct behavior *b;
14645 int **segmentlist;
14646 int **segmentmarkerlist;
14647 #endif
14648
14649 #else
14650
14651 #ifdef ANSI_DECLARATORS
14652 void writepoly(struct mesh *m, struct behavior *b, char *polyfilename,
14653 REAL *holelist, int holes, REAL *regionlist, int regions,
14654 int argc, char **argv)
14655 #else
14656 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14657 argc, argv)
14658 struct mesh *m;
14659 struct behavior *b;
14660 char *polyfilename;
14661 REAL *holelist;
14662 int holes;
14663 REAL *regionlist;
14664 int regions;
14665 int argc;
14666 char **argv;
14667 #endif
14668
14669 #endif
14670
14671 {
14672 #ifdef TRILIBRARY
14673 int *slist;
14674 int *smlist;
14675 int index;
14676 #else
14677 FILE *outfile;
14678 long holenumber, regionnumber;
14679 #endif
14680 struct osub subsegloop;
14681 vertex endpoint1, endpoint2;
14682 long subsegnumber;
14683
14684 #ifdef TRILIBRARY
14685 if (!b->quiet) {
14686 printf("Writing segments.\n");
14687 }
14688
14689 if (*segmentlist == (int *) NULL) {
14690 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14691 sizeof(int)));
14692 }
14693
14694 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14695 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14696 sizeof(int)));
14697 }
14698 slist = *segmentlist;
14699 smlist = *segmentmarkerlist;
14700 index = 0;
14701 #else
14702 if (!b->quiet) {
14703 printf("Writing %s.\n", polyfilename);
14704 }
14705 outfile = fopen(polyfilename, "w");
14706 if (outfile == (FILE *) NULL) {
14707 printf(" Error: Cannot create file %s.\n", polyfilename);
14708 triexit(1);
14709 }
14710
14711
14712
14713 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14714 1 - b->nobound);
14715
14716 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14717 #endif
14718
14719 traversalinit(&m->subsegs);
14720 subsegloop.ss = subsegtraverse(m);
14721 subsegloop.ssorient = 0;
14722 subsegnumber = b->firstnumber;
14723 while (subsegloop.ss != (subseg *) NULL) {
14724 sorg(subsegloop, endpoint1);
14725 sdest(subsegloop, endpoint2);
14726 #ifdef TRILIBRARY
14727
14728 slist[index++] = vertexmark(endpoint1);
14729 slist[index++] = vertexmark(endpoint2);
14730 if (!b->nobound) {
14731
14732 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14733 }
14734 #else
14735
14736 if (b->nobound) {
14737 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14738 vertexmark(endpoint1), vertexmark(endpoint2));
14739 } else {
14740 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14741 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14742 }
14743 #endif
14744
14745 subsegloop.ss = subsegtraverse(m);
14746 subsegnumber++;
14747 }
14748
14749 #ifndef TRILIBRARY
14750 #ifndef CDT_ONLY
14751 fprintf(outfile, "%d\n", holes);
14752 if (holes > 0) {
14753 for (holenumber = 0; holenumber < holes; holenumber++) {
14754
14755 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14756 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14757 }
14758 }
14759 if (regions > 0) {
14760 fprintf(outfile, "%d\n", regions);
14761 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14762
14763 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14764 b->firstnumber + regionnumber,
14765 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14766 regionlist[4 * regionnumber + 2],
14767 regionlist[4 * regionnumber + 3]);
14768 }
14769 }
14770 #endif
14771
14772 finishfile(outfile, argc, argv);
14773 #endif
14774 }
14775
14776
14777
14778
14779
14780
14781
14782 #ifdef TRILIBRARY
14783
14784 #ifdef ANSI_DECLARATORS
14785 void writeedges(struct mesh *m, struct behavior *b,
14786 int **edgelist, int **edgemarkerlist)
14787 #else
14788 void writeedges(m, b, edgelist, edgemarkerlist)
14789 struct mesh *m;
14790 struct behavior *b;
14791 int **edgelist;
14792 int **edgemarkerlist;
14793 #endif
14794
14795 #else
14796
14797 #ifdef ANSI_DECLARATORS
14798 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14799 int argc, char **argv)
14800 #else
14801 void writeedges(m, b, edgefilename, argc, argv)
14802 struct mesh *m;
14803 struct behavior *b;
14804 char *edgefilename;
14805 int argc;
14806 char **argv;
14807 #endif
14808
14809 #endif
14810
14811 {
14812 #ifdef TRILIBRARY
14813 int *elist;
14814 int *emlist;
14815 int index;
14816 #else
14817 FILE *outfile;
14818 #endif
14819 struct otri triangleloop, trisym;
14820 struct osub checkmark;
14821 vertex p1, p2;
14822 long edgenumber;
14823 triangle ptr;
14824 subseg sptr;
14825
14826 #ifdef TRILIBRARY
14827 if (!b->quiet) {
14828 printf("Writing edges.\n");
14829 }
14830
14831 if (*edgelist == (int *) NULL) {
14832 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14833 }
14834
14835 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14836 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14837 }
14838 elist = *edgelist;
14839 emlist = *edgemarkerlist;
14840 index = 0;
14841 #else
14842 if (!b->quiet) {
14843 printf("Writing %s.\n", edgefilename);
14844 }
14845 outfile = fopen(edgefilename, "w");
14846 if (outfile == (FILE *) NULL) {
14847 printf(" Error: Cannot create file %s.\n", edgefilename);
14848 triexit(1);
14849 }
14850
14851 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14852 #endif
14853
14854 traversalinit(&m->triangles);
14855 triangleloop.tri = triangletraverse(m);
14856 edgenumber = b->firstnumber;
14857
14858
14859
14860
14861
14862
14863 while (triangleloop.tri != (triangle *) NULL) {
14864 for (triangleloop.orient = 0; triangleloop.orient < 3;
14865 triangleloop.orient++) {
14866 sym(triangleloop, trisym);
14867 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14868 org(triangleloop, p1);
14869 dest(triangleloop, p2);
14870 #ifdef TRILIBRARY
14871 elist[index++] = vertexmark(p1);
14872 elist[index++] = vertexmark(p2);
14873 #endif
14874 if (b->nobound) {
14875 #ifndef TRILIBRARY
14876
14877 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14878 vertexmark(p1), vertexmark(p2));
14879 #endif
14880 } else {
14881
14882
14883 if (b->usesegments) {
14884 tspivot(triangleloop, checkmark);
14885 if (checkmark.ss == m->dummysub) {
14886 #ifdef TRILIBRARY
14887 emlist[edgenumber - b->firstnumber] = 0;
14888 #else
14889 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14890 vertexmark(p1), vertexmark(p2), 0);
14891 #endif
14892 } else {
14893 #ifdef TRILIBRARY
14894 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14895 #else
14896 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14897 vertexmark(p1), vertexmark(p2), mark(checkmark));
14898 #endif
14899 }
14900 } else {
14901 #ifdef TRILIBRARY
14902 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14903 #else
14904 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14905 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14906 #endif
14907 }
14908 }
14909 edgenumber++;
14910 }
14911 }
14912 triangleloop.tri = triangletraverse(m);
14913 }
14914
14915 #ifndef TRILIBRARY
14916 finishfile(outfile, argc, argv);
14917 #endif
14918 }
14919
14920
14921
14922
14923
14924
14925
14926
14927
14928
14929
14930
14931
14932
14933
14934
14935
14936 #ifdef TRILIBRARY
14937
14938 #ifdef ANSI_DECLARATORS
14939 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
14940 REAL **vpointattriblist, int **vpointmarkerlist,
14941 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
14942 #else
14943 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
14944 vedgelist, vedgemarkerlist, vnormlist)
14945 struct mesh *m;
14946 struct behavior *b;
14947 REAL **vpointlist;
14948 REAL **vpointattriblist;
14949 int **vpointmarkerlist;
14950 int **vedgelist;
14951 int **vedgemarkerlist;
14952 REAL **vnormlist;
14953 #endif
14954
14955 #else
14956
14957 #ifdef ANSI_DECLARATORS
14958 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
14959 char *vedgefilename, int argc, char **argv)
14960 #else
14961 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
14962 struct mesh *m;
14963 struct behavior *b;
14964 char *vnodefilename;
14965 char *vedgefilename;
14966 int argc;
14967 char **argv;
14968 #endif
14969
14970 #endif
14971
14972 {
14973 #ifdef TRILIBRARY
14974 REAL *plist;
14975 REAL *palist;
14976 int *elist;
14977 REAL *normlist;
14978 int coordindex;
14979 int attribindex;
14980 #else
14981 FILE *outfile;
14982 #endif
14983 struct otri triangleloop, trisym;
14984 vertex torg, tdest, tapex;
14985 REAL circumcenter[2];
14986 REAL xi, eta;
14987 long vnodenumber, vedgenumber;
14988 int p1, p2;
14989 int i;
14990 triangle ptr;
14991
14992 #ifdef TRILIBRARY
14993 if (!b->quiet) {
14994 printf("Writing Voronoi vertices.\n");
14995 }
14996
14997 if (*vpointlist == (REAL *) NULL) {
14998 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
14999 sizeof(REAL)));
15000 }
15001
15002 if (*vpointattriblist == (REAL *) NULL) {
15003 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15004 m->nextras * sizeof(REAL)));
15005 }
15006 *vpointmarkerlist = (int *) NULL;
15007 plist = *vpointlist;
15008 palist = *vpointattriblist;
15009 coordindex = 0;
15010 attribindex = 0;
15011 #else
15012 if (!b->quiet) {
15013 printf("Writing %s.\n", vnodefilename);
15014 }
15015 outfile = fopen(vnodefilename, "w");
15016 if (outfile == (FILE *) NULL) {
15017 printf(" Error: Cannot create file %s.\n", vnodefilename);
15018 triexit(1);
15019 }
15020
15021
15022 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15023 #endif
15024
15025 traversalinit(&m->triangles);
15026 triangleloop.tri = triangletraverse(m);
15027 triangleloop.orient = 0;
15028 vnodenumber = b->firstnumber;
15029 while (triangleloop.tri != (triangle *) NULL) {
15030 org(triangleloop, torg);
15031 dest(triangleloop, tdest);
15032 apex(triangleloop, tapex);
15033 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15034 #ifdef TRILIBRARY
15035
15036 plist[coordindex++] = circumcenter[0];
15037 plist[coordindex++] = circumcenter[1];
15038 for (i = 2; i < 2 + m->nextras; i++) {
15039
15040 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15041 + eta * (tapex[i] - torg[i]);
15042 }
15043 #else
15044
15045 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15046 circumcenter[1]);
15047 for (i = 2; i < 2 + m->nextras; i++) {
15048
15049 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15050 + eta * (tapex[i] - torg[i]));
15051 }
15052 fprintf(outfile, "\n");
15053 #endif
15054
15055 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15056 triangleloop.tri = triangletraverse(m);
15057 vnodenumber++;
15058 }
15059
15060 #ifndef TRILIBRARY
15061 finishfile(outfile, argc, argv);
15062 #endif
15063
15064 #ifdef TRILIBRARY
15065 if (!b->quiet) {
15066 printf("Writing Voronoi edges.\n");
15067 }
15068
15069 if (*vedgelist == (int *) NULL) {
15070 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15071 }
15072 *vedgemarkerlist = (int *) NULL;
15073
15074 if (*vnormlist == (REAL *) NULL) {
15075 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15076 }
15077 elist = *vedgelist;
15078 normlist = *vnormlist;
15079 coordindex = 0;
15080 #else
15081 if (!b->quiet) {
15082 printf("Writing %s.\n", vedgefilename);
15083 }
15084 outfile = fopen(vedgefilename, "w");
15085 if (outfile == (FILE *) NULL) {
15086 printf(" Error: Cannot create file %s.\n", vedgefilename);
15087 triexit(1);
15088 }
15089
15090 fprintf(outfile, "%ld %d\n", m->edges, 0);
15091 #endif
15092
15093 traversalinit(&m->triangles);
15094 triangleloop.tri = triangletraverse(m);
15095 vedgenumber = b->firstnumber;
15096
15097
15098
15099
15100
15101
15102 while (triangleloop.tri != (triangle *) NULL) {
15103 for (triangleloop.orient = 0; triangleloop.orient < 3;
15104 triangleloop.orient++) {
15105 sym(triangleloop, trisym);
15106 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15107
15108 p1 = * (int *) (triangleloop.tri + 6);
15109 if (trisym.tri == m->dummytri) {
15110 org(triangleloop, torg);
15111 dest(triangleloop, tdest);
15112 #ifdef TRILIBRARY
15113
15114 elist[coordindex] = p1;
15115 normlist[coordindex++] = tdest[1] - torg[1];
15116 elist[coordindex] = -1;
15117 normlist[coordindex++] = torg[0] - tdest[0];
15118 #else
15119
15120
15121
15122 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15123 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15124 #endif
15125 } else {
15126
15127 p2 = * (int *) (trisym.tri + 6);
15128
15129 #ifdef TRILIBRARY
15130 elist[coordindex] = p1;
15131 normlist[coordindex++] = 0.0;
15132 elist[coordindex] = p2;
15133 normlist[coordindex++] = 0.0;
15134 #else
15135 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15136 #endif
15137 }
15138 vedgenumber++;
15139 }
15140 }
15141 triangleloop.tri = triangletraverse(m);
15142 }
15143
15144 #ifndef TRILIBRARY
15145 finishfile(outfile, argc, argv);
15146 #endif
15147 }
15148
15149 #ifdef TRILIBRARY
15150
15151 #ifdef ANSI_DECLARATORS
15152 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15153 #else
15154 void writeneighbors(m, b, neighborlist)
15155 struct mesh *m;
15156 struct behavior *b;
15157 int **neighborlist;
15158 #endif
15159
15160 #else
15161
15162 #ifdef ANSI_DECLARATORS
15163 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15164 int argc, char **argv)
15165 #else
15166 void writeneighbors(m, b, neighborfilename, argc, argv)
15167 struct mesh *m;
15168 struct behavior *b;
15169 char *neighborfilename;
15170 int argc;
15171 char **argv;
15172 #endif
15173
15174 #endif
15175
15176 {
15177 #ifdef TRILIBRARY
15178 int *nlist;
15179 int index;
15180 #else
15181 FILE *outfile;
15182 #endif
15183 struct otri triangleloop, trisym;
15184 long elementnumber;
15185 int neighbor1, neighbor2, neighbor3;
15186 triangle ptr;
15187
15188 #ifdef TRILIBRARY
15189 if (!b->quiet) {
15190 printf("Writing neighbors.\n");
15191 }
15192
15193 if (*neighborlist == (int *) NULL) {
15194 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15195 sizeof(int)));
15196 }
15197 nlist = *neighborlist;
15198 index = 0;
15199 #else
15200 if (!b->quiet) {
15201 printf("Writing %s.\n", neighborfilename);
15202 }
15203 outfile = fopen(neighborfilename, "w");
15204 if (outfile == (FILE *) NULL) {
15205 printf(" Error: Cannot create file %s.\n", neighborfilename);
15206 triexit(1);
15207 }
15208
15209 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15210 #endif
15211
15212 traversalinit(&m->triangles);
15213 triangleloop.tri = triangletraverse(m);
15214 triangleloop.orient = 0;
15215 elementnumber = b->firstnumber;
15216 while (triangleloop.tri != (triangle *) NULL) {
15217 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15218 triangleloop.tri = triangletraverse(m);
15219 elementnumber++;
15220 }
15221 * (int *) (m->dummytri + 6) = -1;
15222
15223 traversalinit(&m->triangles);
15224 triangleloop.tri = triangletraverse(m);
15225 elementnumber = b->firstnumber;
15226 while (triangleloop.tri != (triangle *) NULL) {
15227 triangleloop.orient = 1;
15228 sym(triangleloop, trisym);
15229 neighbor1 = * (int *) (trisym.tri + 6);
15230 triangleloop.orient = 2;
15231 sym(triangleloop, trisym);
15232 neighbor2 = * (int *) (trisym.tri + 6);
15233 triangleloop.orient = 0;
15234 sym(triangleloop, trisym);
15235 neighbor3 = * (int *) (trisym.tri + 6);
15236 #ifdef TRILIBRARY
15237 nlist[index++] = neighbor1;
15238 nlist[index++] = neighbor2;
15239 nlist[index++] = neighbor3;
15240 #else
15241
15242 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15243 neighbor1, neighbor2, neighbor3);
15244 #endif
15245
15246 triangleloop.tri = triangletraverse(m);
15247 elementnumber++;
15248 }
15249
15250 #ifndef TRILIBRARY
15251 finishfile(outfile, argc, argv);
15252 #endif
15253 }
15254
15255
15256
15257
15258
15259
15260
15261
15262
15263
15264 #ifndef TRILIBRARY
15265
15266 #ifdef ANSI_DECLARATORS
15267 void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15268 int argc, char **argv)
15269 #else
15270 void writeoff(m, b, offfilename, argc, argv)
15271 struct mesh *m;
15272 struct behavior *b;
15273 char *offfilename;
15274 int argc;
15275 char **argv;
15276 #endif
15277
15278 {
15279 FILE *outfile;
15280 struct otri triangleloop;
15281 vertex vertexloop;
15282 vertex p1, p2, p3;
15283 long outvertices;
15284
15285 if (!b->quiet) {
15286 printf("Writing %s.\n", offfilename);
15287 }
15288
15289 if (b->jettison) {
15290 outvertices = m->vertices.items - m->undeads;
15291 } else {
15292 outvertices = m->vertices.items;
15293 }
15294
15295 outfile = fopen(offfilename, "w");
15296 if (outfile == (FILE *) NULL) {
15297 printf(" Error: Cannot create file %s.\n", offfilename);
15298 triexit(1);
15299 }
15300
15301 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15302 m->edges);
15303
15304
15305 traversalinit(&m->vertices);
15306 vertexloop = vertextraverse(m);
15307 while (vertexloop != (vertex) NULL) {
15308 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15309
15310 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15311 0.0);
15312 }
15313 vertexloop = vertextraverse(m);
15314 }
15315
15316
15317 traversalinit(&m->triangles);
15318 triangleloop.tri = triangletraverse(m);
15319 triangleloop.orient = 0;
15320 while (triangleloop.tri != (triangle *) NULL) {
15321 org(triangleloop, p1);
15322 dest(triangleloop, p2);
15323 apex(triangleloop, p3);
15324
15325 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15326 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15327 triangleloop.tri = triangletraverse(m);
15328 }
15329 finishfile(outfile, argc, argv);
15330 }
15331
15332 #endif
15333
15336
15337
15338
15339
15340
15341
15342
15343
15344 #ifdef ANSI_DECLARATORS
15345 void quality_statistics(struct mesh *m, struct behavior *b)
15346 #else
15347 void quality_statistics(m, b)
15348 struct mesh *m;
15349 struct behavior *b;
15350 #endif
15351
15352 {
15353 struct otri triangleloop;
15354 vertex p[3];
15355 REAL cossquaretable[8];
15356 REAL ratiotable[16];
15357 REAL dx[3], dy[3];
15358 REAL edgelength[3];
15359 REAL dotproduct;
15360 REAL cossquare;
15361 REAL triarea;
15362 REAL shortest, longest;
15363 REAL trilongest2;
15364 REAL smallestarea, biggestarea;
15365 REAL triminaltitude2;
15366 REAL minaltitude;
15367 REAL triaspect2;
15368 REAL worstaspect;
15369 REAL smallestangle, biggestangle;
15370 REAL radconst, degconst;
15371 int angletable[18];
15372 int aspecttable[16];
15373 int aspectindex;
15374 int tendegree;
15375 int acutebiggest;
15376 int i, ii, j, k;
15377
15378 printf("Mesh quality statistics:\n\n");
15379 radconst = PI / 18.0;
15380 degconst = 180.0 / PI;
15381 for (i = 0; i < 8; i++) {
15382 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15383 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15384 }
15385 for (i = 0; i < 18; i++) {
15386 angletable[i] = 0;
15387 }
15388
15389 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15390 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15391 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15392 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15393 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15394 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15395 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15396 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15397 for (i = 0; i < 16; i++) {
15398 aspecttable[i] = 0;
15399 }
15400
15401 worstaspect = 0.0;
15402 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15403 minaltitude = minaltitude * minaltitude;
15404 shortest = minaltitude;
15405 longest = 0.0;
15406 smallestarea = minaltitude;
15407 biggestarea = 0.0;
15408 worstaspect = 0.0;
15409 smallestangle = 0.0;
15410 biggestangle = 2.0;
15411 acutebiggest = 1;
15412
15413 traversalinit(&m->triangles);
15414 triangleloop.tri = triangletraverse(m);
15415 triangleloop.orient = 0;
15416 while (triangleloop.tri != (triangle *) NULL) {
15417 org(triangleloop, p[0]);
15418 dest(triangleloop, p[1]);
15419 apex(triangleloop, p[2]);
15420 trilongest2 = 0.0;
15421
15422 for (i = 0; i < 3; i++) {
15423 j = plus1mod3[i];
15424 k = minus1mod3[i];
15425 dx[i] = p[j][0] - p[k][0];
15426 dy[i] = p[j][1] - p[k][1];
15427 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15428 if (edgelength[i] > trilongest2) {
15429 trilongest2 = edgelength[i];
15430 }
15431 if (edgelength[i] > longest) {
15432 longest = edgelength[i];
15433 }
15434 if (edgelength[i] < shortest) {
15435 shortest = edgelength[i];
15436 }
15437 }
15438
15439 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15440 if (triarea < smallestarea) {
15441 smallestarea = triarea;
15442 }
15443 if (triarea > biggestarea) {
15444 biggestarea = triarea;
15445 }
15446 triminaltitude2 = triarea * triarea / trilongest2;
15447 if (triminaltitude2 < minaltitude) {
15448 minaltitude = triminaltitude2;
15449 }
15450 triaspect2 = trilongest2 / triminaltitude2;
15451 if (triaspect2 > worstaspect) {
15452 worstaspect = triaspect2;
15453 }
15454 aspectindex = 0;
15455 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15456 && (aspectindex < 15)) {
15457 aspectindex++;
15458 }
15459 aspecttable[aspectindex]++;
15460
15461 for (i = 0; i < 3; i++) {
15462 j = plus1mod3[i];
15463 k = minus1mod3[i];
15464 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15465 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15466 tendegree = 8;
15467 for (ii = 7; ii >= 0; ii--) {
15468 if (cossquare > cossquaretable[ii]) {
15469 tendegree = ii;
15470 }
15471 }
15472 if (dotproduct <= 0.0) {
15473 angletable[tendegree]++;
15474 if (cossquare > smallestangle) {
15475 smallestangle = cossquare;
15476 }
15477 if (acutebiggest && (cossquare < biggestangle)) {
15478 biggestangle = cossquare;
15479 }
15480 } else {
15481 angletable[17 - tendegree]++;
15482 if (acutebiggest || (cossquare > biggestangle)) {
15483 biggestangle = cossquare;
15484 acutebiggest = 0;
15485 }
15486 }
15487 }
15488 triangleloop.tri = triangletraverse(m);
15489 }
15490
15491 shortest = sqrt(shortest);
15492 longest = sqrt(longest);
15493 minaltitude = sqrt(minaltitude);
15494 worstaspect = sqrt(worstaspect);
15495 smallestarea *= 0.5;
15496 biggestarea *= 0.5;
15497 if (smallestangle >= 1.0) {
15498 smallestangle = 0.0;
15499 } else {
15500 smallestangle = degconst * acos(sqrt(smallestangle));
15501 }
15502 if (biggestangle >= 1.0) {
15503 biggestangle = 180.0;
15504 } else {
15505 if (acutebiggest) {
15506 biggestangle = degconst * acos(sqrt(biggestangle));
15507 } else {
15508 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15509 }
15510 }
15511
15512 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15513 smallestarea, biggestarea);
15514 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15515 shortest, longest);
15516 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15517 minaltitude, worstaspect);
15518
15519 printf(" Triangle aspect ratio histogram:\n");
15520 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15521 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15522 aspecttable[8]);
15523 for (i = 1; i < 7; i++) {
15524 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15525 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15526 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15527 }
15528 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15529 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15530 aspecttable[15]);
15531 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15532
15533 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15534 smallestangle, biggestangle);
15535
15536 printf(" Angle histogram:\n");
15537 for (i = 0; i < 9; i++) {
15538 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15539 i * 10, i * 10 + 10, angletable[i],
15540 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15541 }
15542 printf("\n");
15543 }
15544
15545
15546
15547
15548
15549
15550
15551 #ifdef ANSI_DECLARATORS
15552 void statistics(struct mesh *m, struct behavior *b)
15553 #else
15554 void statistics(m, b)
15555 struct mesh *m;
15556 struct behavior *b;
15557 #endif
15558
15559 {
15560 printf("\nStatistics:\n\n");
15561 printf(" Input vertices: %d\n", m->invertices);
15562 if (b->refine) {
15563 printf(" Input triangles: %d\n", m->inelements);
15564 }
15565 if (b->poly) {
15566 printf(" Input segments: %d\n", m->insegments);
15567 if (!b->refine) {
15568 printf(" Input holes: %d\n", m->holes);
15569 }
15570 }
15571
15572 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15573 printf(" Mesh triangles: %ld\n", m->triangles.items);
15574 printf(" Mesh edges: %ld\n", m->edges);
15575 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15576 if (b->poly || b->refine) {
15577 printf(" Mesh interior boundary edges: %ld\n",
15578 m->subsegs.items - m->hullsize);
15579 printf(" Mesh subsegments (constrained edges): %ld\n",
15580 m->subsegs.items);
15581 }
15582 printf("\n");
15583
15584 if (b->verbose) {
15585 quality_statistics(m, b);
15586 printf("Memory allocation statistics:\n\n");
15587 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15588 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15589 if (m->subsegs.maxitems > 0) {
15590 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15591 }
15592 if (m->viri.maxitems > 0) {
15593 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15594 }
15595 if (m->badsubsegs.maxitems > 0) {
15596 printf(" Maximum number of encroached subsegments: %ld\n",
15597 m->badsubsegs.maxitems);
15598 }
15599 if (m->badtriangles.maxitems > 0) {
15600 printf(" Maximum number of bad triangles: %ld\n",
15601 m->badtriangles.maxitems);
15602 }
15603 if (m->flipstackers.maxitems > 0) {
15604 printf(" Maximum number of stacked triangle flips: %ld\n",
15605 m->flipstackers.maxitems);
15606 }
15607 if (m->splaynodes.maxitems > 0) {
15608 printf(" Maximum number of splay tree nodes: %ld\n",
15609 m->splaynodes.maxitems);
15610 }
15611 printf(" Approximate heap memory use (bytes): %ld\n\n",
15612 m->vertices.maxitems * m->vertices.itembytes +
15613 m->triangles.maxitems * m->triangles.itembytes +
15614 m->subsegs.maxitems * m->subsegs.itembytes +
15615 m->viri.maxitems * m->viri.itembytes +
15616 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15617 m->badtriangles.maxitems * m->badtriangles.itembytes +
15618 m->flipstackers.maxitems * m->flipstackers.itembytes +
15619 m->splaynodes.maxitems * m->splaynodes.itembytes);
15620
15621 printf("Algorithmic statistics:\n\n");
15622 if (!b->weighted) {
15623 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15624 } else {
15625 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15626 }
15627 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15628 if (m->hyperbolacount > 0) {
15629 printf(" Number of right-of-hyperbola tests: %ld\n",
15630 m->hyperbolacount);
15631 }
15632 if (m->circletopcount > 0) {
15633 printf(" Number of circle top computations: %ld\n",
15634 m->circletopcount);
15635 }
15636 if (m->circumcentercount > 0) {
15637 printf(" Number of triangle circumcenter computations: %ld\n",
15638 m->circumcentercount);
15639 }
15640 printf("\n");
15641 }
15642 }
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
15654
15655
15656
15657
15658
15659
15660
15661
15662
15663
15664
15665
15666
15667
15668
15669
15670 #ifdef TRILIBRARY
15671
15672 #ifdef ANSI_DECLARATORS
15673 void triangulate(char *triswitches, struct triangulateio *in,
15674 struct triangulateio *out, struct triangulateio *vorout)
15675 #else
15676 void triangulate(triswitches, in, out, vorout)
15677 char *triswitches;
15678 struct triangulateio *in;
15679 struct triangulateio *out;
15680 struct triangulateio *vorout;
15681 #endif
15682
15683 #else
15684
15685 #ifdef ANSI_DECLARATORS
15686 #include "triangle.h"
15687 int ShewchukTRIANGLE(int argc, char **argv)
15688 #else
15689 #include "triangle.h"
15690 int ShewchukTRIANGLE(argc, argv)
15691 int argc;
15692 char **argv;
15693 #endif
15694
15695 #endif
15696
15697 {
15698 struct mesh m;
15699 struct behavior b;
15700 REAL *holearray;
15701 REAL *regionarray;
15702 #ifndef TRILIBRARY
15703 FILE *polyfile;
15704 #endif
15705
15706 #ifndef NO_TIMER
15707 #define NO_TIMER
15708 #endif
15709
15710 #ifndef NO_TIMER
15711
15712
15713 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15714 struct timezone tz;
15715 #endif
15716
15717 #ifndef NO_TIMER
15718 gettimeofday(&tv0, &tz);
15719 #endif
15720
15721 triangleinit(&m);
15722 #ifdef TRILIBRARY
15723 parsecommandline(1, &triswitches, &b);
15724 #else
15725 parsecommandline(argc, argv, &b);
15726 #endif
15727 m.steinerleft = b.steiner;
15728
15729 #ifdef TRILIBRARY
15730 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15731 in->pointmarkerlist, in->numberofpoints,
15732 in->numberofpointattributes);
15733 #else
15734 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15735 #endif
15736
15737 #ifndef NO_TIMER
15738 if (!b.quiet) {
15739 gettimeofday(&tv1, &tz);
15740 }
15741 #endif
15742
15743 #ifdef CDT_ONLY
15744 m.hullsize = delaunay(&m, &b);
15745 #else
15746 if (b.refine) {
15747
15748 #ifdef TRILIBRARY
15749 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15750 in->triangleattributelist, in->trianglearealist,
15751 in->numberoftriangles, in->numberofcorners,
15752 in->numberoftriangleattributes,
15753 in->segmentlist, in->segmentmarkerlist,
15754 in->numberofsegments);
15755 #else
15756 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15757 b.inpolyfilename, polyfile);
15758 #endif
15759 } else {
15760 m.hullsize = delaunay(&m, &b);
15761 }
15762 #endif
15763
15764 #ifndef NO_TIMER
15765 if (!b.quiet) {
15766 gettimeofday(&tv2, &tz);
15767 if (b.refine) {
15768 printf("Mesh reconstruction");
15769 } else {
15770 printf("Delaunay");
15771 }
15772 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15773 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15774 }
15775 #endif
15776
15777
15778
15779 m.infvertex1 = (vertex) NULL;
15780 m.infvertex2 = (vertex) NULL;
15781 m.infvertex3 = (vertex) NULL;
15782
15783 if (b.usesegments) {
15784 m.checksegments = 1;
15785 if (!b.refine) {
15786
15787 #ifdef TRILIBRARY
15788 formskeleton(&m, &b, in->segmentlist,
15789 in->segmentmarkerlist, in->numberofsegments);
15790 #else
15791 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15792 #endif
15793 }
15794 }
15795
15796 #ifndef NO_TIMER
15797 if (!b.quiet) {
15798 gettimeofday(&tv3, &tz);
15799 if (b.usesegments && !b.refine) {
15800 printf("Segment milliseconds: %ld\n",
15801 1000l * (tv3.tv_sec - tv2.tv_sec) +
15802 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15803 }
15804 }
15805 #endif
15806
15807 if (b.poly && (m.triangles.items > 0)) {
15808 #ifdef TRILIBRARY
15809 holearray = in->holelist;
15810 m.holes = in->numberofholes;
15811 regionarray = in->regionlist;
15812 m.regions = in->numberofregions;
15813 #else
15814 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15815 ®ionarray, &m.regions);
15816 #endif
15817 if (!b.refine) {
15818
15819 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15820 }
15821 } else {
15822
15823
15824
15825 m.holes = 0;
15826 m.regions = 0;
15827 }
15828
15829 #ifndef NO_TIMER
15830 if (!b.quiet) {
15831 gettimeofday(&tv4, &tz);
15832 if (b.poly && !b.refine) {
15833 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15834 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15835 }
15836 }
15837 #endif
15838
15839 #ifndef CDT_ONLY
15840 if (b.quality && (m.triangles.items > 0)) {
15841 enforcequality(&m, &b);
15842 }
15843 #endif
15844
15845 #ifndef NO_TIMER
15846 if (!b.quiet) {
15847 gettimeofday(&tv5, &tz);
15848 #ifndef CDT_ONLY
15849 if (b.quality) {
15850 printf("Quality milliseconds: %ld\n",
15851 1000l * (tv5.tv_sec - tv4.tv_sec) +
15852 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15853 }
15854 #endif
15855 }
15856 #endif
15857
15858
15859 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15860
15861 if (b.order > 1) {
15862 highorder(&m, &b);
15863 }
15864 if (!b.quiet) {
15865 printf("\n");
15866 }
15867
15868 #ifdef TRILIBRARY
15869 if (b.jettison) {
15870 out->numberofpoints = m.vertices.items - m.undeads;
15871 } else {
15872 out->numberofpoints = m.vertices.items;
15873 }
15874 out->numberofpointattributes = m.nextras;
15875 out->numberoftriangles = m.triangles.items;
15876 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15877 out->numberoftriangleattributes = m.eextras;
15878 out->numberofedges = m.edges;
15879 if (b.usesegments) {
15880 out->numberofsegments = m.subsegs.items;
15881 } else {
15882 out->numberofsegments = m.hullsize;
15883 }
15884 if (vorout != (struct triangulateio *) NULL) {
15885 vorout->numberofpoints = m.triangles.items;
15886 vorout->numberofpointattributes = m.nextras;
15887 vorout->numberofedges = m.edges;
15888 }
15889 #endif
15890
15891
15892 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15893 if (!b.quiet) {
15894 #ifdef TRILIBRARY
15895 printf("NOT writing vertices.\n");
15896 #else
15897 printf("NOT writing a .node file.\n");
15898 #endif
15899 }
15900 numbernodes(&m, &b);
15901 } else {
15902
15903 #ifdef TRILIBRARY
15904 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15905 &out->pointmarkerlist);
15906 #else
15907 writenodes(&m, &b, b.outnodefilename, argc, argv);
15908 #endif
15909 }
15910 if (b.noelewritten) {
15911 if (!b.quiet) {
15912 #ifdef TRILIBRARY
15913 printf("NOT writing triangles.\n");
15914 #else
15915 printf("NOT writing an .ele file.\n");
15916 #endif
15917 }
15918 } else {
15919 #ifdef TRILIBRARY
15920 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15921 #else
15922 writeelements(&m, &b, b.outelefilename, argc, argv);
15923 #endif
15924 }
15925
15926
15927 if (b.poly || b.convex) {
15928
15929 if (b.nopolywritten || b.noiterationnum) {
15930 if (!b.quiet) {
15931 #ifdef TRILIBRARY
15932 printf("NOT writing segments.\n");
15933 #else
15934 printf("NOT writing a .poly file.\n");
15935 #endif
15936 }
15937 } else {
15938 #ifdef TRILIBRARY
15939 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
15940 out->numberofholes = m.holes;
15941 out->numberofregions = m.regions;
15942 if (b.poly) {
15943 out->holelist = in->holelist;
15944 out->regionlist = in->regionlist;
15945 } else {
15946 out->holelist = (REAL *) NULL;
15947 out->regionlist = (REAL *) NULL;
15948 }
15949 #else
15950 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
15951 m.regions, argc, argv);
15952 #endif
15953 }
15954 }
15955 #ifndef TRILIBRARY
15956 #ifndef CDT_ONLY
15957 if (m.regions > 0) {
15958 trifree((VOID *) regionarray);
15959 }
15960 #endif
15961 if (m.holes > 0) {
15962 trifree((VOID *) holearray);
15963 }
15964 if (b.geomview) {
15965 writeoff(&m, &b, b.offfilename, argc, argv);
15966 }
15967 #endif
15968 if (b.edgesout) {
15969 #ifdef TRILIBRARY
15970 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
15971 #else
15972 writeedges(&m, &b, b.edgefilename, argc, argv);
15973 #endif
15974 }
15975 if (b.voronoi) {
15976 #ifdef TRILIBRARY
15977 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
15978 &vorout->pointmarkerlist, &vorout->edgelist,
15979 &vorout->edgemarkerlist, &vorout->normlist);
15980 #else
15981 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
15982 #endif
15983 }
15984 if (b.neighbors) {
15985 #ifdef TRILIBRARY
15986 writeneighbors(&m, &b, &out->neighborlist);
15987 #else
15988 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
15989 #endif
15990 }
15991
15992 if (!b.quiet) {
15993 #ifndef NO_TIMER
15994 gettimeofday(&tv6, &tz);
15995 printf("\nOutput milliseconds: %ld\n",
15996 1000l * (tv6.tv_sec - tv5.tv_sec) +
15997 (tv6.tv_usec - tv5.tv_usec) / 1000l);
15998 printf("Total running milliseconds: %ld\n",
15999 1000l * (tv6.tv_sec - tv0.tv_sec) +
16000 (tv6.tv_usec - tv0.tv_usec) / 1000l);
16001 #endif
16002
16003 statistics(&m, &b);
16004 }
16005
16006 #ifndef REDUCED
16007 if (b.docheck) {
16008 checkmesh(&m, &b);
16009 checkdelaunay(&m, &b);
16010 }
16011 #endif
16012
16013 triangledeinit(&m, &b);
16014 #ifndef TRILIBRARY
16015 return 0;
16016 #endif
16017 }