00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 #ifdef SINGLE
00221 #define REAL float
00222 #else
00223 #define REAL double
00224 #endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 #define INEXACT
00280
00281
00282
00283
00284 #define FILENAMESIZE 2048
00285
00286
00287
00288
00289 #define INPUTLINESIZE 1024
00290
00291
00292
00293
00294
00295 #define TRIPERBLOCK 4092
00296 #define SUBSEGPERBLOCK 508
00297 #define VERTEXPERBLOCK 4092
00298 #define VIRUSPERBLOCK 1020
00299
00300 #define BADSUBSEGPERBLOCK 252
00301
00302 #define BADTRIPERBLOCK 4092
00303
00304 #define FLIPSTACKERPERBLOCK 252
00305
00306 #define SPLAYNODEPERBLOCK 508
00307
00308
00309
00310
00311
00312 #define INPUTVERTEX 0
00313 #define SEGMENTVERTEX 1
00314 #define FREEVERTEX 2
00315 #define DEADVERTEX -32768
00316 #define UNDEADVERTEX -32767
00317
00318
00319
00320
00321
00322
00323 #ifdef _MSC_VER
00324 #else
00325
00326 #define VOID int
00327 #endif
00328
00329
00330
00331
00332
00333
00334
00335
00336 #define SAMPLEFACTOR 11
00337
00338
00339
00340
00341
00342 #define SAMPLERATE 10
00343
00344
00345
00346 #define PI 3.141592653589793238462643383279502884197169399375105820974944592308
00347
00348
00349
00350 #define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
00351
00352
00353
00354 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
00355
00356 #include <stdio.h>
00357 #include <stdlib.h>
00358 #include <string.h>
00359 #include <math.h>
00360 #ifndef NO_TIMER
00361 #ifdef _MSC_VER
00362 #include <time.h>
00363 #include <WinSock2.h>
00364 #include <windows.h>
00365
00366 #if defined(_MSC_EXTENSIONS)
00367 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
00368 #else
00369 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
00370 #endif
00371
00372 struct timezone
00373 {
00374 int tz_minuteswest;
00375 int tz_dsttime;
00376 };
00377
00378
00379
00380 int gettimeofday(struct timeval *tv, struct timezone *tz)
00381 {
00382
00383 FILETIME ft;
00384
00385
00386 unsigned __int64 tmpres = 0;
00387 static int tzflag = 0;
00388
00389 if (NULL != tv)
00390 {
00391 GetSystemTimeAsFileTime(&ft);
00392
00393
00394
00395
00396 tmpres |= ft.dwHighDateTime;
00397 tmpres <<= 32;
00398 tmpres |= ft.dwLowDateTime;
00399
00400
00401 tmpres /= 10;
00402
00403
00404
00405 tmpres -= DELTA_EPOCH_IN_MICROSECS;
00406
00407
00408
00409 tv->tv_sec = (long)(tmpres / 1000000UL);
00410 tv->tv_usec = (long)(tmpres % 1000000UL);
00411 }
00412
00413 if (NULL != tz)
00414 {
00415 if (!tzflag)
00416 {
00417 _tzset();
00418 tzflag++;
00419 }
00420
00421
00422 tz->tz_minuteswest = _timezone / 60;
00423 tz->tz_dsttime = _daylight;
00424 }
00425 return 0;
00426 }
00427 #else
00428 #include <sys/time.h>
00429 #endif
00430 #endif
00431 #ifdef CPU86
00432 #include <float.h>
00433 #endif
00434 #ifdef LINUX
00435 #include <fpu_control.h>
00436 #endif
00437 #ifdef TRILIBRARY
00438 #include "triangle.h"
00439 #endif
00440
00441
00442
00443 #ifndef TRILIBRARY
00444 char *readline();
00445 char *findfield();
00446 #endif
00447
00448
00449
00450
00451
00452 enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
00453
00454
00455
00456
00457
00458
00459
00460 enum insertvertexresult {SUCCESSFULVERTEX, ENCROACHINGVERTEX, VIOLATINGVERTEX,
00461 DUPLICATEVERTEX};
00462
00463
00464
00465
00466
00467
00468 enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 typedef REAL **triangle;
00588
00589
00590
00591
00592
00593
00594 struct otri {
00595 triangle *tri;
00596 int orient;
00597 };
00598
00599
00600
00601
00602
00603
00604 typedef REAL **subseg;
00605
00606
00607
00608
00609
00610
00611 struct osub {
00612 subseg *ss;
00613 int ssorient;
00614 };
00615
00616
00617
00618
00619
00620
00621 typedef REAL *vertex;
00622
00623
00624
00625
00626 struct badsubseg {
00627 subseg encsubseg;
00628 vertex subsegorg, subsegdest;
00629 };
00630
00631
00632
00633
00634
00635 struct badtriang {
00636 triangle poortri;
00637 REAL key;
00638 vertex triangorg, triangdest, triangapex;
00639 struct badtriang *nexttriang;
00640 };
00641
00642
00643
00644
00645
00646 struct flipstacker {
00647 triangle flippedtri;
00648 struct flipstacker* prevflip;
00649 };
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661 struct event {
00662 REAL xkey, ykey;
00663 VOID *eventptr;
00664 int heapposition;
00665 };
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 struct splaynode {
00679 struct otri keyedge;
00680 vertex keydest;
00681 struct splaynode *lchild, *rchild;
00682 };
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 struct memorypool {
00708 VOID **firstblock, **nowblock;
00709 VOID *nextitem;
00710 VOID *deaditemstack;
00711 VOID **pathblock;
00712 VOID* pathitem;
00713 int alignbytes;
00714 int itembytes;
00715 int itemsperblock;
00716 int itemsfirstblock;
00717 long items, maxitems;
00718 int unallocateditems;
00719 int pathitemsleft;
00720 };
00721
00722
00723
00724
00725 REAL splitter;
00726 REAL epsilon;
00727 REAL resulterrbound;
00728 REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
00729 REAL iccerrboundA, iccerrboundB, iccerrboundC;
00730 REAL o3derrboundA, o3derrboundB, o3derrboundC;
00731
00732
00733
00734 unsigned long randomseed;
00735
00736
00737
00738
00739
00740 struct mesh {
00741
00742
00743
00744
00745
00746 struct memorypool triangles;
00747 struct memorypool subsegs;
00748 struct memorypool vertices;
00749 struct memorypool viri;
00750 struct memorypool badsubsegs;
00751 struct memorypool badtriangles;
00752 struct memorypool flipstackers;
00753 struct memorypool splaynodes;
00754
00755
00756
00757
00758 struct badtriang *queuefront[4096];
00759 struct badtriang *queuetail[4096];
00760 int nextnonemptyq[4096];
00761 int firstnonemptyq;
00762
00763
00764
00765 struct flipstacker *lastflip;
00766
00767
00768
00769 REAL xmin, xmax, ymin, ymax;
00770 REAL xminextreme;
00771 int invertices;
00772 int inelements;
00773 int insegments;
00774 int holes;
00775 int regions;
00776 int undeads;
00777 long edges;
00778 int mesh_dim;
00779 int nextras;
00780 int eextras;
00781 long hullsize;
00782 int steinerleft;
00783 int vertexmarkindex;
00784 int vertex2triindex;
00785 int highorderindex;
00786 int elemattribindex;
00787 int areaboundindex;
00788 int checksegments;
00789 int checkquality;
00790 int readnodefile;
00791 long samples;
00792
00793 long incirclecount;
00794 long counterclockcount;
00795 long orient3dcount;
00796 long hyperbolacount;
00797 long circumcentercount;
00798 long circletopcount;
00799
00800
00801
00802 vertex infvertex1, infvertex2, infvertex3;
00803
00804
00805
00806 triangle *dummytri;
00807 triangle *dummytribase;
00808
00809
00810
00811
00812
00813 subseg *dummysub;
00814 subseg *dummysubbase;
00815
00816
00817
00818
00819 struct otri recenttri;
00820
00821 };
00822
00823
00824
00825
00826
00827 struct behavior {
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 int poly, refine, quality, vararea, fixedarea, usertest;
00863 int regionattrib, convex, weighted, jettison;
00864 int firstnumber;
00865 int edgesout, voronoi, neighbors, geomview;
00866 int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
00867 int noholes, noexact, conformdel;
00868 int incremental, sweepline, dwyer;
00869 int splitseg;
00870 int docheck;
00871 int quiet, verbose;
00872 int usesegments;
00873 int order;
00874 int nobisect;
00875 int steiner;
00876 REAL minangle, goodangle, offconstant;
00877 REAL maxarea;
00878
00879
00880
00881 #ifndef TRILIBRARY
00882 char innodefilename[FILENAMESIZE];
00883 char inelefilename[FILENAMESIZE];
00884 char inpolyfilename[FILENAMESIZE];
00885 char areafilename[FILENAMESIZE];
00886 char outnodefilename[FILENAMESIZE];
00887 char outelefilename[FILENAMESIZE];
00888 char outpolyfilename[FILENAMESIZE];
00889 char edgefilename[FILENAMESIZE];
00890 char vnodefilename[FILENAMESIZE];
00891 char vedgefilename[FILENAMESIZE];
00892 char neighborfilename[FILENAMESIZE];
00893 char offfilename[FILENAMESIZE];
00894 #endif
00895
00896 };
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01009
01010
01011 int plus1mod3[3] = {1, 2, 0};
01012 int minus1mod3[3] = {2, 0, 1};
01013
01014
01015
01016
01017
01018
01019
01020
01021 #define decode(ptr, otri) \
01022 (otri).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l); \
01023 (otri).tri = (triangle *) \
01024 ((unsigned long) (ptr) ^ (unsigned long) (otri).orient)
01025
01026
01027
01028
01029
01030 #define encode(otri) \
01031 (triangle) ((unsigned long) (otri).tri | (unsigned long) (otri).orient)
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041 #define sym(otri1, otri2) \
01042 ptr = (otri1).tri[(otri1).orient]; \
01043 decode(ptr, otri2);
01044
01045 #define symself(otri) \
01046 ptr = (otri).tri[(otri).orient]; \
01047 decode(ptr, otri);
01048
01049
01050
01051 #define lnext(otri1, otri2) \
01052 (otri2).tri = (otri1).tri; \
01053 (otri2).orient = plus1mod3[(otri1).orient]
01054
01055 #define lnextself(otri) \
01056 (otri).orient = plus1mod3[(otri).orient]
01057
01058
01059
01060 #define lprev(otri1, otri2) \
01061 (otri2).tri = (otri1).tri; \
01062 (otri2).orient = minus1mod3[(otri1).orient]
01063
01064 #define lprevself(otri) \
01065 (otri).orient = minus1mod3[(otri).orient]
01066
01067
01068
01069
01070
01071 #define onext(otri1, otri2) \
01072 lprev(otri1, otri2); \
01073 symself(otri2);
01074
01075 #define onextself(otri) \
01076 lprevself(otri); \
01077 symself(otri);
01078
01079
01080
01081
01082
01083 #define oprev(otri1, otri2) \
01084 sym(otri1, otri2); \
01085 lnextself(otri2);
01086
01087 #define oprevself(otri) \
01088 symself(otri); \
01089 lnextself(otri);
01090
01091
01092
01093
01094
01095 #define dnext(otri1, otri2) \
01096 sym(otri1, otri2); \
01097 lprevself(otri2);
01098
01099 #define dnextself(otri) \
01100 symself(otri); \
01101 lprevself(otri);
01102
01103
01104
01105
01106
01107 #define dprev(otri1, otri2) \
01108 lnext(otri1, otri2); \
01109 symself(otri2);
01110
01111 #define dprevself(otri) \
01112 lnextself(otri); \
01113 symself(otri);
01114
01115
01116
01117
01118
01119 #define rnext(otri1, otri2) \
01120 sym(otri1, otri2); \
01121 lnextself(otri2); \
01122 symself(otri2);
01123
01124 #define rnextself(otri) \
01125 symself(otri); \
01126 lnextself(otri); \
01127 symself(otri);
01128
01129
01130
01131
01132
01133 #define rprev(otri1, otri2) \
01134 sym(otri1, otri2); \
01135 lprevself(otri2); \
01136 symself(otri2);
01137
01138 #define rprevself(otri) \
01139 symself(otri); \
01140 lprevself(otri); \
01141 symself(otri);
01142
01143
01144
01145
01146 #define org(otri, vertexptr) \
01147 vertexptr = (vertex) (otri).tri[plus1mod3[(otri).orient] + 3]
01148
01149 #define dest(otri, vertexptr) \
01150 vertexptr = (vertex) (otri).tri[minus1mod3[(otri).orient] + 3]
01151
01152 #define apex(otri, vertexptr) \
01153 vertexptr = (vertex) (otri).tri[(otri).orient + 3]
01154
01155 #define setorg(otri, vertexptr) \
01156 (otri).tri[plus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01157
01158 #define setdest(otri, vertexptr) \
01159 (otri).tri[minus1mod3[(otri).orient] + 3] = (triangle) vertexptr
01160
01161 #define setapex(otri, vertexptr) \
01162 (otri).tri[(otri).orient + 3] = (triangle) vertexptr
01163
01164
01165
01166 #define bond(otri1, otri2) \
01167 (otri1).tri[(otri1).orient] = encode(otri2); \
01168 (otri2).tri[(otri2).orient] = encode(otri1)
01169
01170
01171
01172
01173
01174
01175 #define dissolve(otri) \
01176 (otri).tri[(otri).orient] = (triangle) m->dummytri
01177
01178
01179
01180 #define otricopy(otri1, otri2) \
01181 (otri2).tri = (otri1).tri; \
01182 (otri2).orient = (otri1).orient
01183
01184
01185
01186 #define otriequal(otri1, otri2) \
01187 (((otri1).tri == (otri2).tri) && \
01188 ((otri1).orient == (otri2).orient))
01189
01190
01191
01192
01193 #define infect(otri) \
01194 (otri).tri[6] = (triangle) \
01195 ((unsigned long) (otri).tri[6] | (unsigned long) 2l)
01196
01197 #define uninfect(otri) \
01198 (otri).tri[6] = (triangle) \
01199 ((unsigned long) (otri).tri[6] & ~ (unsigned long) 2l)
01200
01201
01202
01203 #define infected(otri) \
01204 (((unsigned long) (otri).tri[6] & (unsigned long) 2l) != 0l)
01205
01206
01207
01208 #define elemattribute(otri, attnum) \
01209 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)]
01210
01211 #define setelemattribute(otri, attnum, value) \
01212 ((REAL *) (otri).tri)[m->elemattribindex + (attnum)] = value
01213
01214
01215
01216 #define areabound(otri) ((REAL *) (otri).tri)[m->areaboundindex]
01217
01218 #define setareabound(otri, value) \
01219 ((REAL *) (otri).tri)[m->areaboundindex] = value
01220
01221
01222
01223
01224
01225
01226 #define deadtri(tria) ((tria)[1] == (triangle) NULL)
01227
01228 #define killtri(tria) \
01229 (tria)[1] = (triangle) NULL; \
01230 (tria)[3] = (triangle) NULL
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 #define sdecode(sptr, osub) \
01242 (osub).ssorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l); \
01243 (osub).ss = (subseg *) \
01244 ((unsigned long) (sptr) & ~ (unsigned long) 3l)
01245
01246
01247
01248
01249
01250 #define sencode(osub) \
01251 (subseg) ((unsigned long) (osub).ss | (unsigned long) (osub).ssorient)
01252
01253
01254
01255 #define ssym(osub1, osub2) \
01256 (osub2).ss = (osub1).ss; \
01257 (osub2).ssorient = 1 - (osub1).ssorient
01258
01259 #define ssymself(osub) \
01260 (osub).ssorient = 1 - (osub).ssorient
01261
01262
01263
01264
01265 #define spivot(osub1, osub2) \
01266 sptr = (osub1).ss[(osub1).ssorient]; \
01267 sdecode(sptr, osub2)
01268
01269 #define spivotself(osub) \
01270 sptr = (osub).ss[(osub).ssorient]; \
01271 sdecode(sptr, osub)
01272
01273
01274
01275
01276 #define snext(osub1, osub2) \
01277 sptr = (osub1).ss[1 - (osub1).ssorient]; \
01278 sdecode(sptr, osub2)
01279
01280 #define snextself(osub) \
01281 sptr = (osub).ss[1 - (osub).ssorient]; \
01282 sdecode(sptr, osub)
01283
01284
01285
01286
01287 #define sorg(osub, vertexptr) \
01288 vertexptr = (vertex) (osub).ss[2 + (osub).ssorient]
01289
01290 #define sdest(osub, vertexptr) \
01291 vertexptr = (vertex) (osub).ss[3 - (osub).ssorient]
01292
01293 #define setsorg(osub, vertexptr) \
01294 (osub).ss[2 + (osub).ssorient] = (subseg) vertexptr
01295
01296 #define setsdest(osub, vertexptr) \
01297 (osub).ss[3 - (osub).ssorient] = (subseg) vertexptr
01298
01299 #define segorg(osub, vertexptr) \
01300 vertexptr = (vertex) (osub).ss[4 + (osub).ssorient]
01301
01302 #define segdest(osub, vertexptr) \
01303 vertexptr = (vertex) (osub).ss[5 - (osub).ssorient]
01304
01305 #define setsegorg(osub, vertexptr) \
01306 (osub).ss[4 + (osub).ssorient] = (subseg) vertexptr
01307
01308 #define setsegdest(osub, vertexptr) \
01309 (osub).ss[5 - (osub).ssorient] = (subseg) vertexptr
01310
01311
01312
01313
01314
01315 #define mark(osub) (* (int *) ((osub).ss + 8))
01316
01317 #define setmark(osub, value) \
01318 * (int *) ((osub).ss + 8) = value
01319
01320
01321
01322 #define sbond(osub1, osub2) \
01323 (osub1).ss[(osub1).ssorient] = sencode(osub2); \
01324 (osub2).ss[(osub2).ssorient] = sencode(osub1)
01325
01326
01327
01328
01329 #define sdissolve(osub) \
01330 (osub).ss[(osub).ssorient] = (subseg) m->dummysub
01331
01332
01333
01334 #define subsegcopy(osub1, osub2) \
01335 (osub2).ss = (osub1).ss; \
01336 (osub2).ssorient = (osub1).ssorient
01337
01338
01339
01340 #define subsegequal(osub1, osub2) \
01341 (((osub1).ss == (osub2).ss) && \
01342 ((osub1).ssorient == (osub2).ssorient))
01343
01344
01345
01346
01347
01348
01349 #define deadsubseg(sub) ((sub)[1] == (subseg) NULL)
01350
01351 #define killsubseg(sub) \
01352 (sub)[1] = (subseg) NULL; \
01353 (sub)[2] = (subseg) NULL
01354
01355
01356
01357
01358
01359
01360
01361 #define tspivot(otri, osub) \
01362 sptr = (subseg) (otri).tri[6 + (otri).orient]; \
01363 sdecode(sptr, osub)
01364
01365
01366
01367
01368 #define stpivot(osub, otri) \
01369 ptr = (triangle) (osub).ss[6 + (osub).ssorient]; \
01370 decode(ptr, otri)
01371
01372
01373
01374 #define tsbond(otri, osub) \
01375 (otri).tri[6 + (otri).orient] = (triangle) sencode(osub); \
01376 (osub).ss[6 + (osub).ssorient] = (subseg) encode(otri)
01377
01378
01379
01380 #define tsdissolve(otri) \
01381 (otri).tri[6 + (otri).orient] = (triangle) m->dummysub
01382
01383
01384
01385 #define stdissolve(osub) \
01386 (osub).ss[6 + (osub).ssorient] = (subseg) m->dummytri
01387
01388
01389
01390
01391
01392 #define vertexmark(vx) ((int *) (vx))[m->vertexmarkindex]
01393
01394 #define setvertexmark(vx, value) \
01395 ((int *) (vx))[m->vertexmarkindex] = value
01396
01397 #define vertextype(vx) ((int *) (vx))[m->vertexmarkindex + 1]
01398
01399 #define setvertextype(vx, value) \
01400 ((int *) (vx))[m->vertexmarkindex + 1] = value
01401
01402 #define vertex2tri(vx) ((triangle *) (vx))[m->vertex2triindex]
01403
01404 #define setvertex2tri(vx, value) \
01405 ((triangle *) (vx))[m->vertex2triindex] = value
01406
01409
01410
01411
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 #ifdef EXTERNAL_TEST
01439
01440 int triunsuitable();
01441
01442 #else
01443
01444 #ifdef ANSI_DECLARATORS
01445 int triunsuitable(vertex triorg, vertex tridest, vertex triapex, REAL area)
01446 #else
01447 int triunsuitable(triorg, tridest, triapex, area)
01448 vertex triorg;
01449 vertex tridest;
01450 vertex triapex;
01451 REAL area;
01452 #endif
01453
01454 {
01455 REAL dxoa, dxda, dxod;
01456 REAL dyoa, dyda, dyod;
01457 REAL oalen, dalen, odlen;
01458 REAL maxlen;
01459
01460 dxoa = triorg[0] - triapex[0];
01461 dyoa = triorg[1] - triapex[1];
01462 dxda = tridest[0] - triapex[0];
01463 dyda = tridest[1] - triapex[1];
01464 dxod = triorg[0] - tridest[0];
01465 dyod = triorg[1] - tridest[1];
01466
01467 oalen = dxoa * dxoa + dyoa * dyoa;
01468 dalen = dxda * dxda + dyda * dyda;
01469 odlen = dxod * dxod + dyod * dyod;
01470
01471 maxlen = (dalen > oalen) ? dalen : oalen;
01472 maxlen = (odlen > maxlen) ? odlen : maxlen;
01473
01474 if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02) {
01475 return 1;
01476 } else {
01477 return 0;
01478 }
01479 }
01480
01481 #endif
01482
01485
01486
01487
01491 #ifdef ANSI_DECLARATORS
01492 void triexit(int status)
01493 #else
01494 void triexit(status)
01495 int status;
01496 #endif
01497
01498 {
01499 exit(status);
01500 }
01501
01502 #ifdef ANSI_DECLARATORS
01503 VOID *trimalloc(int size)
01504 #else
01505 VOID *trimalloc(size)
01506 int size;
01507 #endif
01508
01509 {
01510 VOID *memptr;
01511
01512 memptr = (VOID *) malloc((unsigned int) size);
01513 if (memptr == (VOID *) NULL) {
01514 printf("Error: Out of memory.\n");
01515 triexit(1);
01516 }
01517 return(memptr);
01518 }
01519
01520 #ifdef ANSI_DECLARATORS
01521 void trifree(VOID *memptr)
01522 #else
01523 void trifree(memptr)
01524 VOID *memptr;
01525 #endif
01526
01527 {
01528 free(memptr);
01529 }
01530
01533
01534
01535
01539
01540
01541
01542
01543
01544
01545 #ifndef TRILIBRARY
01546
01547 void syntax()
01548 {
01549 #ifdef CDT_ONLY
01550 #ifdef REDUCED
01551 printf("triangle [-pAcjevngBPNEIOXzo_lQVh] input_file\n");
01552 #else
01553 printf("triangle [-pAcjevngBPNEIOXzo_iFlCQVh] input_file\n");
01554 #endif
01555 #else
01556 #ifdef REDUCED
01557 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__lQVh] input_file\n");
01558 #else
01559 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
01560 #endif
01561 #endif
01562
01563 printf(" -p Triangulates a Planar Straight Line Graph (.poly file).\n");
01564 #ifndef CDT_ONLY
01565 printf(" -r Refines a previously generated mesh.\n");
01566 printf(
01567 " -q Quality mesh generation. A minimum angle may be specified.\n");
01568 printf(" -a Applies a maximum triangle area constraint.\n");
01569 printf(" -u Applies a user-defined triangle constraint.\n");
01570 #endif
01571 printf(
01572 " -A Applies attributes to identify triangles in certain regions.\n");
01573 printf(" -c Encloses the convex hull with segments.\n");
01574 #ifndef CDT_ONLY
01575 printf(" -D Conforming Delaunay: all triangles are truly Delaunay.\n");
01576 #endif
01577
01578
01579
01580
01581 printf(" -j Jettison unused vertices from output .node file.\n");
01582 printf(" -e Generates an edge list.\n");
01583 printf(" -v Generates a Voronoi diagram.\n");
01584 printf(" -n Generates a list of triangle neighbors.\n");
01585 printf(" -g Generates an .off file for Geomview.\n");
01586 printf(" -B Suppresses output of boundary information.\n");
01587 printf(" -P Suppresses output of .poly file.\n");
01588 printf(" -N Suppresses output of .node file.\n");
01589 printf(" -E Suppresses output of .ele file.\n");
01590 printf(" -I Suppresses mesh iteration numbers.\n");
01591 printf(" -O Ignores holes in .poly file.\n");
01592 printf(" -X Suppresses use of exact arithmetic.\n");
01593 printf(" -z Numbers all items starting from zero (rather than one).\n");
01594 printf(" -o2 Generates second-order subparametric elements.\n");
01595 #ifndef CDT_ONLY
01596 printf(" -Y Suppresses boundary segment splitting.\n");
01597 printf(" -S Specifies maximum number of added Steiner points.\n");
01598 #endif
01599 #ifndef REDUCED
01600 printf(" -i Uses incremental method, rather than divide-and-conquer.\n");
01601 printf(" -F Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
01602 #endif
01603 printf(" -l Uses vertical cuts only, rather than alternating cuts.\n");
01604 #ifndef REDUCED
01605 #ifndef CDT_ONLY
01606 printf(
01607 " -s Force segments into mesh by splitting (instead of using CDT).\n");
01608 #endif
01609 printf(" -C Check consistency of final mesh.\n");
01610 #endif
01611 printf(" -Q Quiet: No terminal output except errors.\n");
01612 printf(" -V Verbose: Detailed information on what I'm doing.\n");
01613 printf(" -h Help: Detailed instructions for Triangle.\n");
01614 triexit(0);
01615 }
01616
01617 #endif
01618
01619
01620
01621
01622
01623
01624
01625 #ifndef TRILIBRARY
01626
01627 void info()
01628 {
01629 printf("Triangle\n");
01630 printf(
01631 "A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
01632 printf("Version 1.6\n\n");
01633 printf(
01634 "Copyright 1993, 1995, 1997, 1998, 2002, 2005 Jonathan Richard Shewchuk\n");
01635 printf("2360 Woolsey #H / Berkeley, California 94705-1927\n");
01636 printf("Bugs/comments to jrs@cs.berkeley.edu\n");
01637 printf(
01638 "Created as part of the Quake project (tools for earthquake simulation).\n");
01639 printf(
01640 "Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
01641 printf("There is no warranty whatsoever. Use at your own risk.\n");
01642 #ifdef SINGLE
01643 printf("This executable is compiled for single precision arithmetic.\n\n\n");
01644 #else
01645 printf("This executable is compiled for double precision arithmetic.\n\n\n");
01646 #endif
01647 printf(
01648 "Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
01649 printf(
01650 "triangulations, conforming Delaunay triangulations, Voronoi diagrams, and\n");
01651 printf(
01652 "high-quality triangular meshes. The latter can be generated with no small\n"
01653 );
01654 printf(
01655 "or large angles, and are thus suitable for finite element analysis. If no\n"
01656 );
01657 printf(
01658 "command line switch is specified, your .node input file is read, and the\n");
01659 printf(
01660 "Delaunay triangulation is returned in .node and .ele output files. The\n");
01661 printf("command syntax is:\n\n");
01662 printf("triangle [-prq__a__uAcDjevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
01663 printf(
01664 "Underscores indicate that numbers may optionally follow certain switches.\n");
01665 printf(
01666 "Do not leave any space between a switch and its numeric parameter.\n");
01667 printf(
01668 "input_file must be a file with extension .node, or extension .poly if the\n");
01669 printf(
01670 "-p switch is used. If -r is used, you must supply .node and .ele files,\n");
01671 printf(
01672 "and possibly a .poly file and an .area file as well. The formats of these\n"
01673 );
01674 printf("files are described below.\n\n");
01675 printf("Command Line Switches:\n\n");
01676 printf(
01677 " -p Reads a Planar Straight Line Graph (.poly file), which can specify\n"
01678 );
01679 printf(
01680 " vertices, segments, holes, regional attributes, and regional area\n");
01681 printf(
01682 " constraints. Generates a constrained Delaunay triangulation (CDT)\n"
01683 );
01684 printf(
01685 " fitting the input; or, if -s, -q, -a, or -u is used, a conforming\n");
01686 printf(
01687 " constrained Delaunay triangulation (CCDT). If you want a truly\n");
01688 printf(
01689 " Delaunay (not just constrained Delaunay) triangulation, use -D as\n");
01690 printf(
01691 " well. When -p is not used, Triangle reads a .node file by default.\n"
01692 );
01693 printf(
01694 " -r Refines a previously generated mesh. The mesh is read from a .node\n"
01695 );
01696 printf(
01697 " file and an .ele file. If -p is also used, a .poly file is read\n");
01698 printf(
01699 " and used to constrain segments in the mesh. If -a is also used\n");
01700 printf(
01701 " (with no number following), an .area file is read and used to\n");
01702 printf(
01703 " impose area constraints on the mesh. Further details on refinement\n"
01704 );
01705 printf(" appear below.\n");
01706 printf(
01707 " -q Quality mesh generation by Delaunay refinement (a hybrid of Paul\n");
01708 printf(
01709 " Chew's and Jim Ruppert's algorithms). Adds vertices to the mesh to\n"
01710 );
01711 printf(
01712 " ensure that all angles are between 20 and 140 degrees. An\n");
01713 printf(
01714 " alternative bound on the minimum angle, replacing 20 degrees, may\n");
01715 printf(
01716 " be specified after the `q'. The specified angle may include a\n");
01717 printf(
01718 " decimal point, but not exponential notation. Note that a bound of\n"
01719 );
01720 printf(
01721 " theta degrees on the smallest angle also implies a bound of\n");
01722 printf(
01723 " (180 - 2 theta) on the largest angle. If the minimum angle is 28.6\n"
01724 );
01725 printf(
01726 " degrees or smaller, Triangle is mathematically guaranteed to\n");
01727 printf(
01728 " terminate (assuming infinite precision arithmetic--Triangle may\n");
01729 printf(
01730 " fail to terminate if you run out of precision). In practice,\n");
01731 printf(
01732 " Triangle often succeeds for minimum angles up to 34 degrees. For\n");
01733 printf(
01734 " some meshes, however, you might need to reduce the minimum angle to\n"
01735 );
01736 printf(
01737 " avoid problems associated with insufficient floating-point\n");
01738 printf(" precision.\n");
01739 printf(
01740 " -a Imposes a maximum triangle area. If a number follows the `a', no\n");
01741 printf(
01742 " triangle is generated whose area is larger than that number. If no\n"
01743 );
01744 printf(
01745 " number is specified, an .area file (if -r is used) or .poly file\n");
01746 printf(
01747 " (if -r is not used) specifies a set of maximum area constraints.\n");
01748 printf(
01749 " An .area file contains a separate area constraint for each\n");
01750 printf(
01751 " triangle, and is useful for refining a finite element mesh based on\n"
01752 );
01753 printf(
01754 " a posteriori error estimates. A .poly file can optionally contain\n"
01755 );
01756 printf(
01757 " an area constraint for each segment-bounded region, thereby\n");
01758 printf(
01759 " controlling triangle densities in a first triangulation of a PSLG.\n"
01760 );
01761 printf(
01762 " You can impose both a fixed area constraint and a varying area\n");
01763 printf(
01764 " constraint by invoking the -a switch twice, once with and once\n");
01765 printf(
01766 " without a number following. Each area specified may include a\n");
01767 printf(" decimal point.\n");
01768 printf(
01769 " -u Imposes a user-defined constraint on triangle size. There are two\n"
01770 );
01771 printf(
01772 " ways to use this feature. One is to edit the triunsuitable()\n");
01773 printf(
01774 " procedure in triangle.c to encode any constraint you like, then\n");
01775 printf(
01776 " recompile Triangle. The other is to compile triangle.c with the\n");
01777 printf(
01778 " EXTERNAL_TEST symbol set (compiler switch -DEXTERNAL_TEST), then\n");
01779 printf(
01780 " link Triangle with a separate object file that implements\n");
01781 printf(
01782 " triunsuitable(). In either case, the -u switch causes the user-\n");
01783 printf(" defined test to be applied to every triangle.\n");
01784 printf(
01785 " -A Assigns an additional floating-point attribute to each triangle\n");
01786 printf(
01787 " that identifies what segment-bounded region each triangle belongs\n");
01788 printf(
01789 " to. Attributes are assigned to regions by the .poly file. If a\n");
01790 printf(
01791 " region is not explicitly marked by the .poly file, triangles in\n");
01792 printf(
01793 " that region are assigned an attribute of zero. The -A switch has\n");
01794 printf(
01795 " an effect only when the -p switch is used and the -r switch is not.\n"
01796 );
01797 printf(
01798 " -c Creates segments on the convex hull of the triangulation. If you\n");
01799 printf(
01800 " are triangulating a vertex set, this switch causes a .poly file to\n"
01801 );
01802 printf(
01803 " be written, containing all edges of the convex hull. If you are\n");
01804 printf(
01805 " triangulating a PSLG, this switch specifies that the whole convex\n");
01806 printf(
01807 " hull of the PSLG should be triangulated, regardless of what\n");
01808 printf(
01809 " segments the PSLG has. If you do not use this switch when\n");
01810 printf(
01811 " triangulating a PSLG, Triangle assumes that you have identified the\n"
01812 );
01813 printf(
01814 " region to be triangulated by surrounding it with segments of the\n");
01815 printf(
01816 " input PSLG. Beware: if you are not careful, this switch can cause\n"
01817 );
01818 printf(
01819 " the introduction of an extremely thin angle between a PSLG segment\n"
01820 );
01821 printf(
01822 " and a convex hull segment, which can cause overrefinement (and\n");
01823 printf(
01824 " possibly failure if Triangle runs out of precision). If you are\n");
01825 printf(
01826 " refining a mesh, the -c switch works differently: it causes a\n");
01827 printf(
01828 " .poly file to be written containing the boundary edges of the mesh\n"
01829 );
01830 printf(" (useful if no .poly file was read).\n");
01831 printf(
01832 " -D Conforming Delaunay triangulation: use this switch if you want to\n"
01833 );
01834 printf(
01835 " ensure that all the triangles in the mesh are Delaunay, and not\n");
01836 printf(
01837 " merely constrained Delaunay; or if you want to ensure that all the\n"
01838 );
01839 printf(
01840 " Voronoi vertices lie within the triangulation. (Some finite volume\n"
01841 );
01842 printf(
01843 " methods have this requirement.) This switch invokes Ruppert's\n");
01844 printf(
01845 " original algorithm, which splits every subsegment whose diametral\n");
01846 printf(
01847 " circle is encroached. It usually increases the number of vertices\n"
01848 );
01849 printf(" and triangles.\n");
01850 printf(
01851 " -j Jettisons vertices that are not part of the final triangulation\n");
01852 printf(
01853 " from the output .node file. By default, Triangle copies all\n");
01854 printf(
01855 " vertices in the input .node file to the output .node file, in the\n");
01856 printf(
01857 " same order, so their indices do not change. The -j switch prevents\n"
01858 );
01859 printf(
01860 " duplicated input vertices, or vertices `eaten' by holes, from\n");
01861 printf(
01862 " appearing in the output .node file. Thus, if two input vertices\n");
01863 printf(
01864 " have exactly the same coordinates, only the first appears in the\n");
01865 printf(
01866 " output. If any vertices are jettisoned, the vertex numbering in\n");
01867 printf(
01868 " the output .node file differs from that of the input .node file.\n");
01869 printf(
01870 " -e Outputs (to an .edge file) a list of edges of the triangulation.\n");
01871 printf(
01872 " -v Outputs the Voronoi diagram associated with the triangulation.\n");
01873 printf(
01874 " Does not attempt to detect degeneracies, so some Voronoi vertices\n");
01875 printf(
01876 " may be duplicated. See the discussion of Voronoi diagrams below.\n");
01877 printf(
01878 " -n Outputs (to a .neigh file) a list of triangles neighboring each\n");
01879 printf(" triangle.\n");
01880 printf(
01881 " -g Outputs the mesh to an Object File Format (.off) file, suitable for\n"
01882 );
01883 printf(" viewing with the Geometry Center's Geomview package.\n");
01884 printf(
01885 " -B No boundary markers in the output .node, .poly, and .edge output\n");
01886 printf(
01887 " files. See the detailed discussion of boundary markers below.\n");
01888 printf(
01889 " -P No output .poly file. Saves disk space, but you lose the ability\n");
01890 printf(
01891 " to maintain constraining segments on later refinements of the mesh.\n"
01892 );
01893 printf(" -N No output .node file.\n");
01894 printf(" -E No output .ele file.\n");
01895 printf(
01896 " -I No iteration numbers. Suppresses the output of .node and .poly\n");
01897 printf(
01898 " files, so your input files won't be overwritten. (If your input is\n"
01899 );
01900 printf(
01901 " a .poly file only, a .node file is written.) Cannot be used with\n");
01902 printf(
01903 " the -r switch, because that would overwrite your input .ele file.\n");
01904 printf(
01905 " Shouldn't be used with the -q, -a, -u, or -s switch if you are\n");
01906 printf(
01907 " using a .node file for input, because no .node file is written, so\n"
01908 );
01909 printf(" there is no record of any added Steiner points.\n");
01910 printf(" -O No holes. Ignores the holes in the .poly file.\n");
01911 printf(
01912 " -X No exact arithmetic. Normally, Triangle uses exact floating-point\n"
01913 );
01914 printf(
01915 " arithmetic for certain tests if it thinks the inexact tests are not\n"
01916 );
01917 printf(
01918 " accurate enough. Exact arithmetic ensures the robustness of the\n");
01919 printf(
01920 " triangulation algorithms, despite floating-point roundoff error.\n");
01921 printf(
01922 " Disabling exact arithmetic with the -X switch causes a small\n");
01923 printf(
01924 " improvement in speed and creates the possibility that Triangle will\n"
01925 );
01926 printf(" fail to produce a valid mesh. Not recommended.\n");
01927 printf(
01928 " -z Numbers all items starting from zero (rather than one). Note that\n"
01929 );
01930 printf(
01931 " this switch is normally overridden by the value used to number the\n"
01932 );
01933 printf(
01934 " first vertex of the input .node or .poly file. However, this\n");
01935 printf(
01936 " switch is useful when calling Triangle from another program.\n");
01937 printf(
01938 " -o2 Generates second-order subparametric elements with six nodes each.\n"
01939 );
01940 printf(
01941 " -Y No new vertices on the boundary. This switch is useful when the\n");
01942 printf(
01943 " mesh boundary must be preserved so that it conforms to some\n");
01944 printf(
01945 " adjacent mesh. Be forewarned that you will probably sacrifice much\n"
01946 );
01947 printf(
01948 " of the quality of the mesh; Triangle will try, but the resulting\n");
01949 printf(
01950 " mesh may contain poorly shaped triangles. Works well if all the\n");
01951 printf(
01952 " boundary vertices are closely spaced. Specify this switch twice\n");
01953 printf(
01954 " (`-YY') to prevent all segment splitting, including internal\n");
01955 printf(" boundaries.\n");
01956 printf(
01957 " -S Specifies the maximum number of Steiner points (vertices that are\n");
01958 printf(
01959 " not in the input, but are added to meet the constraints on minimum\n"
01960 );
01961 printf(
01962 " angle and maximum area). The default is to allow an unlimited\n");
01963 printf(
01964 " number. If you specify this switch with no number after it,\n");
01965 printf(
01966 " the limit is set to zero. Triangle always adds vertices at segment\n"
01967 );
01968 printf(
01969 " intersections, even if it needs to use more vertices than the limit\n"
01970 );
01971 printf(
01972 " you set. When Triangle inserts segments by splitting (-s), it\n");
01973 printf(
01974 " always adds enough vertices to ensure that all the segments of the\n"
01975 );
01976 printf(" PLSG are recovered, ignoring the limit if necessary.\n");
01977 printf(
01978 " -i Uses an incremental rather than a divide-and-conquer algorithm to\n");
01979 printf(
01980 " construct a Delaunay triangulation. Try it if the divide-and-\n");
01981 printf(" conquer algorithm fails.\n");
01982 printf(
01983 " -F Uses Steven Fortune's sweepline algorithm to construct a Delaunay\n");
01984 printf(
01985 " triangulation. Warning: does not use exact arithmetic for all\n");
01986 printf(" calculations. An exact result is not guaranteed.\n");
01987 printf(
01988 " -l Uses only vertical cuts in the divide-and-conquer algorithm. By\n");
01989 printf(
01990 " default, Triangle alternates between vertical and horizontal cuts,\n"
01991 );
01992 printf(
01993 " which usually improve the speed except with vertex sets that are\n");
01994 printf(
01995 " small or short and wide. This switch is primarily of theoretical\n");
01996 printf(" interest.\n");
01997 printf(
01998 " -s Specifies that segments should be forced into the triangulation by\n"
01999 );
02000 printf(
02001 " recursively splitting them at their midpoints, rather than by\n");
02002 printf(
02003 " generating a constrained Delaunay triangulation. Segment splitting\n"
02004 );
02005 printf(
02006 " is true to Ruppert's original algorithm, but can create needlessly\n"
02007 );
02008 printf(
02009 " small triangles. This switch is primarily of theoretical interest.\n"
02010 );
02011 printf(
02012 " -C Check the consistency of the final mesh. Uses exact arithmetic for\n"
02013 );
02014 printf(
02015 " checking, even if the -X switch is used. Useful if you suspect\n");
02016 printf(" Triangle is buggy.\n");
02017 printf(
02018 " -Q Quiet: Suppresses all explanation of what Triangle is doing,\n");
02019 printf(" unless an error occurs.\n");
02020 printf(
02021 " -V Verbose: Gives detailed information about what Triangle is doing.\n"
02022 );
02023 printf(
02024 " Add more `V's for increasing amount of detail. `-V' is most\n");
02025 printf(
02026 " useful; itgives information on algorithmic progress and much more\n");
02027 printf(
02028 " detailed statistics. `-VV' gives vertex-by-vertex details, and\n");
02029 printf(
02030 " prints so much that Triangle runs much more slowly. `-VVVV' gives\n"
02031 );
02032 printf(" information only a debugger could love.\n");
02033 printf(" -h Help: Displays these instructions.\n");
02034 printf("\n");
02035 printf("Definitions:\n");
02036 printf("\n");
02037 printf(
02038 " A Delaunay triangulation of a vertex set is a triangulation whose\n");
02039 printf(
02040 " vertices are the vertex set, that covers the convex hull of the vertex\n");
02041 printf(
02042 " set. A Delaunay triangulation has the property that no vertex lies\n");
02043 printf(
02044 " inside the circumscribing circle (circle that passes through all three\n");
02045 printf(" vertices) of any triangle in the triangulation.\n\n");
02046 printf(
02047 " A Voronoi diagram of a vertex set is a subdivision of the plane into\n");
02048 printf(
02049 " polygonal cells (some of which may be unbounded, meaning infinitely\n");
02050 printf(
02051 " large), where each cell is the set of points in the plane that are closer\n"
02052 );
02053 printf(
02054 " to some input vertex than to any other input vertex. The Voronoi diagram\n"
02055 );
02056 printf(" is a geometric dual of the Delaunay triangulation.\n\n");
02057 printf(
02058 " A Planar Straight Line Graph (PSLG) is a set of vertices and segments.\n");
02059 printf(
02060 " Segments are simply edges, whose endpoints are all vertices in the PSLG.\n"
02061 );
02062 printf(
02063 " Segments may intersect each other only at their endpoints. The file\n");
02064 printf(" format for PSLGs (.poly files) is described below.\n\n");
02065 printf(
02066 " A constrained Delaunay triangulation (CDT) of a PSLG is similar to a\n");
02067 printf(
02068 " Delaunay triangulation, but each PSLG segment is present as a single edge\n"
02069 );
02070 printf(
02071 " of the CDT. (A constrained Delaunay triangulation is not truly a\n");
02072 printf(
02073 " Delaunay triangulation, because some of its triangles might not be\n");
02074 printf(
02075 " Delaunay.) By definition, a CDT does not have any vertices other than\n");
02076 printf(
02077 " those specified in the input PSLG. Depending on context, a CDT might\n");
02078 printf(
02079 " cover the convex hull of the PSLG, or it might cover only a segment-\n");
02080 printf(" bounded region (e.g. a polygon).\n\n");
02081 printf(
02082 " A conforming Delaunay triangulation of a PSLG is a triangulation in which\n"
02083 );
02084 printf(
02085 " each triangle is truly Delaunay, and each PSLG segment is represented by\n"
02086 );
02087 printf(
02088 " a linear contiguous sequence of edges of the triangulation. New vertices\n"
02089 );
02090 printf(
02091 " (not part of the PSLG) may appear, and each input segment may have been\n");
02092 printf(
02093 " subdivided into shorter edges (subsegments) by these additional vertices.\n"
02094 );
02095 printf(
02096 " The new vertices are frequently necessary to maintain the Delaunay\n");
02097 printf(" property while ensuring that every segment is represented.\n\n");
02098 printf(
02099 " A conforming constrained Delaunay triangulation (CCDT) of a PSLG is a\n");
02100 printf(
02101 " triangulation of a PSLG whose triangles are constrained Delaunay. New\n");
02102 printf(" vertices may appear, and input segments may be subdivided into\n");
02103 printf(
02104 " subsegments, but not to guarantee that segments are respected; rather, to\n"
02105 );
02106 printf(
02107 " improve the quality of the triangles. The high-quality meshes produced\n");
02108 printf(
02109 " by the -q switch are usually CCDTs, but can be made conforming Delaunay\n");
02110 printf(" with the -D switch.\n\n");
02111 printf("File Formats:\n\n");
02112 printf(
02113 " All files may contain comments prefixed by the character '#'. Vertices,\n"
02114 );
02115 printf(
02116 " triangles, edges, holes, and maximum area constraints must be numbered\n");
02117 printf(
02118 " consecutively, starting from either 1 or 0. Whichever you choose, all\n");
02119 printf(
02120 " input files must be consistent; if the vertices are numbered from 1, so\n");
02121 printf(
02122 " must be all other objects. Triangle automatically detects your choice\n");
02123 printf(
02124 " while reading the .node (or .poly) file. (When calling Triangle from\n");
02125 printf(
02126 " another program, use the -z switch if you wish to number objects from\n");
02127 printf(" zero.) Examples of these file formats are given below.\n\n");
02128 printf(" .node files:\n");
02129 printf(
02130 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02131 );
02132 printf(
02133 " <# of boundary markers (0 or 1)>\n"
02134 );
02135 printf(
02136 " Remaining lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02137 printf("\n");
02138 printf(
02139 " The attributes, which are typically floating-point values of physical\n");
02140 printf(
02141 " quantities (such as mass or conductivity) associated with the nodes of\n"
02142 );
02143 printf(
02144 " a finite element mesh, are copied unchanged to the output mesh. If -q,\n"
02145 );
02146 printf(
02147 " -a, -u, -D, or -s is selected, each new Steiner point added to the mesh\n"
02148 );
02149 printf(" has attributes assigned to it by linear interpolation.\n\n");
02150 printf(
02151 " If the fourth entry of the first line is `1', the last column of the\n");
02152 printf(
02153 " remainder of the file is assumed to contain boundary markers. Boundary\n"
02154 );
02155 printf(
02156 " markers are used to identify boundary vertices and vertices resting on\n"
02157 );
02158 printf(
02159 " PSLG segments; a complete description appears in a section below. The\n"
02160 );
02161 printf(
02162 " .node file produced by Triangle contains boundary markers in the last\n");
02163 printf(" column unless they are suppressed by the -B switch.\n\n");
02164 printf(" .ele files:\n");
02165 printf(
02166 " First line: <# of triangles> <nodes per triangle> <# of attributes>\n");
02167 printf(
02168 " Remaining lines: <triangle #> <node> <node> <node> ... [attributes]\n");
02169 printf("\n");
02170 printf(
02171 " Nodes are indices into the corresponding .node file. The first three\n");
02172 printf(
02173 " nodes are the corner vertices, and are listed in counterclockwise order\n"
02174 );
02175 printf(
02176 " around each triangle. (The remaining nodes, if any, depend on the type\n"
02177 );
02178 printf(" of finite element used.)\n\n");
02179 printf(
02180 " The attributes are just like those of .node files. Because there is no\n"
02181 );
02182 printf(
02183 " simple mapping from input to output triangles, Triangle attempts to\n");
02184 printf(
02185 " interpolate attributes, and may cause a lot of diffusion of attributes\n"
02186 );
02187 printf(
02188 " among nearby triangles as the triangulation is refined. Attributes do\n"
02189 );
02190 printf(" not diffuse across segments, so attributes used to identify\n");
02191 printf(" segment-bounded regions remain intact.\n\n");
02192 printf(
02193 " In .ele files produced by Triangle, each triangular element has three\n");
02194 printf(
02195 " nodes (vertices) unless the -o2 switch is used, in which case\n");
02196 printf(
02197 " subparametric quadratic elements with six nodes each are generated.\n");
02198 printf(
02199 " The first three nodes are the corners in counterclockwise order, and\n");
02200 printf(
02201 " the fourth, fifth, and sixth nodes lie on the midpoints of the edges\n");
02202 printf(
02203 " opposite the first, second, and third vertices, respectively.\n");
02204 printf("\n");
02205 printf(" .poly files:\n");
02206 printf(
02207 " First line: <# of vertices> <dimension (must be 2)> <# of attributes>\n"
02208 );
02209 printf(
02210 " <# of boundary markers (0 or 1)>\n"
02211 );
02212 printf(
02213 " Following lines: <vertex #> <x> <y> [attributes] [boundary marker]\n");
02214 printf(" One line: <# of segments> <# of boundary markers (0 or 1)>\n");
02215 printf(
02216 " Following lines: <segment #> <endpoint> <endpoint> [boundary marker]\n");
02217 printf(" One line: <# of holes>\n");
02218 printf(" Following lines: <hole #> <x> <y>\n");
02219 printf(
02220 " Optional line: <# of regional attributes and/or area constraints>\n");
02221 printf(
02222 " Optional following lines: <region #> <x> <y> <attribute> <max area>\n");
02223 printf("\n");
02224 printf(
02225 " A .poly file represents a PSLG, as well as some additional information.\n"
02226 );
02227 printf(
02228 " The first section lists all the vertices, and is identical to the\n");
02229 printf(
02230 " format of .node files. <# of vertices> may be set to zero to indicate\n"
02231 );
02232 printf(
02233 " that the vertices are listed in a separate .node file; .poly files\n");
02234 printf(
02235 " produced by Triangle always have this format. A vertex set represented\n"
02236 );
02237 printf(
02238 " this way has the advantage that it may easily be triangulated with or\n");
02239 printf(
02240 " without segments (depending on whether the -p switch is invoked).\n");
02241 printf("\n");
02242 printf(
02243 " The second section lists the segments. Segments are edges whose\n");
02244 printf(
02245 " presence in the triangulation is enforced. (Depending on the choice of\n"
02246 );
02247 printf(
02248 " switches, segment might be subdivided into smaller edges). Each\n");
02249 printf(
02250 " segment is specified by listing the indices of its two endpoints. This\n"
02251 );
02252 printf(
02253 " means that you must include its endpoints in the vertex list. Each\n");
02254 printf(" segment, like each point, may have a boundary marker.\n\n");
02255 printf(
02256 " If -q, -a, -u, and -s are not selected, Triangle produces a constrained\n"
02257 );
02258 printf(
02259 " Delaunay triangulation (CDT), in which each segment appears as a single\n"
02260 );
02261 printf(
02262 " edge in the triangulation. If -q, -a, -u, or -s is selected, Triangle\n"
02263 );
02264 printf(
02265 " produces a conforming constrained Delaunay triangulation (CCDT), in\n");
02266 printf(
02267 " which segments may be subdivided into smaller edges. If -D is\n");
02268 printf(
02269 " selected, Triangle produces a conforming Delaunay triangulation, so\n");
02270 printf(
02271 " that every triangle is Delaunay, and not just constrained Delaunay.\n");
02272 printf("\n");
02273 printf(
02274 " The third section lists holes (and concavities, if -c is selected) in\n");
02275 printf(
02276 " the triangulation. Holes are specified by identifying a point inside\n");
02277 printf(
02278 " each hole. After the triangulation is formed, Triangle creates holes\n");
02279 printf(
02280 " by eating triangles, spreading out from each hole point until its\n");
02281 printf(
02282 " progress is blocked by segments in the PSLG. You must be careful to\n");
02283 printf(
02284 " enclose each hole in segments, or your whole triangulation might be\n");
02285 printf(
02286 " eaten away. If the two triangles abutting a segment are eaten, the\n");
02287 printf(
02288 " segment itself is also eaten. Do not place a hole directly on a\n");
02289 printf(" segment; if you do, Triangle chooses one side of the segment\n");
02290 printf(" arbitrarily.\n\n");
02291 printf(
02292 " The optional fourth section lists regional attributes (to be assigned\n");
02293 printf(
02294 " to all triangles in a region) and regional constraints on the maximum\n");
02295 printf(
02296 " triangle area. Triangle reads this section only if the -A switch is\n");
02297 printf(
02298 " used or the -a switch is used without a number following it, and the -r\n"
02299 );
02300 printf(
02301 " switch is not used. Regional attributes and area constraints are\n");
02302 printf(
02303 " propagated in the same manner as holes: you specify a point for each\n");
02304 printf(
02305 " attribute and/or constraint, and the attribute and/or constraint\n");
02306 printf(
02307 " affects the whole region (bounded by segments) containing the point.\n");
02308 printf(
02309 " If two values are written on a line after the x and y coordinate, the\n");
02310 printf(
02311 " first such value is assumed to be a regional attribute (but is only\n");
02312 printf(
02313 " applied if the -A switch is selected), and the second value is assumed\n"
02314 );
02315 printf(
02316 " to be a regional area constraint (but is only applied if the -a switch\n"
02317 );
02318 printf(
02319 " is selected). You may specify just one value after the coordinates,\n");
02320 printf(
02321 " which can serve as both an attribute and an area constraint, depending\n"
02322 );
02323 printf(
02324 " on the choice of switches. If you are using the -A and -a switches\n");
02325 printf(
02326 " simultaneously and wish to assign an attribute to some region without\n");
02327 printf(" imposing an area constraint, use a negative maximum area.\n\n");
02328 printf(
02329 " When a triangulation is created from a .poly file, you must either\n");
02330 printf(
02331 " enclose the entire region to be triangulated in PSLG segments, or\n");
02332 printf(
02333 " use the -c switch, which automatically creates extra segments that\n");
02334 printf(
02335 " enclose the convex hull of the PSLG. If you do not use the -c switch,\n"
02336 );
02337 printf(
02338 " Triangle eats all triangles that are not enclosed by segments; if you\n");
02339 printf(
02340 " are not careful, your whole triangulation may be eaten away. If you do\n"
02341 );
02342 printf(
02343 " use the -c switch, you can still produce concavities by the appropriate\n"
02344 );
02345 printf(
02346 " placement of holes just inside the boundary of the convex hull.\n");
02347 printf("\n");
02348 printf(
02349 " An ideal PSLG has no intersecting segments, nor any vertices that lie\n");
02350 printf(
02351 " upon segments (except, of course, the endpoints of each segment). You\n"
02352 );
02353 printf(
02354 " aren't required to make your .poly files ideal, but you should be aware\n"
02355 );
02356 printf(
02357 " of what can go wrong. Segment intersections are relatively safe--\n");
02358 printf(
02359 " Triangle calculates the intersection points for you and adds them to\n");
02360 printf(
02361 " the triangulation--as long as your machine's floating-point precision\n");
02362 printf(
02363 " doesn't become a problem. You are tempting the fates if you have three\n"
02364 );
02365 printf(
02366 " segments that cross at the same location, and expect Triangle to figure\n"
02367 );
02368 printf(
02369 " out where the intersection point is. Thanks to floating-point roundoff\n"
02370 );
02371 printf(
02372 " error, Triangle will probably decide that the three segments intersect\n"
02373 );
02374 printf(
02375 " at three different points, and you will find a minuscule triangle in\n");
02376 printf(
02377 " your output--unless Triangle tries to refine the tiny triangle, uses\n");
02378 printf(
02379 " up the last bit of machine precision, and fails to terminate at all.\n");
02380 printf(
02381 " You're better off putting the intersection point in the input files,\n");
02382 printf(
02383 " and manually breaking up each segment into two. Similarly, if you\n");
02384 printf(
02385 " place a vertex at the middle of a segment, and hope that Triangle will\n"
02386 );
02387 printf(
02388 " break up the segment at that vertex, you might get lucky. On the other\n"
02389 );
02390 printf(
02391 " hand, Triangle might decide that the vertex doesn't lie precisely on\n");
02392 printf(
02393 " the segment, and you'll have a needle-sharp triangle in your output--or\n"
02394 );
02395 printf(" a lot of tiny triangles if you're generating a quality mesh.\n");
02396 printf("\n");
02397 printf(
02398 " When Triangle reads a .poly file, it also writes a .poly file, which\n");
02399 printf(
02400 " includes all the subsegments--the edges that are parts of input\n");
02401 printf(
02402 " segments. If the -c switch is used, the output .poly file also\n");
02403 printf(
02404 " includes all of the edges on the convex hull. Hence, the output .poly\n"
02405 );
02406 printf(
02407 " file is useful for finding edges associated with input segments and for\n"
02408 );
02409 printf(
02410 " setting boundary conditions in finite element simulations. Moreover,\n");
02411 printf(
02412 " you will need the output .poly file if you plan to refine the output\n");
02413 printf(
02414 " mesh, and don't want segments to be missing in later triangulations.\n");
02415 printf("\n");
02416 printf(" .area files:\n");
02417 printf(" First line: <# of triangles>\n");
02418 printf(" Following lines: <triangle #> <maximum area>\n");
02419 printf("\n");
02420 printf(
02421 " An .area file associates with each triangle a maximum area that is used\n"
02422 );
02423 printf(
02424 " for mesh refinement. As with other file formats, every triangle must\n");
02425 printf(
02426 " be represented, and the triangles must be numbered consecutively. A\n");
02427 printf(
02428 " triangle may be left unconstrained by assigning it a negative maximum\n");
02429 printf(" area.\n\n");
02430 printf(" .edge files:\n");
02431 printf(" First line: <# of edges> <# of boundary markers (0 or 1)>\n");
02432 printf(
02433 " Following lines: <edge #> <endpoint> <endpoint> [boundary marker]\n");
02434 printf("\n");
02435 printf(
02436 " Endpoints are indices into the corresponding .node file. Triangle can\n"
02437 );
02438 printf(
02439 " produce .edge files (use the -e switch), but cannot read them. The\n");
02440 printf(
02441 " optional column of boundary markers is suppressed by the -B switch.\n");
02442 printf("\n");
02443 printf(
02444 " In Voronoi diagrams, one also finds a special kind of edge that is an\n");
02445 printf(
02446 " infinite ray with only one endpoint. For these edges, a different\n");
02447 printf(" format is used:\n\n");
02448 printf(" <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
02449 printf(
02450 " The `direction' is a floating-point vector that indicates the direction\n"
02451 );
02452 printf(" of the infinite ray.\n\n");
02453 printf(" .neigh files:\n");
02454 printf(
02455 " First line: <# of triangles> <# of neighbors per triangle (always 3)>\n"
02456 );
02457 printf(
02458 " Following lines: <triangle #> <neighbor> <neighbor> <neighbor>\n");
02459 printf("\n");
02460 printf(
02461 " Neighbors are indices into the corresponding .ele file. An index of -1\n"
02462 );
02463 printf(
02464 " indicates no neighbor (because the triangle is on an exterior\n");
02465 printf(
02466 " boundary). The first neighbor of triangle i is opposite the first\n");
02467 printf(" corner of triangle i, and so on.\n\n");
02468 printf(
02469 " Triangle can produce .neigh files (use the -n switch), but cannot read\n"
02470 );
02471 printf(" them.\n\n");
02472 printf("Boundary Markers:\n\n");
02473 printf(
02474 " Boundary markers are tags used mainly to identify which output vertices\n");
02475 printf(
02476 " and edges are associated with which PSLG segment, and to identify which\n");
02477 printf(
02478 " vertices and edges occur on a boundary of the triangulation. A common\n");
02479 printf(
02480 " use is to determine where boundary conditions should be applied to a\n");
02481 printf(
02482 " finite element mesh. You can prevent boundary markers from being written\n"
02483 );
02484 printf(" into files produced by Triangle by using the -B switch.\n\n");
02485 printf(
02486 " The boundary marker associated with each segment in an output .poly file\n"
02487 );
02488 printf(" and each edge in an output .edge file is chosen as follows:\n");
02489 printf(
02490 " - If an output edge is part or all of a PSLG segment with a nonzero\n");
02491 printf(
02492 " boundary marker, then the edge is assigned the same marker.\n");
02493 printf(
02494 " - Otherwise, if the edge lies on a boundary of the triangulation\n");
02495 printf(
02496 " (even the boundary of a hole), then the edge is assigned the marker\n");
02497 printf(" one (1).\n");
02498 printf(" - Otherwise, the edge is assigned the marker zero (0).\n");
02499 printf(
02500 " The boundary marker associated with each vertex in an output .node file\n");
02501 printf(" is chosen as follows:\n");
02502 printf(
02503 " - If a vertex is assigned a nonzero boundary marker in the input file,\n"
02504 );
02505 printf(
02506 " then it is assigned the same marker in the output .node file.\n");
02507 printf(
02508 " - Otherwise, if the vertex lies on a PSLG segment (even if it is an\n");
02509 printf(
02510 " endpoint of the segment) with a nonzero boundary marker, then the\n");
02511 printf(
02512 " vertex is assigned the same marker. If the vertex lies on several\n");
02513 printf(" such segments, one of the markers is chosen arbitrarily.\n");
02514 printf(
02515 " - Otherwise, if the vertex occurs on a boundary of the triangulation,\n");
02516 printf(" then the vertex is assigned the marker one (1).\n");
02517 printf(" - Otherwise, the vertex is assigned the marker zero (0).\n");
02518 printf("\n");
02519 printf(
02520 " If you want Triangle to determine for you which vertices and edges are on\n"
02521 );
02522 printf(
02523 " the boundary, assign them the boundary marker zero (or use no markers at\n"
02524 );
02525 printf(
02526 " all) in your input files. In the output files, all boundary vertices,\n");
02527 printf(" edges, and segments will be assigned the value one.\n\n");
02528 printf("Triangulation Iteration Numbers:\n\n");
02529 printf(
02530 " Because Triangle can read and refine its own triangulations, input\n");
02531 printf(
02532 " and output files have iteration numbers. For instance, Triangle might\n");
02533 printf(
02534 " read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
02535 printf(
02536 " triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
02537 printf(" mesh.4.poly. Files with no iteration number are treated as if\n");
02538 printf(
02539 " their iteration number is zero; hence, Triangle might read the file\n");
02540 printf(
02541 " points.node, triangulate it, and produce the files points.1.node and\n");
02542 printf(" points.1.ele.\n\n");
02543 printf(
02544 " Iteration numbers allow you to create a sequence of successively finer\n");
02545 printf(
02546 " meshes suitable for multigrid methods. They also allow you to produce a\n"
02547 );
02548 printf(
02549 " sequence of meshes using error estimate-driven mesh refinement.\n");
02550 printf("\n");
02551 printf(
02552 " If you're not using refinement or quality meshing, and you don't like\n");
02553 printf(
02554 " iteration numbers, use the -I switch to disable them. This switch also\n");
02555 printf(
02556 " disables output of .node and .poly files to prevent your input files from\n"
02557 );
02558 printf(
02559 " being overwritten. (If the input is a .poly file that contains its own\n");
02560 printf(
02561 " points, a .node file is written. This can be quite convenient for\n");
02562 printf(" computing CDTs or quality meshes.)\n\n");
02563 printf("Examples of How to Use Triangle:\n\n");
02564 printf(
02565 " `triangle dots' reads vertices from dots.node, and writes their Delaunay\n"
02566 );
02567 printf(
02568 " triangulation to dots.1.node and dots.1.ele. (dots.1.node is identical\n");
02569 printf(
02570 " to dots.node.) `triangle -I dots' writes the triangulation to dots.ele\n");
02571 printf(
02572 " instead. (No additional .node file is needed, so none is written.)\n");
02573 printf("\n");
02574 printf(
02575 " `triangle -pe object.1' reads a PSLG from object.1.poly (and possibly\n");
02576 printf(
02577 " object.1.node, if the vertices are omitted from object.1.poly) and writes\n"
02578 );
02579 printf(
02580 " its constrained Delaunay triangulation to object.2.node and object.2.ele.\n"
02581 );
02582 printf(
02583 " The segments are copied to object.2.poly, and all edges are written to\n");
02584 printf(" object.2.edge.\n\n");
02585 printf(
02586 " `triangle -pq31.5a.1 object' reads a PSLG from object.poly (and possibly\n"
02587 );
02588 printf(
02589 " object.node), generates a mesh whose angles are all between 31.5 and 117\n"
02590 );
02591 printf(
02592 " degrees and whose triangles all have areas of 0.1 or less, and writes the\n"
02593 );
02594 printf(
02595 " mesh to object.1.node and object.1.ele. Each segment may be broken up\n");
02596 printf(" into multiple subsegments; these are written to object.1.poly.\n");
02597 printf("\n");
02598 printf(
02599 " Here is a sample file `box.poly' describing a square with a square hole:\n"
02600 );
02601 printf("\n");
02602 printf(
02603 " # A box with eight vertices in 2D, no attributes, one boundary marker.\n"
02604 );
02605 printf(" 8 2 0 1\n");
02606 printf(" # Outer box has these vertices:\n");
02607 printf(" 1 0 0 0\n");
02608 printf(" 2 0 3 0\n");
02609 printf(" 3 3 0 0\n");
02610 printf(" 4 3 3 33 # A special marker for this vertex.\n");
02611 printf(" # Inner square has these vertices:\n");
02612 printf(" 5 1 1 0\n");
02613 printf(" 6 1 2 0\n");
02614 printf(" 7 2 1 0\n");
02615 printf(" 8 2 2 0\n");
02616 printf(" # Five segments with boundary markers.\n");
02617 printf(" 5 1\n");
02618 printf(" 1 1 2 5 # Left side of outer box.\n");
02619 printf(" # Square hole has these segments:\n");
02620 printf(" 2 5 7 0\n");
02621 printf(" 3 7 8 0\n");
02622 printf(" 4 8 6 10\n");
02623 printf(" 5 6 5 0\n");
02624 printf(" # One hole in the middle of the inner square.\n");
02625 printf(" 1\n");
02626 printf(" 1 1.5 1.5\n");
02627 printf("\n");
02628 printf(
02629 " Note that some segments are missing from the outer square, so you must\n");
02630 printf(
02631 " use the `-c' switch. After `triangle -pqc box.poly', here is the output\n"
02632 );
02633 printf(
02634 " file `box.1.node', with twelve vertices. The last four vertices were\n");
02635 printf(
02636 " added to meet the angle constraint. Vertices 1, 2, and 9 have markers\n");
02637 printf(
02638 " from segment 1. Vertices 6 and 8 have markers from segment 4. All the\n");
02639 printf(
02640 " other vertices but 4 have been marked to indicate that they lie on a\n");
02641 printf(" boundary.\n\n");
02642 printf(" 12 2 0 1\n");
02643 printf(" 1 0 0 5\n");
02644 printf(" 2 0 3 5\n");
02645 printf(" 3 3 0 1\n");
02646 printf(" 4 3 3 33\n");
02647 printf(" 5 1 1 1\n");
02648 printf(" 6 1 2 10\n");
02649 printf(" 7 2 1 1\n");
02650 printf(" 8 2 2 10\n");
02651 printf(" 9 0 1.5 5\n");
02652 printf(" 10 1.5 0 1\n");
02653 printf(" 11 3 1.5 1\n");
02654 printf(" 12 1.5 3 1\n");
02655 printf(" # Generated by triangle -pqc box.poly\n");
02656 printf("\n");
02657 printf(" Here is the output file `box.1.ele', with twelve triangles.\n");
02658 printf("\n");
02659 printf(" 12 3 0\n");
02660 printf(" 1 5 6 9\n");
02661 printf(" 2 10 3 7\n");
02662 printf(" 3 6 8 12\n");
02663 printf(" 4 9 1 5\n");
02664 printf(" 5 6 2 9\n");
02665 printf(" 6 7 3 11\n");
02666 printf(" 7 11 4 8\n");
02667 printf(" 8 7 5 10\n");
02668 printf(" 9 12 2 6\n");
02669 printf(" 10 8 7 11\n");
02670 printf(" 11 5 1 10\n");
02671 printf(" 12 8 4 12\n");
02672 printf(" # Generated by triangle -pqc box.poly\n\n");
02673 printf(
02674 " Here is the output file `box.1.poly'. Note that segments have been added\n"
02675 );
02676 printf(
02677 " to represent the convex hull, and some segments have been subdivided by\n");
02678 printf(
02679 " newly added vertices. Note also that <# of vertices> is set to zero to\n");
02680 printf(" indicate that the vertices should be read from the .node file.\n");
02681 printf("\n");
02682 printf(" 0 2 0 1\n");
02683 printf(" 12 1\n");
02684 printf(" 1 1 9 5\n");
02685 printf(" 2 5 7 1\n");
02686 printf(" 3 8 7 1\n");
02687 printf(" 4 6 8 10\n");
02688 printf(" 5 5 6 1\n");
02689 printf(" 6 3 10 1\n");
02690 printf(" 7 4 11 1\n");
02691 printf(" 8 2 12 1\n");
02692 printf(" 9 9 2 5\n");
02693 printf(" 10 10 1 1\n");
02694 printf(" 11 11 3 1\n");
02695 printf(" 12 12 4 1\n");
02696 printf(" 1\n");
02697 printf(" 1 1.5 1.5\n");
02698 printf(" # Generated by triangle -pqc box.poly\n");
02699 printf("\n");
02700 printf("Refinement and Area Constraints:\n");
02701 printf("\n");
02702 printf(
02703 " The -r switch causes a mesh (.node and .ele files) to be read and\n");
02704 printf(
02705 " refined. If the -p switch is also used, a .poly file is read and used to\n"
02706 );
02707 printf(
02708 " specify edges that are constrained and cannot be eliminated (although\n");
02709 printf(
02710 " they can be subdivided into smaller edges) by the refinement process.\n");
02711 printf("\n");
02712 printf(
02713 " When you refine a mesh, you generally want to impose tighter constraints.\n"
02714 );
02715 printf(
02716 " One way to accomplish this is to use -q with a larger angle, or -a\n");
02717 printf(
02718 " followed by a smaller area than you used to generate the mesh you are\n");
02719 printf(
02720 " refining. Another way to do this is to create an .area file, which\n");
02721 printf(
02722 " specifies a maximum area for each triangle, and use the -a switch\n");
02723 printf(
02724 " (without a number following). Each triangle's area constraint is applied\n"
02725 );
02726 printf(
02727 " to that triangle. Area constraints tend to diffuse as the mesh is\n");
02728 printf(
02729 " refined, so if there are large variations in area constraint between\n");
02730 printf(
02731 " adjacent triangles, you may not get the results you want. In that case,\n"
02732 );
02733 printf(
02734 " consider instead using the -u switch and writing a C procedure that\n");
02735 printf(" determines which triangles are too large.\n\n");
02736 printf(
02737 " If you are refining a mesh composed of linear (three-node) elements, the\n"
02738 );
02739 printf(
02740 " output mesh contains all the nodes present in the input mesh, in the same\n"
02741 );
02742 printf(
02743 " order, with new nodes added at the end of the .node file. However, the\n");
02744 printf(
02745 " refinement is not hierarchical: there is no guarantee that each output\n");
02746 printf(
02747 " element is contained in a single input element. Often, an output element\n"
02748 );
02749 printf(
02750 " can overlap two or three input elements, and some input edges are not\n");
02751 printf(
02752 " present in the output mesh. Hence, a sequence of refined meshes forms a\n"
02753 );
02754 printf(
02755 " hierarchy of nodes, but not a hierarchy of elements. If you refine a\n");
02756 printf(
02757 " mesh of higher-order elements, the hierarchical property applies only to\n"
02758 );
02759 printf(
02760 " the nodes at the corners of an element; the midpoint nodes on each edge\n");
02761 printf(" are discarded before the mesh is refined.\n\n");
02762 printf(
02763 " Maximum area constraints in .poly files operate differently from those in\n"
02764 );
02765 printf(
02766 " .area files. A maximum area in a .poly file applies to the whole\n");
02767 printf(
02768 " (segment-bounded) region in which a point falls, whereas a maximum area\n");
02769 printf(
02770 " in an .area file applies to only one triangle. Area constraints in .poly\n"
02771 );
02772 printf(
02773 " files are used only when a mesh is first generated, whereas area\n");
02774 printf(
02775 " constraints in .area files are used only to refine an existing mesh, and\n"
02776 );
02777 printf(
02778 " are typically based on a posteriori error estimates resulting from a\n");
02779 printf(" finite element simulation on that mesh.\n\n");
02780 printf(
02781 " `triangle -rq25 object.1' reads object.1.node and object.1.ele, then\n");
02782 printf(
02783 " refines the triangulation to enforce a 25 degree minimum angle, and then\n"
02784 );
02785 printf(
02786 " writes the refined triangulation to object.2.node and object.2.ele.\n");
02787 printf("\n");
02788 printf(
02789 " `triangle -rpaa6.2 z.3' reads z.3.node, z.3.ele, z.3.poly, and z.3.area.\n"
02790 );
02791 printf(
02792 " After reconstructing the mesh and its subsegments, Triangle refines the\n");
02793 printf(
02794 " mesh so that no triangle has area greater than 6.2, and furthermore the\n");
02795 printf(
02796 " triangles satisfy the maximum area constraints in z.3.area. No angle\n");
02797 printf(
02798 " bound is imposed at all. The output is written to z.4.node, z.4.ele, and\n"
02799 );
02800 printf(" z.4.poly.\n\n");
02801 printf(
02802 " The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
02803 printf(
02804 " x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
02805 printf(" suitable for multigrid.\n\n");
02806 printf("Convex Hulls and Mesh Boundaries:\n\n");
02807 printf(
02808 " If the input is a vertex set (not a PSLG), Triangle produces its convex\n");
02809 printf(
02810 " hull as a by-product in the output .poly file if you use the -c switch.\n");
02811 printf(
02812 " There are faster algorithms for finding a two-dimensional convex hull\n");
02813 printf(" than triangulation, of course, but this one comes for free.\n\n");
02814 printf(
02815 " If the input is an unconstrained mesh (you are using the -r switch but\n");
02816 printf(
02817 " not the -p switch), Triangle produces a list of its boundary edges\n");
02818 printf(
02819 " (including hole boundaries) as a by-product when you use the -c switch.\n");
02820 printf(
02821 " If you also use the -p switch, the output .poly file contains all the\n");
02822 printf(" segments from the input .poly file as well.\n\n");
02823 printf("Voronoi Diagrams:\n\n");
02824 printf(
02825 " The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
02826 printf(
02827 " .v.edge. For example, `triangle -v points' reads points.node, produces\n");
02828 printf(
02829 " its Delaunay triangulation in points.1.node and points.1.ele, and\n");
02830 printf(
02831 " produces its Voronoi diagram in points.1.v.node and points.1.v.edge. The\n"
02832 );
02833 printf(
02834 " .v.node file contains a list of all Voronoi vertices, and the .v.edge\n");
02835 printf(
02836 " file contains a list of all Voronoi edges, some of which may be infinite\n"
02837 );
02838 printf(
02839 " rays. (The choice of filenames makes it easy to run the set of Voronoi\n");
02840 printf(" vertices through Triangle, if so desired.)\n\n");
02841 printf(
02842 " This implementation does not use exact arithmetic to compute the Voronoi\n"
02843 );
02844 printf(
02845 " vertices, and does not check whether neighboring vertices are identical.\n"
02846 );
02847 printf(
02848 " Be forewarned that if the Delaunay triangulation is degenerate or\n");
02849 printf(
02850 " near-degenerate, the Voronoi diagram may have duplicate vertices or\n");
02851 printf(" crossing edges.\n\n");
02852 printf(
02853 " The result is a valid Voronoi diagram only if Triangle's output is a true\n"
02854 );
02855 printf(
02856 " Delaunay triangulation. The Voronoi output is usually meaningless (and\n");
02857 printf(
02858 " may contain crossing edges and other pathology) if the output is a CDT or\n"
02859 );
02860 printf(
02861 " CCDT, or if it has holes or concavities. If the triangulated domain is\n");
02862 printf(
02863 " convex and has no holes, you can use -D switch to force Triangle to\n");
02864 printf(
02865 " construct a conforming Delaunay triangulation instead of a CCDT, so the\n");
02866 printf(" Voronoi diagram will be valid.\n\n");
02867 printf("Mesh Topology:\n\n");
02868 printf(
02869 " You may wish to know which triangles are adjacent to a certain Delaunay\n");
02870 printf(
02871 " edge in an .edge file, which Voronoi cells are adjacent to a certain\n");
02872 printf(
02873 " Voronoi edge in a .v.edge file, or which Voronoi cells are adjacent to\n");
02874 printf(
02875 " each other. All of this information can be found by cross-referencing\n");
02876 printf(
02877 " output files with the recollection that the Delaunay triangulation and\n");
02878 printf(" the Voronoi diagram are planar duals.\n\n");
02879 printf(
02880 " Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
02881 printf(
02882 " the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
02883 printf(
02884 " wise from the Voronoi edge. Triangle j of an .ele file is the dual of\n");
02885 printf(
02886 " vertex j of the corresponding .v.node file. Voronoi cell k is the dual\n");
02887 printf(" of vertex k of the corresponding .node file.\n\n");
02888 printf(
02889 " Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
02890 printf(
02891 " vertices of the corresponding Voronoi edge. If the endpoints of a\n");
02892 printf(
02893 " Voronoi edge are Voronoi vertices 2 and 6 respectively, then triangles 2\n"
02894 );
02895 printf(
02896 " and 6 adjoin the left and right sides of the corresponding Delaunay edge,\n"
02897 );
02898 printf(
02899 " respectively. To find the Voronoi cells adjacent to a Voronoi edge, look\n"
02900 );
02901 printf(
02902 " at the endpoints of the corresponding Delaunay edge. If the endpoints of\n"
02903 );
02904 printf(
02905 " a Delaunay edge are input vertices 7 and 12, then Voronoi cells 7 and 12\n"
02906 );
02907 printf(
02908 " adjoin the right and left sides of the corresponding Voronoi edge,\n");
02909 printf(
02910 " respectively. To find which Voronoi cells are adjacent to each other,\n");
02911 printf(" just read the list of Delaunay edges.\n\n");
02912 printf(
02913 " Triangle does not write a list of the edges adjoining each Voronoi cell,\n"
02914 );
02915 printf(
02916 " but you can reconstructed it straightforwardly. For instance, to find\n");
02917 printf(
02918 " all the edges of Voronoi cell 1, search the output .edge file for every\n");
02919 printf(
02920 " edge that has input vertex 1 as an endpoint. The corresponding dual\n");
02921 printf(
02922 " edges in the output .v.edge file form the boundary of Voronoi cell 1.\n");
02923 printf("\n");
02924 printf(
02925 " For each Voronoi vertex, the .neigh file gives a list of the three\n");
02926 printf(
02927 " Voronoi vertices attached to it. You might find this more convenient\n");
02928 printf(" than the .v.edge file.\n\n");
02929 printf("Quadratic Elements:\n\n");
02930 printf(
02931 " Triangle generates meshes with subparametric quadratic elements if the\n");
02932 printf(
02933 " -o2 switch is specified. Quadratic elements have six nodes per element,\n"
02934 );
02935 printf(
02936 " rather than three. `Subparametric' means that the edges of the triangles\n"
02937 );
02938 printf(
02939 " are always straight, so that subparametric quadratic elements are\n");
02940 printf(
02941 " geometrically identical to linear elements, even though they can be used\n"
02942 );
02943 printf(
02944 " with quadratic interpolating functions. The three extra nodes of an\n");
02945 printf(
02946 " element fall at the midpoints of the three edges, with the fourth, fifth,\n"
02947 );
02948 printf(
02949 " and sixth nodes appearing opposite the first, second, and third corners\n");
02950 printf(" respectively.\n\n");
02951 printf("Domains with Small Angles:\n\n");
02952 printf(
02953 " If two input segments adjoin each other at a small angle, clearly the -q\n"
02954 );
02955 printf(
02956 " switch cannot remove the small angle. Moreover, Triangle may have no\n");
02957 printf(
02958 " choice but to generate additional triangles whose smallest angles are\n");
02959 printf(
02960 " smaller than the specified bound. However, these triangles only appear\n");
02961 printf(
02962 " between input segments separated by small angles. Moreover, if you\n");
02963 printf(
02964 " request a minimum angle of theta degrees, Triangle will generally produce\n"
02965 );
02966 printf(
02967 " no angle larger than 180 - 2 theta, even if it is forced to compromise on\n"
02968 );
02969 printf(" the minimum angle.\n\n");
02970 printf("Statistics:\n\n");
02971 printf(
02972 " After generating a mesh, Triangle prints a count of entities in the\n");
02973 printf(
02974 " output mesh, including the number of vertices, triangles, edges, exterior\n"
02975 );
02976 printf(
02977 " boundary edges (i.e. subsegments on the boundary of the triangulation,\n");
02978 printf(
02979 " including hole boundaries), interior boundary edges (i.e. subsegments of\n"
02980 );
02981 printf(
02982 " input segments not on the boundary), and total subsegments. If you've\n");
02983 printf(
02984 " forgotten the statistics for an existing mesh, run Triangle on that mesh\n"
02985 );
02986 printf(
02987 " with the -rNEP switches to read the mesh and print the statistics without\n"
02988 );
02989 printf(
02990 " writing any files. Use -rpNEP if you've got a .poly file for the mesh.\n");
02991 printf("\n");
02992 printf(
02993 " The -V switch produces extended statistics, including a rough estimate\n");
02994 printf(
02995 " of memory use, the number of calls to geometric predicates, and\n");
02996 printf(
02997 " histograms of the angles and the aspect ratios of the triangles in the\n");
02998 printf(" mesh.\n\n");
02999 printf("Exact Arithmetic:\n\n");
03000 printf(
03001 " Triangle uses adaptive exact arithmetic to perform what computational\n");
03002 printf(
03003 " geometers call the `orientation' and `incircle' tests. If the floating-\n"
03004 );
03005 printf(
03006 " point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
03007 printf(
03008 " most workstations do), and does not use extended precision internal\n");
03009 printf(
03010 " floating-point registers, then your output is guaranteed to be an\n");
03011 printf(
03012 " absolutely true Delaunay or constrained Delaunay triangulation, roundoff\n"
03013 );
03014 printf(
03015 " error notwithstanding. The word `adaptive' implies that these arithmetic\n"
03016 );
03017 printf(
03018 " routines compute the result only to the precision necessary to guarantee\n"
03019 );
03020 printf(
03021 " correctness, so they are usually nearly as fast as their approximate\n");
03022 printf(" counterparts.\n\n");
03023 printf(
03024 " May CPUs, including Intel x86 processors, have extended precision\n");
03025 printf(
03026 " floating-point registers. These must be reconfigured so their precision\n"
03027 );
03028 printf(
03029 " is reduced to memory precision. Triangle does this if it is compiled\n");
03030 printf(" correctly. See the makefile for details.\n\n");
03031 printf(
03032 " The exact tests can be disabled with the -X switch. On most inputs, this\n"
03033 );
03034 printf(
03035 " switch reduces the computation time by about eight percent--it's not\n");
03036 printf(
03037 " worth the risk. There are rare difficult inputs (having many collinear\n");
03038 printf(
03039 " and cocircular vertices), however, for which the difference in speed\n");
03040 printf(
03041 " could be a factor of two. Be forewarned that these are precisely the\n");
03042 printf(
03043 " inputs most likely to cause errors if you use the -X switch. Hence, the\n"
03044 );
03045 printf(" -X switch is not recommended.\n\n");
03046 printf(
03047 " Unfortunately, the exact tests don't solve every numerical problem.\n");
03048 printf(
03049 " Exact arithmetic is not used to compute the positions of new vertices,\n");
03050 printf(
03051 " because the bit complexity of vertex coordinates would grow without\n");
03052 printf(
03053 " bound. Hence, segment intersections aren't computed exactly; in very\n");
03054 printf(
03055 " unusual cases, roundoff error in computing an intersection point might\n");
03056 printf(
03057 " actually lead to an inverted triangle and an invalid triangulation.\n");
03058 printf(
03059 " (This is one reason to specify your own intersection points in your .poly\n"
03060 );
03061 printf(
03062 " files.) Similarly, exact arithmetic is not used to compute the vertices\n"
03063 );
03064 printf(" of the Voronoi diagram.\n\n");
03065 printf(
03066 " Another pair of problems not solved by the exact arithmetic routines is\n");
03067 printf(
03068 " underflow and overflow. If Triangle is compiled for double precision\n");
03069 printf(
03070 " arithmetic, I believe that Triangle's geometric predicates work correctly\n"
03071 );
03072 printf(
03073 " if the exponent of every input coordinate falls in the range [-148, 201].\n"
03074 );
03075 printf(
03076 " Underflow can silently prevent the orientation and incircle tests from\n");
03077 printf(
03078 " being performed exactly, while overflow typically causes a floating\n");
03079 printf(" exception.\n\n");
03080 printf("Calling Triangle from Another Program:\n\n");
03081 printf(" Read the file triangle.h for details.\n\n");
03082 printf("Troubleshooting:\n\n");
03083 printf(" Please read this section before mailing me bugs.\n\n");
03084 printf(" `My output mesh has no triangles!'\n\n");
03085 printf(
03086 " If you're using a PSLG, you've probably failed to specify a proper set\n"
03087 );
03088 printf(
03089 " of bounding segments, or forgotten to use the -c switch. Or you may\n");
03090 printf(
03091 " have placed a hole badly, thereby eating all your triangles. To test\n");
03092 printf(" these possibilities, try again with the -c and -O switches.\n");
03093 printf(
03094 " Alternatively, all your input vertices may be collinear, in which case\n"
03095 );
03096 printf(" you can hardly expect to triangulate them.\n\n");
03097 printf(" `Triangle doesn't terminate, or just crashes.'\n\n");
03098 printf(
03099 " Bad things can happen when triangles get so small that the distance\n");
03100 printf(
03101 " between their vertices isn't much larger than the precision of your\n");
03102 printf(
03103 " machine's arithmetic. If you've compiled Triangle for single-precision\n"
03104 );
03105 printf(
03106 " arithmetic, you might do better by recompiling it for double-precision.\n"
03107 );
03108 printf(
03109 " Then again, you might just have to settle for more lenient constraints\n"
03110 );
03111 printf(
03112 " on the minimum angle and the maximum area than you had planned.\n");
03113 printf("\n");
03114 printf(
03115 " You can minimize precision problems by ensuring that the origin lies\n");
03116 printf(
03117 " inside your vertex set, or even inside the densest part of your\n");
03118 printf(
03119 " mesh. If you're triangulating an object whose x-coordinates all fall\n");
03120 printf(
03121 " between 6247133 and 6247134, you're not leaving much floating-point\n");
03122 printf(" precision for Triangle to work with.\n\n");
03123 printf(
03124 " Precision problems can occur covertly if the input PSLG contains two\n");
03125 printf(
03126 " segments that meet (or intersect) at an extremely small angle, or if\n");
03127 printf(
03128 " such an angle is introduced by the -c switch. If you don't realize\n");
03129 printf(
03130 " that a tiny angle is being formed, you might never discover why\n");
03131 printf(
03132 " Triangle is crashing. To check for this possibility, use the -S switch\n"
03133 );
03134 printf(
03135 " (with an appropriate limit on the number of Steiner points, found by\n");
03136 printf(
03137 " trial-and-error) to stop Triangle early, and view the output .poly file\n"
03138 );
03139 printf(
03140 " with Show Me (described below). Look carefully for regions where dense\n"
03141 );
03142 printf(
03143 " clusters of vertices are forming and for small angles between segments.\n"
03144 );
03145 printf(
03146 " Zoom in closely, as such segments might look like a single segment from\n"
03147 );
03148 printf(" a distance.\n\n");
03149 printf(
03150 " If some of the input values are too large, Triangle may suffer a\n");
03151 printf(
03152 " floating exception due to overflow when attempting to perform an\n");
03153 printf(
03154 " orientation or incircle test. (Read the section on exact arithmetic\n");
03155 printf(
03156 " above.) Again, I recommend compiling Triangle for double (rather\n");
03157 printf(" than single) precision arithmetic.\n\n");
03158 printf(
03159 " Unexpected problems can arise if you use quality meshing (-q, -a, or\n");
03160 printf(
03161 " -u) with an input that is not segment-bounded--that is, if your input\n");
03162 printf(
03163 " is a vertex set, or you're using the -c switch. If the convex hull of\n"
03164 );
03165 printf(
03166 " your input vertices has collinear vertices on its boundary, an input\n");
03167 printf(
03168 " vertex that you think lies on the convex hull might actually lie just\n");
03169 printf(
03170 " inside the convex hull. If so, the vertex and the nearby convex hull\n");
03171 printf(
03172 " edge form an extremely thin triangle. When Triangle tries to refine\n");
03173 printf(
03174 " the mesh to enforce angle and area constraints, Triangle might generate\n"
03175 );
03176 printf(
03177 " extremely tiny triangles, or it might fail because of insufficient\n");
03178 printf(" floating-point precision.\n\n");
03179 printf(
03180 " `The numbering of the output vertices doesn't match the input vertices.'\n"
03181 );
03182 printf("\n");
03183 printf(
03184 " You may have had duplicate input vertices, or you may have eaten some\n");
03185 printf(
03186 " of your input vertices with a hole, or by placing them outside the area\n"
03187 );
03188 printf(
03189 " enclosed by segments. In any case, you can solve the problem by not\n");
03190 printf(" using the -j switch.\n\n");
03191 printf(
03192 " `Triangle executes without incident, but when I look at the resulting\n");
03193 printf(
03194 " mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
03195 printf("\n");
03196 printf(
03197 " If you select the -X switch, Triangle occasionally makes mistakes due\n");
03198 printf(
03199 " to floating-point roundoff error. Although these errors are rare,\n");
03200 printf(
03201 " don't use the -X switch. If you still have problems, please report the\n"
03202 );
03203 printf(" bug.\n\n");
03204 printf(
03205 " `Triangle executes without incident, but when I look at the resulting\n");
03206 printf(" Voronoi diagram, it has overlapping edges or other geometric\n");
03207 printf(" inconsistencies.'\n");
03208 printf("\n");
03209 printf(
03210 " If your input is a PSLG (-p), you can only expect a meaningful Voronoi\n"
03211 );
03212 printf(
03213 " diagram if the domain you are triangulating is convex and free of\n");
03214 printf(
03215 " holes, and you use the -D switch to construct a conforming Delaunay\n");
03216 printf(" triangulation (instead of a CDT or CCDT).\n\n");
03217 printf(
03218 " Strange things can happen if you've taken liberties with your PSLG. Do\n");
03219 printf(
03220 " you have a vertex lying in the middle of a segment? Triangle sometimes\n");
03221 printf(
03222 " copes poorly with that sort of thing. Do you want to lay out a collinear\n"
03223 );
03224 printf(
03225 " row of evenly spaced, segment-connected vertices? Have you simply\n");
03226 printf(
03227 " defined one long segment connecting the leftmost vertex to the rightmost\n"
03228 );
03229 printf(
03230 " vertex, and a bunch of vertices lying along it? This method occasionally\n"
03231 );
03232 printf(
03233 " works, especially with horizontal and vertical lines, but often it\n");
03234 printf(
03235 " doesn't, and you'll have to connect each adjacent pair of vertices with a\n"
03236 );
03237 printf(" separate segment. If you don't like it, tough.\n\n");
03238 printf(
03239 " Furthermore, if you have segments that intersect other than at their\n");
03240 printf(
03241 " endpoints, try not to let the intersections fall extremely close to PSLG\n"
03242 );
03243 printf(" vertices or each other.\n\n");
03244 printf(
03245 " If you have problems refining a triangulation not produced by Triangle:\n");
03246 printf(
03247 " Are you sure the triangulation is geometrically valid? Is it formatted\n");
03248 printf(
03249 " correctly for Triangle? Are the triangles all listed so the first three\n"
03250 );
03251 printf(
03252 " vertices are their corners in counterclockwise order? Are all of the\n");
03253 printf(
03254 " triangles constrained Delaunay? Triangle's Delaunay refinement algorithm\n"
03255 );
03256 printf(" assumes that it starts with a CDT.\n\n");
03257 printf("Show Me:\n\n");
03258 printf(
03259 " Triangle comes with a separate program named `Show Me', whose primary\n");
03260 printf(
03261 " purpose is to draw meshes on your screen or in PostScript. Its secondary\n"
03262 );
03263 printf(
03264 " purpose is to check the validity of your input files, and do so more\n");
03265 printf(
03266 " thoroughly than Triangle does. Unlike Triangle, Show Me requires that\n");
03267 printf(
03268 " you have the X Windows system. Sorry, Microsoft Windows users.\n");
03269 printf("\n");
03270 printf("Triangle on the Web:\n");
03271 printf("\n");
03272 printf(" To see an illustrated version of these instructions, check out\n");
03273 printf("\n");
03274 printf(" http://www.cs.cmu.edu/~quake/triangle.html\n");
03275 printf("\n");
03276 printf("A Brief Plea:\n");
03277 printf("\n");
03278 printf(
03279 " If you use Triangle, and especially if you use it to accomplish real\n");
03280 printf(
03281 " work, I would like very much to hear from you. A short letter or email\n");
03282 printf(
03283 " (to jrs@cs.berkeley.edu) describing how you use Triangle will mean a lot\n"
03284 );
03285 printf(
03286 " to me. The more people I know are using this program, the more easily I\n"
03287 );
03288 printf(
03289 " can justify spending time on improvements, which in turn will benefit\n");
03290 printf(
03291 " you. Also, I can put you on a list to receive email whenever a new\n");
03292 printf(" version of Triangle is available.\n\n");
03293 printf(
03294 " If you use a mesh generated by Triangle in a publication, please include\n"
03295 );
03296 printf(
03297 " an acknowledgment as well. And please spell Triangle with a capital `T'!\n"
03298 );
03299 printf(
03300 " If you want to include a citation, use `Jonathan Richard Shewchuk,\n");
03301 printf(
03302 " ``Triangle: Engineering a 2D Quality Mesh Generator and Delaunay\n");
03303 printf(
03304 " Triangulator,'' in Applied Computational Geometry: Towards Geometric\n");
03305 printf(
03306 " Engineering (Ming C. Lin and Dinesh Manocha, editors), volume 1148 of\n");
03307 printf(
03308 " Lecture Notes in Computer Science, pages 203-222, Springer-Verlag,\n");
03309 printf(
03310 " Berlin, May 1996. (From the First ACM Workshop on Applied Computational\n"
03311 );
03312 printf(" Geometry.)'\n\n");
03313 printf("Research credit:\n\n");
03314 printf(
03315 " Of course, I can take credit for only a fraction of the ideas that made\n");
03316 printf(
03317 " this mesh generator possible. Triangle owes its existence to the efforts\n"
03318 );
03319 printf(
03320 " of many fine computational geometers and other researchers, including\n");
03321 printf(
03322 " Marshall Bern, L. Paul Chew, Kenneth L. Clarkson, Boris Delaunay, Rex A.\n"
03323 );
03324 printf(
03325 " Dwyer, David Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E.\n");
03326 printf(
03327 " Knuth, Charles L. Lawson, Der-Tsai Lee, Gary L. Miller, Ernst P. Mucke,\n");
03328 printf(
03329 " Steven E. Pav, Douglas M. Priest, Jim Ruppert, Isaac Saias, Bruce J.\n");
03330 printf(
03331 " Schachter, Micha Sharir, Peter W. Shor, Daniel D. Sleator, Jorge Stolfi,\n"
03332 );
03333 printf(" Robert E. Tarjan, Alper Ungor, Christopher J. Van Wyk, Noel J.\n");
03334 printf(
03335 " Walkington, and Binhai Zhu. See the comments at the beginning of the\n");
03336 printf(" source code for references.\n\n");
03337 triexit(0);
03338 }
03339
03340 #endif
03341
03342
03343
03344
03345
03346
03347
03348 void internalerror()
03349 {
03350 printf(" Please report this bug to jrs@cs.berkeley.edu\n");
03351 printf(" Include the message above, your input data set, and the exact\n");
03352 printf(" command line you used to run Triangle.\n");
03353 triexit(1);
03354 }
03355
03356
03357
03358
03359
03360
03361
03362
03363 #ifdef ANSI_DECLARATORS
03364 void parsecommandline(int argc, char **argv, struct behavior *b)
03365 #else
03366 void parsecommandline(argc, argv, b)
03367 int argc;
03368 char **argv;
03369 struct behavior *b;
03370 #endif
03371
03372 {
03373 #ifdef TRILIBRARY
03374 #define STARTINDEX 0
03375 #else
03376 #define STARTINDEX 1
03377 int increment;
03378 int meshnumber;
03379 #endif
03380 int i, j, k;
03381 char workstring[FILENAMESIZE];
03382
03383 b->poly = b->refine = b->quality = 0;
03384 b->vararea = b->fixedarea = b->usertest = 0;
03385 b->regionattrib = b->convex = b->weighted = b->jettison = 0;
03386 b->firstnumber = 1;
03387 b->edgesout = b->voronoi = b->neighbors = b->geomview = 0;
03388 b->nobound = b->nopolywritten = b->nonodewritten = b->noelewritten = 0;
03389 b->noiterationnum = 0;
03390 b->noholes = b->noexact = 0;
03391 b->incremental = b->sweepline = 0;
03392 b->dwyer = 1;
03393 b->splitseg = 0;
03394 b->docheck = 0;
03395 b->nobisect = 0;
03396 b->conformdel = 0;
03397 b->steiner = -1;
03398 b->order = 1;
03399 b->minangle = 0.0;
03400 b->maxarea = -1.0;
03401 b->quiet = b->verbose = 0;
03402 #ifndef TRILIBRARY
03403 b->innodefilename[0] = '\0';
03404 #endif
03405
03406 for (i = STARTINDEX; i < argc; i++) {
03407 #ifndef TRILIBRARY
03408 if (argv[i][0] == '-') {
03409 #endif
03410 for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
03411 if (argv[i][j] == 'p') {
03412 b->poly = 1;
03413 }
03414 #ifndef CDT_ONLY
03415 if (argv[i][j] == 'r') {
03416 b->refine = 1;
03417 }
03418 if (argv[i][j] == 'q') {
03419 b->quality = 1;
03420 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03421 (argv[i][j + 1] == '.')) {
03422 k = 0;
03423 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03424 (argv[i][j + 1] == '.')) {
03425 j++;
03426 workstring[k] = argv[i][j];
03427 k++;
03428 }
03429 workstring[k] = '\0';
03430 b->minangle = (REAL) strtod(workstring, (char **) NULL);
03431 } else {
03432 b->minangle = 20.0;
03433 }
03434 }
03435 if (argv[i][j] == 'a') {
03436 b->quality = 1;
03437 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03438 (argv[i][j + 1] == '.')) {
03439 b->fixedarea = 1;
03440 k = 0;
03441 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03442 (argv[i][j + 1] == '.')) {
03443 j++;
03444 workstring[k] = argv[i][j];
03445 k++;
03446 }
03447 workstring[k] = '\0';
03448 b->maxarea = (REAL) strtod(workstring, (char **) NULL);
03449 if (b->maxarea <= 0.0) {
03450 printf("Error: Maximum area must be greater than zero.\n");
03451 triexit(1);
03452 }
03453 } else {
03454 b->vararea = 1;
03455 }
03456 }
03457 if (argv[i][j] == 'u') {
03458 b->quality = 1;
03459 b->usertest = 1;
03460 }
03461 #endif
03462 if (argv[i][j] == 'A') {
03463 b->regionattrib = 1;
03464 }
03465 if (argv[i][j] == 'c') {
03466 b->convex = 1;
03467 }
03468 if (argv[i][j] == 'w') {
03469 b->weighted = 1;
03470 }
03471 if (argv[i][j] == 'W') {
03472 b->weighted = 2;
03473 }
03474 if (argv[i][j] == 'j') {
03475 b->jettison = 1;
03476 }
03477 if (argv[i][j] == 'z') {
03478 b->firstnumber = 0;
03479 }
03480 if (argv[i][j] == 'e') {
03481 b->edgesout = 1;
03482 }
03483 if (argv[i][j] == 'v') {
03484 b->voronoi = 1;
03485 }
03486 if (argv[i][j] == 'n') {
03487 b->neighbors = 1;
03488 }
03489 if (argv[i][j] == 'g') {
03490 b->geomview = 1;
03491 }
03492 if (argv[i][j] == 'B') {
03493 b->nobound = 1;
03494 }
03495 if (argv[i][j] == 'P') {
03496 b->nopolywritten = 1;
03497 }
03498 if (argv[i][j] == 'N') {
03499 b->nonodewritten = 1;
03500 }
03501 if (argv[i][j] == 'E') {
03502 b->noelewritten = 1;
03503 }
03504 #ifndef TRILIBRARY
03505 if (argv[i][j] == 'I') {
03506 b->noiterationnum = 1;
03507 }
03508 #endif
03509 if (argv[i][j] == 'O') {
03510 b->noholes = 1;
03511 }
03512 if (argv[i][j] == 'X') {
03513 b->noexact = 1;
03514 }
03515 if (argv[i][j] == 'o') {
03516 if (argv[i][j + 1] == '2') {
03517 j++;
03518 b->order = 2;
03519 }
03520 }
03521 #ifndef CDT_ONLY
03522 if (argv[i][j] == 'Y') {
03523 b->nobisect++;
03524 }
03525 if (argv[i][j] == 'S') {
03526 b->steiner = 0;
03527 while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
03528 j++;
03529 b->steiner = b->steiner * 10 + (int) (argv[i][j] - '0');
03530 }
03531 }
03532 #endif
03533 #ifndef REDUCED
03534 if (argv[i][j] == 'i') {
03535 b->incremental = 1;
03536 }
03537 if (argv[i][j] == 'F') {
03538 b->sweepline = 1;
03539 }
03540 #endif
03541 if (argv[i][j] == 'l') {
03542 b->dwyer = 0;
03543 }
03544 #ifndef REDUCED
03545 #ifndef CDT_ONLY
03546 if (argv[i][j] == 's') {
03547 b->splitseg = 1;
03548 }
03549 if ((argv[i][j] == 'D') || (argv[i][j] == 'L')) {
03550 b->quality = 1;
03551 b->conformdel = 1;
03552 }
03553 #endif
03554 if (argv[i][j] == 'C') {
03555 b->docheck = 1;
03556 }
03557 #endif
03558 if (argv[i][j] == 'Q') {
03559 b->quiet = 1;
03560 }
03561 if (argv[i][j] == 'V') {
03562 b->verbose++;
03563 }
03564 #ifndef TRILIBRARY
03565 if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03566 (argv[i][j] == '?')) {
03567 info();
03568 }
03569 #endif
03570 }
03571 #ifndef TRILIBRARY
03572 } else {
03573 strncpy(b->innodefilename, argv[i], FILENAMESIZE - 1);
03574 b->innodefilename[FILENAMESIZE - 1] = '\0';
03575 }
03576 #endif
03577 }
03578 #ifndef TRILIBRARY
03579 if (b->innodefilename[0] == '\0') {
03580 syntax();
03581 }
03582 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".node")) {
03583 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03584 }
03585 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".poly")) {
03586 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03587 b->poly = 1;
03588 }
03589 #ifndef CDT_ONLY
03590 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 4], ".ele")) {
03591 b->innodefilename[strlen(b->innodefilename) - 4] = '\0';
03592 b->refine = 1;
03593 }
03594 if (!strcmp(&b->innodefilename[strlen(b->innodefilename) - 5], ".area")) {
03595 b->innodefilename[strlen(b->innodefilename) - 5] = '\0';
03596 b->refine = 1;
03597 b->quality = 1;
03598 b->vararea = 1;
03599 }
03600 #endif
03601 #endif
03602 b->usesegments = b->poly || b->refine || b->quality || b->convex;
03603 b->goodangle = cos(b->minangle * PI / 180.0);
03604 if (b->goodangle == 1.0) {
03605 b->offconstant = 0.0;
03606 } else {
03607 b->offconstant = 0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
03608 }
03609 b->goodangle *= b->goodangle;
03610 if (b->refine && b->noiterationnum) {
03611 printf(
03612 "Error: You cannot use the -I switch when refining a triangulation.\n");
03613 triexit(1);
03614 }
03615
03616
03617 if (!b->refine && !b->poly) {
03618 b->vararea = 0;
03619 }
03620
03621
03622 if (b->refine || !b->poly) {
03623 b->regionattrib = 0;
03624 }
03625
03626
03627 if (b->weighted && (b->poly || b->quality)) {
03628 b->weighted = 0;
03629 if (!b->quiet) {
03630 printf("Warning: weighted triangulations (-w, -W) are incompatible\n");
03631 printf(" with PSLGs (-p) and meshing (-q, -a, -u). Weights ignored.\n"
03632 );
03633 }
03634 }
03635 if (b->jettison && b->nonodewritten && !b->quiet) {
03636 printf("Warning: -j and -N switches are somewhat incompatible.\n");
03637 printf(" If any vertices are jettisoned, you will need the output\n");
03638 printf(" .node file to reconstruct the new node indices.");
03639 }
03640
03641 #ifndef TRILIBRARY
03642 strcpy(b->inpolyfilename, b->innodefilename);
03643 strcpy(b->inelefilename, b->innodefilename);
03644 strcpy(b->areafilename, b->innodefilename);
03645 increment = 0;
03646 strcpy(workstring, b->innodefilename);
03647 j = 1;
03648 while (workstring[j] != '\0') {
03649 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03650 increment = j + 1;
03651 }
03652 j++;
03653 }
03654 meshnumber = 0;
03655 if (increment > 0) {
03656 j = increment;
03657 do {
03658 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03659 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03660 } else {
03661 increment = 0;
03662 }
03663 j++;
03664 } while (workstring[j] != '\0');
03665 }
03666 if (b->noiterationnum) {
03667 strcpy(b->outnodefilename, b->innodefilename);
03668 strcpy(b->outelefilename, b->innodefilename);
03669 strcpy(b->edgefilename, b->innodefilename);
03670 strcpy(b->vnodefilename, b->innodefilename);
03671 strcpy(b->vedgefilename, b->innodefilename);
03672 strcpy(b->neighborfilename, b->innodefilename);
03673 strcpy(b->offfilename, b->innodefilename);
03674 strcat(b->outnodefilename, ".node");
03675 strcat(b->outelefilename, ".ele");
03676 strcat(b->edgefilename, ".edge");
03677 strcat(b->vnodefilename, ".v.node");
03678 strcat(b->vedgefilename, ".v.edge");
03679 strcat(b->neighborfilename, ".neigh");
03680 strcat(b->offfilename, ".off");
03681 } else if (increment == 0) {
03682 strcpy(b->outnodefilename, b->innodefilename);
03683 strcpy(b->outpolyfilename, b->innodefilename);
03684 strcpy(b->outelefilename, b->innodefilename);
03685 strcpy(b->edgefilename, b->innodefilename);
03686 strcpy(b->vnodefilename, b->innodefilename);
03687 strcpy(b->vedgefilename, b->innodefilename);
03688 strcpy(b->neighborfilename, b->innodefilename);
03689 strcpy(b->offfilename, b->innodefilename);
03690 strcat(b->outnodefilename, ".1.node");
03691 strcat(b->outpolyfilename, ".1.poly");
03692 strcat(b->outelefilename, ".1.ele");
03693 strcat(b->edgefilename, ".1.edge");
03694 strcat(b->vnodefilename, ".1.v.node");
03695 strcat(b->vedgefilename, ".1.v.edge");
03696 strcat(b->neighborfilename, ".1.neigh");
03697 strcat(b->offfilename, ".1.off");
03698 } else {
03699 workstring[increment] = '%';
03700 workstring[increment + 1] = 'd';
03701 workstring[increment + 2] = '\0';
03702 sprintf(b->outnodefilename, workstring, meshnumber + 1);
03703 strcpy(b->outpolyfilename, b->outnodefilename);
03704 strcpy(b->outelefilename, b->outnodefilename);
03705 strcpy(b->edgefilename, b->outnodefilename);
03706 strcpy(b->vnodefilename, b->outnodefilename);
03707 strcpy(b->vedgefilename, b->outnodefilename);
03708 strcpy(b->neighborfilename, b->outnodefilename);
03709 strcpy(b->offfilename, b->outnodefilename);
03710 strcat(b->outnodefilename, ".node");
03711 strcat(b->outpolyfilename, ".poly");
03712 strcat(b->outelefilename, ".ele");
03713 strcat(b->edgefilename, ".edge");
03714 strcat(b->vnodefilename, ".v.node");
03715 strcat(b->vedgefilename, ".v.edge");
03716 strcat(b->neighborfilename, ".neigh");
03717 strcat(b->offfilename, ".off");
03718 }
03719 strcat(b->innodefilename, ".node");
03720 strcat(b->inpolyfilename, ".poly");
03721 strcat(b->inelefilename, ".ele");
03722 strcat(b->areafilename, ".area");
03723 #endif
03724 }
03725
03728
03729
03730
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745 #ifdef ANSI_DECLARATORS
03746 void printtriangle(struct mesh *m, struct behavior *b, struct otri *t)
03747 #else
03748 void printtriangle(m, b, t)
03749 struct mesh *m;
03750 struct behavior *b;
03751 struct otri *t;
03752 #endif
03753
03754 {
03755 struct otri printtri;
03756 struct osub printsh;
03757 vertex printvertex;
03758
03759 printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
03760 t->orient);
03761 decode(t->tri[0], printtri);
03762 if (printtri.tri == m->dummytri) {
03763 printf(" [0] = Outer space\n");
03764 } else {
03765 printf(" [0] = x%lx %d\n", (unsigned long) printtri.tri,
03766 printtri.orient);
03767 }
03768 decode(t->tri[1], printtri);
03769 if (printtri.tri == m->dummytri) {
03770 printf(" [1] = Outer space\n");
03771 } else {
03772 printf(" [1] = x%lx %d\n", (unsigned long) printtri.tri,
03773 printtri.orient);
03774 }
03775 decode(t->tri[2], printtri);
03776 if (printtri.tri == m->dummytri) {
03777 printf(" [2] = Outer space\n");
03778 } else {
03779 printf(" [2] = x%lx %d\n", (unsigned long) printtri.tri,
03780 printtri.orient);
03781 }
03782
03783 org(*t, printvertex);
03784 if (printvertex == (vertex) NULL)
03785 printf(" Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
03786 else
03787 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03788 (t->orient + 1) % 3 + 3, (unsigned long) printvertex,
03789 printvertex[0], printvertex[1]);
03790 dest(*t, printvertex);
03791 if (printvertex == (vertex) NULL)
03792 printf(" Dest [%d] = NULL\n", (t->orient + 2) % 3 + 3);
03793 else
03794 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03795 (t->orient + 2) % 3 + 3, (unsigned long) printvertex,
03796 printvertex[0], printvertex[1]);
03797 apex(*t, printvertex);
03798 if (printvertex == (vertex) NULL)
03799 printf(" Apex [%d] = NULL\n", t->orient + 3);
03800 else
03801 printf(" Apex [%d] = x%lx (%.12g, %.12g)\n",
03802 t->orient + 3, (unsigned long) printvertex,
03803 printvertex[0], printvertex[1]);
03804
03805 if (b->usesegments) {
03806 sdecode(t->tri[6], printsh);
03807 if (printsh.ss != m->dummysub) {
03808 printf(" [6] = x%lx %d\n", (unsigned long) printsh.ss,
03809 printsh.ssorient);
03810 }
03811 sdecode(t->tri[7], printsh);
03812 if (printsh.ss != m->dummysub) {
03813 printf(" [7] = x%lx %d\n", (unsigned long) printsh.ss,
03814 printsh.ssorient);
03815 }
03816 sdecode(t->tri[8], printsh);
03817 if (printsh.ss != m->dummysub) {
03818 printf(" [8] = x%lx %d\n", (unsigned long) printsh.ss,
03819 printsh.ssorient);
03820 }
03821 }
03822
03823 if (b->vararea) {
03824 printf(" Area constraint: %.4g\n", areabound(*t));
03825 }
03826 }
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839 #ifdef ANSI_DECLARATORS
03840 void printsubseg(struct mesh *m, struct behavior *b, struct osub *s)
03841 #else
03842 void printsubseg(m, b, s)
03843 struct mesh *m;
03844 struct behavior *b;
03845 struct osub *s;
03846 #endif
03847
03848 {
03849 struct osub printsh;
03850 struct otri printtri;
03851 vertex printvertex;
03852
03853 printf("subsegment x%lx with orientation %d and mark %d:\n",
03854 (unsigned long) s->ss, s->ssorient, mark(*s));
03855 sdecode(s->ss[0], printsh);
03856 if (printsh.ss == m->dummysub) {
03857 printf(" [0] = No subsegment\n");
03858 } else {
03859 printf(" [0] = x%lx %d\n", (unsigned long) printsh.ss,
03860 printsh.ssorient);
03861 }
03862 sdecode(s->ss[1], printsh);
03863 if (printsh.ss == m->dummysub) {
03864 printf(" [1] = No subsegment\n");
03865 } else {
03866 printf(" [1] = x%lx %d\n", (unsigned long) printsh.ss,
03867 printsh.ssorient);
03868 }
03869
03870 sorg(*s, printvertex);
03871 if (printvertex == (vertex) NULL)
03872 printf(" Origin[%d] = NULL\n", 2 + s->ssorient);
03873 else
03874 printf(" Origin[%d] = x%lx (%.12g, %.12g)\n",
03875 2 + s->ssorient, (unsigned long) printvertex,
03876 printvertex[0], printvertex[1]);
03877 sdest(*s, printvertex);
03878 if (printvertex == (vertex) NULL)
03879 printf(" Dest [%d] = NULL\n", 3 - s->ssorient);
03880 else
03881 printf(" Dest [%d] = x%lx (%.12g, %.12g)\n",
03882 3 - s->ssorient, (unsigned long) printvertex,
03883 printvertex[0], printvertex[1]);
03884
03885 decode(s->ss[6], printtri);
03886 if (printtri.tri == m->dummytri) {
03887 printf(" [6] = Outer space\n");
03888 } else {
03889 printf(" [6] = x%lx %d\n", (unsigned long) printtri.tri,
03890 printtri.orient);
03891 }
03892 decode(s->ss[7], printtri);
03893 if (printtri.tri == m->dummytri) {
03894 printf(" [7] = Outer space\n");
03895 } else {
03896 printf(" [7] = x%lx %d\n", (unsigned long) printtri.tri,
03897 printtri.orient);
03898 }
03899
03900 segorg(*s, printvertex);
03901 if (printvertex == (vertex) NULL)
03902 printf(" Segment origin[%d] = NULL\n", 4 + s->ssorient);
03903 else
03904 printf(" Segment origin[%d] = x%lx (%.12g, %.12g)\n",
03905 4 + s->ssorient, (unsigned long) printvertex,
03906 printvertex[0], printvertex[1]);
03907 segdest(*s, printvertex);
03908 if (printvertex == (vertex) NULL)
03909 printf(" Segment dest [%d] = NULL\n", 5 - s->ssorient);
03910 else
03911 printf(" Segment dest [%d] = x%lx (%.12g, %.12g)\n",
03912 5 - s->ssorient, (unsigned long) printvertex,
03913 printvertex[0], printvertex[1]);
03914 }
03915
03918
03919
03920
03924
03925
03926
03927
03928
03929
03930
03931
03932
03933 #ifdef ANSI_DECLARATORS
03934 void poolzero(struct memorypool* pool)
03935 #else
03936 void poolzero(pool)
03937 struct memorypool* pool;
03938 #endif
03939
03940 {
03941 pool->firstblock = (VOID **) NULL;
03942 pool->nowblock = (VOID **) NULL;
03943 pool->nextitem = (VOID *) NULL;
03944 pool->deaditemstack = (VOID *) NULL;
03945 pool->pathblock = (VOID **) NULL;
03946 pool->pathitem = (VOID *) NULL;
03947 pool->alignbytes = 0;
03948 pool->itembytes = 0;
03949 pool->itemsperblock = 0;
03950 pool->itemsfirstblock = 0;
03951 pool->items = 0;
03952 pool->maxitems = 0;
03953 pool->unallocateditems = 0;
03954 pool->pathitemsleft = 0;
03955 }
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967 #ifdef ANSI_DECLARATORS
03968 void poolrestart(struct memorypool* pool)
03969 #else
03970 void poolrestart(pool)
03971 struct memorypool* pool;
03972 #endif
03973
03974 {
03975 unsigned long alignptr;
03976
03977 pool->items = 0;
03978 pool->maxitems = 0;
03979
03980
03981 pool->nowblock = pool->firstblock;
03982
03983 alignptr = (unsigned long) (pool->nowblock + 1);
03984
03985 pool->nextitem = (VOID *)
03986 (alignptr + (unsigned long) pool->alignbytes -
03987 (alignptr % (unsigned long) pool->alignbytes));
03988
03989 pool->unallocateditems = pool->itemsfirstblock;
03990
03991 pool->deaditemstack = (VOID *) NULL;
03992 }
03993
03994
03995
03996
03997
03998
03999
04000
04001
04002
04003
04004
04005
04006
04007
04008
04009
04010
04011
04012
04013 #ifdef ANSI_DECLARATORS
04014 void poolinit(struct memorypool* pool, int bytecount, int itemcount,
04015 int firstitemcount, unsigned alignment)
04016 #else
04017 void poolinit(pool, bytecount, itemcount, firstitemcount, alignment)
04018 struct memorypool* pool;
04019 int bytecount;
04020 int itemcount;
04021 int firstitemcount;
04022 unsigned alignment;
04023 #endif
04024
04025 {
04026
04027
04028
04029
04030 if (alignment > sizeof(VOID *)) {
04031 pool->alignbytes = alignment;
04032 } else {
04033 pool->alignbytes = sizeof(VOID *);
04034 }
04035 pool->itembytes = ((bytecount - 1) / pool->alignbytes + 1) *
04036 pool->alignbytes;
04037 pool->itemsperblock = itemcount;
04038 if (firstitemcount == 0) {
04039 pool->itemsfirstblock = itemcount;
04040 } else {
04041 pool->itemsfirstblock = firstitemcount;
04042 }
04043
04044
04045
04046
04047 pool->firstblock = (VOID **)
04048 trimalloc(pool->itemsfirstblock * pool->itembytes + (int) sizeof(VOID *) +
04049 pool->alignbytes);
04050
04051 *(pool->firstblock) = (VOID *) NULL;
04052 poolrestart(pool);
04053 }
04054
04055
04056
04057
04058
04059
04060
04061 #ifdef ANSI_DECLARATORS
04062 void pooldeinit(struct memorypool* pool)
04063 #else
04064 void pooldeinit(pool)
04065 struct memorypool* pool;
04066 #endif
04067
04068 {
04069 while (pool->firstblock != (VOID **) NULL) {
04070 pool->nowblock = (VOID **) *(pool->firstblock);
04071 trifree((VOID *) pool->firstblock);
04072 pool->firstblock = pool->nowblock;
04073 }
04074 }
04075
04076
04077
04078
04079
04080
04081
04082 #ifdef ANSI_DECLARATORS
04083 VOID* poolalloc(struct memorypool* pool)
04084 #else
04085 VOID* poolalloc(pool)
04086 struct memorypool* pool;
04087 #endif
04088
04089 {
04090 VOID *newitem;
04091 VOID **newblock;
04092 unsigned long alignptr;
04093
04094
04095
04096 if (pool->deaditemstack != (VOID *) NULL) {
04097 newitem = pool->deaditemstack;
04098 pool->deaditemstack = * (VOID **) pool->deaditemstack;
04099 } else {
04100
04101 if (pool->unallocateditems == 0) {
04102
04103 if (*(pool->nowblock) == (VOID *) NULL) {
04104
04105 newblock = (VOID **) trimalloc(pool->itemsperblock * pool->itembytes +
04106 (int) sizeof(VOID *) +
04107 pool->alignbytes);
04108 *(pool->nowblock) = (VOID *) newblock;
04109
04110 *newblock = (VOID *) NULL;
04111 }
04112
04113
04114 pool->nowblock = (VOID **) *(pool->nowblock);
04115
04116
04117 alignptr = (unsigned long) (pool->nowblock + 1);
04118
04119 pool->nextitem = (VOID *)
04120 (alignptr + (unsigned long) pool->alignbytes -
04121 (alignptr % (unsigned long) pool->alignbytes));
04122
04123 pool->unallocateditems = pool->itemsperblock;
04124 }
04125
04126
04127 newitem = pool->nextitem;
04128
04129 pool->nextitem = (VOID *) ((char *) pool->nextitem + pool->itembytes);
04130 pool->unallocateditems--;
04131 pool->maxitems++;
04132 }
04133 pool->items++;
04134 return newitem;
04135 }
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145 #ifdef ANSI_DECLARATORS
04146 void pooldealloc(struct memorypool* pool, VOID *dyingitem)
04147 #else
04148 void pooldealloc(pool, dyingitem)
04149 struct memorypool* pool;
04150 VOID *dyingitem;
04151 #endif
04152
04153 {
04154
04155 *((VOID **) dyingitem) = pool->deaditemstack;
04156 pool->deaditemstack = dyingitem;
04157 pool->items--;
04158 }
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168 #ifdef ANSI_DECLARATORS
04169 void traversalinit(struct memorypool* pool)
04170 #else
04171 void traversalinit(pool)
04172 struct memorypool* pool;
04173 #endif
04174
04175 {
04176 unsigned long alignptr;
04177
04178
04179 pool->pathblock = pool->firstblock;
04180
04181 alignptr = (unsigned long) (pool->pathblock + 1);
04182
04183 pool->pathitem = (VOID *)
04184 (alignptr + (unsigned long) pool->alignbytes -
04185 (alignptr % (unsigned long) pool->alignbytes));
04186
04187 pool->pathitemsleft = pool->itemsfirstblock;
04188 }
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204 #ifdef ANSI_DECLARATORS
04205 VOID *traverse(struct memorypool* pool)
04206 #else
04207 VOID *traverse(pool)
04208 struct memorypool* pool;
04209 #endif
04210
04211 {
04212 VOID *newitem;
04213 unsigned long alignptr;
04214
04215
04216 if (pool->pathitem == pool->nextitem) {
04217 return (VOID *) NULL;
04218 }
04219
04220
04221 if (pool->pathitemsleft == 0) {
04222
04223 pool->pathblock = (VOID **) *(pool->pathblock);
04224
04225 alignptr = (unsigned long) (pool->pathblock + 1);
04226
04227 pool->pathitem = (VOID *)
04228 (alignptr + (unsigned long) pool->alignbytes -
04229 (alignptr % (unsigned long) pool->alignbytes));
04230
04231 pool->pathitemsleft = pool->itemsperblock;
04232 }
04233
04234 newitem = pool->pathitem;
04235
04236 pool->pathitem = (VOID *) ((char *) pool->pathitem + pool->itembytes);
04237 pool->pathitemsleft--;
04238 return newitem;
04239 }
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269 #ifdef ANSI_DECLARATORS
04270 void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes,
04271 int subsegbytes)
04272 #else
04273 void dummyinit(m, b, trianglebytes, subsegbytes)
04274 struct mesh *m;
04275 struct behavior *b;
04276 int trianglebytes;
04277 int subsegbytes;
04278 #endif
04279
04280 {
04281 unsigned long alignptr;
04282
04283
04284 m->dummytribase = (triangle *) trimalloc(trianglebytes +
04285 m->triangles.alignbytes);
04286
04287 alignptr = (unsigned long) m->dummytribase;
04288 m->dummytri = (triangle *)
04289 (alignptr + (unsigned long) m->triangles.alignbytes -
04290 (alignptr % (unsigned long) m->triangles.alignbytes));
04291
04292
04293
04294
04295 m->dummytri[0] = (triangle) m->dummytri;
04296 m->dummytri[1] = (triangle) m->dummytri;
04297 m->dummytri[2] = (triangle) m->dummytri;
04298
04299 m->dummytri[3] = (triangle) NULL;
04300 m->dummytri[4] = (triangle) NULL;
04301 m->dummytri[5] = (triangle) NULL;
04302
04303 if (b->usesegments) {
04304
04305
04306
04307 m->dummysubbase = (subseg *) trimalloc(subsegbytes +
04308 m->subsegs.alignbytes);
04309
04310 alignptr = (unsigned long) m->dummysubbase;
04311 m->dummysub = (subseg *)
04312 (alignptr + (unsigned long) m->subsegs.alignbytes -
04313 (alignptr % (unsigned long) m->subsegs.alignbytes));
04314
04315
04316
04317
04318 m->dummysub[0] = (subseg) m->dummysub;
04319 m->dummysub[1] = (subseg) m->dummysub;
04320
04321 m->dummysub[2] = (subseg) NULL;
04322 m->dummysub[3] = (subseg) NULL;
04323 m->dummysub[4] = (subseg) NULL;
04324 m->dummysub[5] = (subseg) NULL;
04325
04326 m->dummysub[6] = (subseg) m->dummytri;
04327 m->dummysub[7] = (subseg) m->dummytri;
04328
04329 * (int *) (m->dummysub + 8) = 0;
04330
04331
04332
04333 m->dummytri[6] = (triangle) m->dummysub;
04334 m->dummytri[7] = (triangle) m->dummysub;
04335 m->dummytri[8] = (triangle) m->dummysub;
04336 }
04337 }
04338
04339
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349 #ifdef ANSI_DECLARATORS
04350 void initializevertexpool(struct mesh *m, struct behavior *b)
04351 #else
04352 void initializevertexpool(m, b)
04353 struct mesh *m;
04354 struct behavior *b;
04355 #endif
04356
04357 {
04358 int vertexsize;
04359
04360
04361
04362
04363 m->vertexmarkindex = ((m->mesh_dim + m->nextras) * sizeof(REAL) +
04364 sizeof(int) - 1) /
04365 sizeof(int);
04366 vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
04367 if (b->poly) {
04368
04369
04370 m->vertex2triindex = (vertexsize + sizeof(triangle) - 1) /
04371 sizeof(triangle);
04372 vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
04373 }
04374
04375
04376 poolinit(&m->vertices, vertexsize, VERTEXPERBLOCK,
04377 m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
04378 sizeof(REAL));
04379 }
04380
04381
04382
04383
04384
04385
04386
04387
04388
04389
04390
04391
04392 #ifdef ANSI_DECLARATORS
04393 void initializetrisubpools(struct mesh *m, struct behavior *b)
04394 #else
04395 void initializetrisubpools(m, b)
04396 struct mesh *m;
04397 struct behavior *b;
04398 #endif
04399
04400 {
04401 unsigned trisize;
04402
04403
04404
04405
04406
04407 m->highorderindex = 6 + (b->usesegments * 3);
04408
04409 trisize = ((b->order + 1) * (b->order + 2) / 2 + (m->highorderindex - 3)) *
04410 sizeof(triangle);
04411
04412
04413 m->elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
04414
04415
04416
04417 m->areaboundindex = m->elemattribindex + m->eextras + b->regionattrib;
04418
04419
04420 if (b->vararea) {
04421 trisize = (m->areaboundindex + 1) * sizeof(REAL);
04422 } else if (m->eextras + b->regionattrib > 0) {
04423 trisize = m->areaboundindex * sizeof(REAL);
04424 }
04425
04426
04427
04428
04429 if ((b->voronoi || b->neighbors) &&
04430 (trisize < 6 * sizeof(triangle) + sizeof(int))) {
04431 trisize = 6 * sizeof(triangle) + sizeof(int);
04432 }
04433
04434
04435 poolinit(&m->triangles, trisize, TRIPERBLOCK,
04436 (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2) :
04437 TRIPERBLOCK, 4);
04438
04439 if (b->usesegments) {
04440
04441
04442 poolinit(&m->subsegs, 8 * sizeof(triangle) + sizeof(int),
04443 SUBSEGPERBLOCK, SUBSEGPERBLOCK, 4);
04444
04445
04446 dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
04447 } else {
04448
04449 dummyinit(m, b, m->triangles.itembytes, 0);
04450 }
04451 }
04452
04453
04454
04455
04456
04457
04458
04459 #ifdef ANSI_DECLARATORS
04460 void triangledealloc(struct mesh *m, triangle *dyingtriangle)
04461 #else
04462 void triangledealloc(m, dyingtriangle)
04463 struct mesh *m;
04464 triangle *dyingtriangle;
04465 #endif
04466
04467 {
04468
04469
04470 killtri(dyingtriangle);
04471 pooldealloc(&m->triangles, (VOID *) dyingtriangle);
04472 }
04473
04474
04475
04476
04477
04478
04479
04480 #ifdef ANSI_DECLARATORS
04481 triangle *triangletraverse(struct mesh *m)
04482 #else
04483 triangle *triangletraverse(m)
04484 struct mesh *m;
04485 #endif
04486
04487 {
04488 triangle *newtriangle;
04489
04490 do {
04491 newtriangle = (triangle *) traverse(&m->triangles);
04492 if (newtriangle == (triangle *) NULL) {
04493 return (triangle *) NULL;
04494 }
04495 } while (deadtri(newtriangle));
04496 return newtriangle;
04497 }
04498
04499
04500
04501
04502
04503
04504
04505 #ifdef ANSI_DECLARATORS
04506 void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
04507 #else
04508 void subsegdealloc(m, dyingsubseg)
04509 struct mesh *m;
04510 subseg *dyingsubseg;
04511 #endif
04512
04513 {
04514
04515
04516 killsubseg(dyingsubseg);
04517 pooldealloc(&m->subsegs, (VOID *) dyingsubseg);
04518 }
04519
04520
04521
04522
04523
04524
04525
04526 #ifdef ANSI_DECLARATORS
04527 subseg *subsegtraverse(struct mesh *m)
04528 #else
04529 subseg *subsegtraverse(m)
04530 struct mesh *m;
04531 #endif
04532
04533 {
04534 subseg *newsubseg;
04535
04536 do {
04537 newsubseg = (subseg *) traverse(&m->subsegs);
04538 if (newsubseg == (subseg *) NULL) {
04539 return (subseg *) NULL;
04540 }
04541 } while (deadsubseg(newsubseg));
04542 return newsubseg;
04543 }
04544
04545
04546
04547
04548
04549
04550
04551 #ifdef ANSI_DECLARATORS
04552 void vertexdealloc(struct mesh *m, vertex dyingvertex)
04553 #else
04554 void vertexdealloc(m, dyingvertex)
04555 struct mesh *m;
04556 vertex dyingvertex;
04557 #endif
04558
04559 {
04560
04561
04562 setvertextype(dyingvertex, DEADVERTEX);
04563 pooldealloc(&m->vertices, (VOID *) dyingvertex);
04564 }
04565
04566
04567
04568
04569
04570
04571
04572 #ifdef ANSI_DECLARATORS
04573 vertex vertextraverse(struct mesh *m)
04574 #else
04575 vertex vertextraverse(m)
04576 struct mesh *m;
04577 #endif
04578
04579 {
04580 vertex newvertex;
04581
04582 do {
04583 newvertex = (vertex) traverse(&m->vertices);
04584 if (newvertex == (vertex) NULL) {
04585 return (vertex) NULL;
04586 }
04587 } while (vertextype(newvertex) == DEADVERTEX);
04588 return newvertex;
04589 }
04590
04591
04592
04593
04594
04595
04596
04597
04598 #ifndef CDT_ONLY
04599
04600 #ifdef ANSI_DECLARATORS
04601 void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
04602 #else
04603 void badsubsegdealloc(m, dyingseg)
04604 struct mesh *m;
04605 struct badsubseg *dyingseg;
04606 #endif
04607
04608 {
04609
04610
04611 dyingseg->subsegorg = (vertex) NULL;
04612 pooldealloc(&m->badsubsegs, (VOID *) dyingseg);
04613 }
04614
04615 #endif
04616
04617
04618
04619
04620
04621
04622
04623 #ifndef CDT_ONLY
04624
04625 #ifdef ANSI_DECLARATORS
04626 struct badsubseg *badsubsegtraverse(struct mesh *m)
04627 #else
04628 struct badsubseg *badsubsegtraverse(m)
04629 struct mesh *m;
04630 #endif
04631
04632 {
04633 struct badsubseg *newseg;
04634
04635 do {
04636 newseg = (struct badsubseg *) traverse(&m->badsubsegs);
04637 if (newseg == (struct badsubseg *) NULL) {
04638 return (struct badsubseg *) NULL;
04639 }
04640 } while (newseg->subsegorg == (vertex) NULL);
04641 return newseg;
04642 }
04643
04644 #endif
04645
04646
04647
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658 #ifdef ANSI_DECLARATORS
04659 vertex getvertex(struct mesh *m, struct behavior *b, int number)
04660 #else
04661 vertex getvertex(m, b, number)
04662 struct mesh *m;
04663 struct behavior *b;
04664 int number;
04665 #endif
04666
04667 {
04668 VOID **getblock;
04669 char *foundvertex;
04670 unsigned long alignptr;
04671 int current;
04672
04673 getblock = m->vertices.firstblock;
04674 current = b->firstnumber;
04675
04676
04677 if (current + m->vertices.itemsfirstblock <= number) {
04678 getblock = (VOID **) *getblock;
04679 current += m->vertices.itemsfirstblock;
04680 while (current + m->vertices.itemsperblock <= number) {
04681 getblock = (VOID **) *getblock;
04682 current += m->vertices.itemsperblock;
04683 }
04684 }
04685
04686
04687 alignptr = (unsigned long) (getblock + 1);
04688 foundvertex = (char *) (alignptr + (unsigned long) m->vertices.alignbytes -
04689 (alignptr % (unsigned long) m->vertices.alignbytes));
04690 return (vertex) (foundvertex + m->vertices.itembytes * (number - current));
04691 }
04692
04693
04694
04695
04696
04697
04698
04699 #ifdef ANSI_DECLARATORS
04700 void triangledeinit(struct mesh *m, struct behavior *b)
04701 #else
04702 void triangledeinit(m, b)
04703 struct mesh *m;
04704 struct behavior *b;
04705 #endif
04706
04707 {
04708 pooldeinit(&m->triangles);
04709 trifree((VOID *) m->dummytribase);
04710 if (b->usesegments) {
04711 pooldeinit(&m->subsegs);
04712 trifree((VOID *) m->dummysubbase);
04713 }
04714 pooldeinit(&m->vertices);
04715 #ifndef CDT_ONLY
04716 if (b->quality) {
04717 pooldeinit(&m->badsubsegs);
04718 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
04719 pooldeinit(&m->badtriangles);
04720 pooldeinit(&m->flipstackers);
04721 }
04722 }
04723 #endif
04724 }
04725
04728
04729
04730
04734
04735
04736
04737
04738
04739
04740 #ifdef ANSI_DECLARATORS
04741 void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
04742 #else
04743 void maketriangle(m, b, newotri)
04744 struct mesh *m;
04745 struct behavior *b;
04746 struct otri *newotri;
04747 #endif
04748
04749 {
04750 int i;
04751
04752 newotri->tri = (triangle *) poolalloc(&m->triangles);
04753
04754 newotri->tri[0] = (triangle) m->dummytri;
04755 newotri->tri[1] = (triangle) m->dummytri;
04756 newotri->tri[2] = (triangle) m->dummytri;
04757
04758 newotri->tri[3] = (triangle) NULL;
04759 newotri->tri[4] = (triangle) NULL;
04760 newotri->tri[5] = (triangle) NULL;
04761 if (b->usesegments) {
04762
04763
04764 newotri->tri[6] = (triangle) m->dummysub;
04765 newotri->tri[7] = (triangle) m->dummysub;
04766 newotri->tri[8] = (triangle) m->dummysub;
04767 }
04768 for (i = 0; i < m->eextras; i++) {
04769 setelemattribute(*newotri, i, 0.0);
04770 }
04771 if (b->vararea) {
04772 setareabound(*newotri, -1.0);
04773 }
04774
04775 newotri->orient = 0;
04776 }
04777
04778
04779
04780
04781
04782
04783
04784 #ifdef ANSI_DECLARATORS
04785 void makesubseg(struct mesh *m, struct osub *newsubseg)
04786 #else
04787 void makesubseg(m, newsubseg)
04788 struct mesh *m;
04789 struct osub *newsubseg;
04790 #endif
04791
04792 {
04793 newsubseg->ss = (subseg *) poolalloc(&m->subsegs);
04794
04795
04796 newsubseg->ss[0] = (subseg) m->dummysub;
04797 newsubseg->ss[1] = (subseg) m->dummysub;
04798
04799 newsubseg->ss[2] = (subseg) NULL;
04800 newsubseg->ss[3] = (subseg) NULL;
04801 newsubseg->ss[4] = (subseg) NULL;
04802 newsubseg->ss[5] = (subseg) NULL;
04803
04804 newsubseg->ss[6] = (subseg) m->dummytri;
04805 newsubseg->ss[7] = (subseg) m->dummytri;
04806
04807 setmark(*newsubseg, 0);
04808
04809 newsubseg->ssorient = 0;
04810 }
04811
04814
04815
04816
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831
04832
04833 #define Absolute(a) ((a) >= 0.0 ? (a) : -(a))
04834
04835
04836
04837
04838
04839
04840
04841
04842
04843
04844
04845
04846
04847
04848
04849 #define Fast_Two_Sum_Tail(a, b, x, y) \
04850 bvirt = x - a; \
04851 y = b - bvirt
04852
04853 #define Fast_Two_Sum(a, b, x, y) \
04854 x = (REAL) (a + b); \
04855 Fast_Two_Sum_Tail(a, b, x, y)
04856
04857 #define Two_Sum_Tail(a, b, x, y) \
04858 bvirt = (REAL) (x - a); \
04859 avirt = x - bvirt; \
04860 bround = b - bvirt; \
04861 around = a - avirt; \
04862 y = around + bround
04863
04864 #define Two_Sum(a, b, x, y) \
04865 x = (REAL) (a + b); \
04866 Two_Sum_Tail(a, b, x, y)
04867
04868 #define Two_Diff_Tail(a, b, x, y) \
04869 bvirt = (REAL) (a - x); \
04870 avirt = x + bvirt; \
04871 bround = bvirt - b; \
04872 around = a - avirt; \
04873 y = around + bround
04874
04875 #define Two_Diff(a, b, x, y) \
04876 x = (REAL) (a - b); \
04877 Two_Diff_Tail(a, b, x, y)
04878
04879 #define Split(a, ahi, alo) \
04880 c = (REAL) (splitter * a); \
04881 abig = (REAL) (c - a); \
04882 ahi = c - abig; \
04883 alo = a - ahi
04884
04885 #define Two_Product_Tail(a, b, x, y) \
04886 Split(a, ahi, alo); \
04887 Split(b, bhi, blo); \
04888 err1 = x - (ahi * bhi); \
04889 err2 = err1 - (alo * bhi); \
04890 err3 = err2 - (ahi * blo); \
04891 y = (alo * blo) - err3
04892
04893 #define Two_Product(a, b, x, y) \
04894 x = (REAL) (a * b); \
04895 Two_Product_Tail(a, b, x, y)
04896
04897
04898
04899
04900 #define Two_Product_Presplit(a, b, bhi, blo, x, y) \
04901 x = (REAL) (a * b); \
04902 Split(a, ahi, alo); \
04903 err1 = x - (ahi * bhi); \
04904 err2 = err1 - (alo * bhi); \
04905 err3 = err2 - (ahi * blo); \
04906 y = (alo * blo) - err3
04907
04908
04909
04910 #define Square_Tail(a, x, y) \
04911 Split(a, ahi, alo); \
04912 err1 = x - (ahi * ahi); \
04913 err3 = err1 - ((ahi + ahi) * alo); \
04914 y = (alo * alo) - err3
04915
04916 #define Square(a, x, y) \
04917 x = (REAL) (a * a); \
04918 Square_Tail(a, x, y)
04919
04920
04921
04922
04923 #define Two_One_Sum(a1, a0, b, x2, x1, x0) \
04924 Two_Sum(a0, b , _i, x0); \
04925 Two_Sum(a1, _i, x2, x1)
04926
04927 #define Two_One_Diff(a1, a0, b, x2, x1, x0) \
04928 Two_Diff(a0, b , _i, x0); \
04929 Two_Sum( a1, _i, x2, x1)
04930
04931 #define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
04932 Two_One_Sum(a1, a0, b0, _j, _0, x0); \
04933 Two_One_Sum(_j, _0, b1, x3, x2, x1)
04934
04935 #define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
04936 Two_One_Diff(a1, a0, b0, _j, _0, x0); \
04937 Two_One_Diff(_j, _0, b1, x3, x2, x1)
04938
04939
04940
04941 #define Two_One_Product(a1, a0, b, x3, x2, x1, x0) \
04942 Split(b, bhi, blo); \
04943 Two_Product_Presplit(a0, b, bhi, blo, _i, x0); \
04944 Two_Product_Presplit(a1, b, bhi, blo, _j, _0); \
04945 Two_Sum(_i, _0, _k, x1); \
04946 Fast_Two_Sum(_j, _k, x3, x2)
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967 void exactinit()
04968 {
04969 REAL half;
04970 REAL check, lastcheck;
04971 int every_other;
04972 #ifdef LINUX
04973 int cword;
04974 #endif
04975
04976 #ifdef CPU86
04977 #ifdef SINGLE
04978 _control87(_PC_24, _MCW_PC);
04979 #else
04980 _control87(_PC_53, _MCW_PC);
04981 #endif
04982 #endif
04983 #ifdef LINUX
04984 #ifdef SINGLE
04985
04986 cword = 4210;
04987 #else
04988
04989 cword = 4722;
04990 #endif
04991 _FPU_SETCW(cword);
04992 #endif
04993
04994 every_other = 1;
04995 half = 0.5;
04996 epsilon = 1.0;
04997 splitter = 1.0;
04998 check = 1.0;
04999
05000
05001
05002
05003 do {
05004 lastcheck = check;
05005 epsilon *= half;
05006 if (every_other) {
05007 splitter *= 2.0;
05008 }
05009 every_other = !every_other;
05010 check = 1.0 + epsilon;
05011 } while ((check != 1.0) && (check != lastcheck));
05012 splitter += 1.0;
05013
05014 resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
05015 ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
05016 ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
05017 ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
05018 iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
05019 iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
05020 iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
05021 o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
05022 o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
05023 o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
05024 }
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040 #ifdef ANSI_DECLARATORS
05041 int fast_expansion_sum_zeroelim(int elen, REAL *e, int flen, REAL *f, REAL *h)
05042 #else
05043 int fast_expansion_sum_zeroelim(elen, e, flen, f, h)
05044 int elen;
05045 REAL *e;
05046 int flen;
05047 REAL *f;
05048 REAL *h;
05049 #endif
05050
05051 {
05052 REAL Q;
05053 INEXACT REAL Qnew;
05054 INEXACT REAL hh;
05055 INEXACT REAL bvirt;
05056 REAL avirt, bround, around;
05057 int eindex, findex, hindex;
05058 REAL enow, fnow;
05059
05060 enow = e[0];
05061 fnow = f[0];
05062 eindex = findex = 0;
05063 if ((fnow > enow) == (fnow > -enow)) {
05064 Q = enow;
05065 enow = e[++eindex];
05066 } else {
05067 Q = fnow;
05068 fnow = f[++findex];
05069 }
05070 hindex = 0;
05071 if ((eindex < elen) && (findex < flen)) {
05072 if ((fnow > enow) == (fnow > -enow)) {
05073 Fast_Two_Sum(enow, Q, Qnew, hh);
05074 enow = e[++eindex];
05075 } else {
05076 Fast_Two_Sum(fnow, Q, Qnew, hh);
05077 fnow = f[++findex];
05078 }
05079 Q = Qnew;
05080 if (hh != 0.0) {
05081 h[hindex++] = hh;
05082 }
05083 while ((eindex < elen) && (findex < flen)) {
05084 if ((fnow > enow) == (fnow > -enow)) {
05085 Two_Sum(Q, enow, Qnew, hh);
05086 enow = e[++eindex];
05087 } else {
05088 Two_Sum(Q, fnow, Qnew, hh);
05089 fnow = f[++findex];
05090 }
05091 Q = Qnew;
05092 if (hh != 0.0) {
05093 h[hindex++] = hh;
05094 }
05095 }
05096 }
05097 while (eindex < elen) {
05098 Two_Sum(Q, enow, Qnew, hh);
05099 enow = e[++eindex];
05100 Q = Qnew;
05101 if (hh != 0.0) {
05102 h[hindex++] = hh;
05103 }
05104 }
05105 while (findex < flen) {
05106 Two_Sum(Q, fnow, Qnew, hh);
05107 fnow = f[++findex];
05108 Q = Qnew;
05109 if (hh != 0.0) {
05110 h[hindex++] = hh;
05111 }
05112 }
05113 if ((Q != 0.0) || (hindex == 0)) {
05114 h[hindex++] = Q;
05115 }
05116 return hindex;
05117 }
05118
05119
05120
05121
05122
05123
05124
05125
05126
05127
05128
05129
05130
05131
05132
05133
05134 #ifdef ANSI_DECLARATORS
05135 int scale_expansion_zeroelim(int elen, REAL *e, REAL b, REAL *h)
05136 #else
05137 int scale_expansion_zeroelim(elen, e, b, h)
05138 int elen;
05139 REAL *e;
05140 REAL b;
05141 REAL *h;
05142 #endif
05143
05144 {
05145 INEXACT REAL Q, sum;
05146 REAL hh;
05147 INEXACT REAL product1;
05148 REAL product0;
05149 int eindex, hindex;
05150 REAL enow;
05151 INEXACT REAL bvirt;
05152 REAL avirt, bround, around;
05153 INEXACT REAL c;
05154 INEXACT REAL abig;
05155 REAL ahi, alo, bhi, blo;
05156 REAL err1, err2, err3;
05157
05158 Split(b, bhi, blo);
05159 Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
05160 hindex = 0;
05161 if (hh != 0) {
05162 h[hindex++] = hh;
05163 }
05164 for (eindex = 1; eindex < elen; eindex++) {
05165 enow = e[eindex];
05166 Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
05167 Two_Sum(Q, product0, sum, hh);
05168 if (hh != 0) {
05169 h[hindex++] = hh;
05170 }
05171 Fast_Two_Sum(product1, sum, Q, hh);
05172 if (hh != 0) {
05173 h[hindex++] = hh;
05174 }
05175 }
05176 if ((Q != 0.0) || (hindex == 0)) {
05177 h[hindex++] = Q;
05178 }
05179 return hindex;
05180 }
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190 #ifdef ANSI_DECLARATORS
05191 REAL estimate(int elen, REAL *e)
05192 #else
05193 REAL estimate(elen, e)
05194 int elen;
05195 REAL *e;
05196 #endif
05197
05198 {
05199 REAL Q;
05200 int eindex;
05201
05202 Q = e[0];
05203 for (eindex = 1; eindex < elen; eindex++) {
05204 Q += e[eindex];
05205 }
05206 return Q;
05207 }
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218
05219
05220
05221
05222
05223
05224
05225
05226
05227
05228
05229 #ifdef ANSI_DECLARATORS
05230 REAL counterclockwiseadapt(vertex pa, vertex pb, vertex pc, REAL detsum)
05231 #else
05232 REAL counterclockwiseadapt(pa, pb, pc, detsum)
05233 vertex pa;
05234 vertex pb;
05235 vertex pc;
05236 REAL detsum;
05237 #endif
05238
05239 {
05240 INEXACT REAL acx, acy, bcx, bcy;
05241 REAL acxtail, acytail, bcxtail, bcytail;
05242 INEXACT REAL detleft, detright;
05243 REAL detlefttail, detrighttail;
05244 REAL det, errbound;
05245 REAL B[4], C1[8], C2[12], D[16];
05246 INEXACT REAL B3;
05247 int C1length, C2length, Dlength;
05248 REAL u[4];
05249 INEXACT REAL u3;
05250 INEXACT REAL s1, t1;
05251 REAL s0, t0;
05252
05253 INEXACT REAL bvirt;
05254 REAL avirt, bround, around;
05255 INEXACT REAL c;
05256 INEXACT REAL abig;
05257 REAL ahi, alo, bhi, blo;
05258 REAL err1, err2, err3;
05259 INEXACT REAL _i, _j;
05260 REAL _0;
05261
05262 acx = (REAL) (pa[0] - pc[0]);
05263 bcx = (REAL) (pb[0] - pc[0]);
05264 acy = (REAL) (pa[1] - pc[1]);
05265 bcy = (REAL) (pb[1] - pc[1]);
05266
05267 Two_Product(acx, bcy, detleft, detlefttail);
05268 Two_Product(acy, bcx, detright, detrighttail);
05269
05270 Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
05271 B3, B[2], B[1], B[0]);
05272 B[3] = B3;
05273
05274 det = estimate(4, B);
05275 errbound = ccwerrboundB * detsum;
05276 if ((det >= errbound) || (-det >= errbound)) {
05277 return det;
05278 }
05279
05280 Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
05281 Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
05282 Two_Diff_Tail(pa[1], pc[1], acy, acytail);
05283 Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
05284
05285 if ((acxtail == 0.0) && (acytail == 0.0)
05286 && (bcxtail == 0.0) && (bcytail == 0.0)) {
05287 return det;
05288 }
05289
05290 errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
05291 det += (acx * bcytail + bcy * acxtail)
05292 - (acy * bcxtail + bcx * acytail);
05293 if ((det >= errbound) || (-det >= errbound)) {
05294 return det;
05295 }
05296
05297 Two_Product(acxtail, bcy, s1, s0);
05298 Two_Product(acytail, bcx, t1, t0);
05299 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05300 u[3] = u3;
05301 C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
05302
05303 Two_Product(acx, bcytail, s1, s0);
05304 Two_Product(acy, bcxtail, t1, t0);
05305 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05306 u[3] = u3;
05307 C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
05308
05309 Two_Product(acxtail, bcytail, s1, s0);
05310 Two_Product(acytail, bcxtail, t1, t0);
05311 Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
05312 u[3] = u3;
05313 Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
05314
05315 return(D[Dlength - 1]);
05316 }
05317
05318 #ifdef ANSI_DECLARATORS
05319 REAL counterclockwise(struct mesh *m, struct behavior *b,
05320 vertex pa, vertex pb, vertex pc)
05321 #else
05322 REAL counterclockwise(m, b, pa, pb, pc)
05323 struct mesh *m;
05324 struct behavior *b;
05325 vertex pa;
05326 vertex pb;
05327 vertex pc;
05328 #endif
05329
05330 {
05331 REAL detleft, detright, det;
05332 REAL detsum, errbound;
05333
05334 m->counterclockcount++;
05335
05336 detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
05337 detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
05338 det = detleft - detright;
05339
05340 if (b->noexact) {
05341 return det;
05342 }
05343
05344 if (detleft > 0.0) {
05345 if (detright <= 0.0) {
05346 return det;
05347 } else {
05348 detsum = detleft + detright;
05349 }
05350 } else if (detleft < 0.0) {
05351 if (detright >= 0.0) {
05352 return det;
05353 } else {
05354 detsum = -detleft - detright;
05355 }
05356 } else {
05357 return det;
05358 }
05359
05360 errbound = ccwerrboundA * detsum;
05361 if ((det >= errbound) || (-det >= errbound)) {
05362 return det;
05363 }
05364
05365 return counterclockwiseadapt(pa, pb, pc, detsum);
05366 }
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386
05387 #ifdef ANSI_DECLARATORS
05388 REAL incircleadapt(vertex pa, vertex pb, vertex pc, vertex pd, REAL permanent)
05389 #else
05390 REAL incircleadapt(pa, pb, pc, pd, permanent)
05391 vertex pa;
05392 vertex pb;
05393 vertex pc;
05394 vertex pd;
05395 REAL permanent;
05396 #endif
05397
05398 {
05399 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
05400 REAL det, errbound;
05401
05402 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
05403 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
05404 REAL bc[4], ca[4], ab[4];
05405 INEXACT REAL bc3, ca3, ab3;
05406 REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
05407 int axbclen, axxbclen, aybclen, ayybclen, alen;
05408 REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
05409 int bxcalen, bxxcalen, bycalen, byycalen, blen;
05410 REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
05411 int cxablen, cxxablen, cyablen, cyyablen, clen;
05412 REAL abdet[64];
05413 int ablen;
05414 REAL fin1[1152], fin2[1152];
05415 REAL *finnow, *finother, *finswap;
05416 int finlength;
05417
05418 REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
05419 INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
05420 REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
05421 REAL aa[4], bb[4], cc[4];
05422 INEXACT REAL aa3, bb3, cc3;
05423 INEXACT REAL ti1, tj1;
05424 REAL ti0, tj0;
05425 REAL u[4], v[4];
05426 INEXACT REAL u3, v3;
05427 REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
05428 REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
05429 int temp8len, temp16alen, temp16blen, temp16clen;
05430 int temp32alen, temp32blen, temp48len, temp64len;
05431 REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
05432 int axtbblen, axtcclen, aytbblen, aytcclen;
05433 REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
05434 int bxtaalen, bxtcclen, bytaalen, bytcclen;
05435 REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
05436 int cxtaalen, cxtbblen, cytaalen, cytbblen;
05437 REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
05438 int axtbclen=0, aytbclen=0, bxtcalen=0, bytcalen=0, cxtablen=0, cytablen=0;
05439 REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
05440 int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
05441 REAL axtbctt[8], aytbctt[8], bxtcatt[8];
05442 REAL bytcatt[8], cxtabtt[8], cytabtt[8];
05443 int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
05444 REAL abt[8], bct[8], cat[8];
05445 int abtlen, bctlen, catlen;
05446 REAL abtt[4], bctt[4], catt[4];
05447 int abttlen, bcttlen, cattlen;
05448 INEXACT REAL abtt3, bctt3, catt3;
05449 REAL negate;
05450
05451 INEXACT REAL bvirt;
05452 REAL avirt, bround, around;
05453 INEXACT REAL c;
05454 INEXACT REAL abig;
05455 REAL ahi, alo, bhi, blo;
05456 REAL err1, err2, err3;
05457 INEXACT REAL _i, _j;
05458 REAL _0;
05459
05460 adx = (REAL) (pa[0] - pd[0]);
05461 bdx = (REAL) (pb[0] - pd[0]);
05462 cdx = (REAL) (pc[0] - pd[0]);
05463 ady = (REAL) (pa[1] - pd[1]);
05464 bdy = (REAL) (pb[1] - pd[1]);
05465 cdy = (REAL) (pc[1] - pd[1]);
05466
05467 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
05468 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
05469 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
05470 bc[3] = bc3;
05471 axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
05472 axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
05473 aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
05474 ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
05475 alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
05476
05477 Two_Product(cdx, ady, cdxady1, cdxady0);
05478 Two_Product(adx, cdy, adxcdy1, adxcdy0);
05479 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
05480 ca[3] = ca3;
05481 bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
05482 bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
05483 bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
05484 byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
05485 blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
05486
05487 Two_Product(adx, bdy, adxbdy1, adxbdy0);
05488 Two_Product(bdx, ady, bdxady1, bdxady0);
05489 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
05490 ab[3] = ab3;
05491 cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
05492 cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
05493 cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
05494 cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
05495 clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
05496
05497 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
05498 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
05499
05500 det = estimate(finlength, fin1);
05501 errbound = iccerrboundB * permanent;
05502 if ((det >= errbound) || (-det >= errbound)) {
05503 return det;
05504 }
05505
05506 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
05507 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
05508 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
05509 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
05510 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
05511 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
05512 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
05513 && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
05514 return det;
05515 }
05516
05517 errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
05518 det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
05519 - (bdy * cdxtail + cdx * bdytail))
05520 + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
05521 + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
05522 - (cdy * adxtail + adx * cdytail))
05523 + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
05524 + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
05525 - (ady * bdxtail + bdx * adytail))
05526 + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
05527 if ((det >= errbound) || (-det >= errbound)) {
05528 return det;
05529 }
05530
05531 finnow = fin1;
05532 finother = fin2;
05533
05534 if ((bdxtail != 0.0) || (bdytail != 0.0)
05535 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05536 Square(adx, adxadx1, adxadx0);
05537 Square(ady, adyady1, adyady0);
05538 Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
05539 aa[3] = aa3;
05540 }
05541 if ((cdxtail != 0.0) || (cdytail != 0.0)
05542 || (adxtail != 0.0) || (adytail != 0.0)) {
05543 Square(bdx, bdxbdx1, bdxbdx0);
05544 Square(bdy, bdybdy1, bdybdy0);
05545 Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
05546 bb[3] = bb3;
05547 }
05548 if ((adxtail != 0.0) || (adytail != 0.0)
05549 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05550 Square(cdx, cdxcdx1, cdxcdx0);
05551 Square(cdy, cdycdy1, cdycdy0);
05552 Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
05553 cc[3] = cc3;
05554 }
05555
05556 if (adxtail != 0.0) {
05557 axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
05558 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
05559 temp16a);
05560
05561 axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
05562 temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
05563
05564 axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
05565 temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
05566
05567 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05568 temp16blen, temp16b, temp32a);
05569 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05570 temp32alen, temp32a, temp48);
05571 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05572 temp48, finother);
05573 finswap = finnow; finnow = finother; finother = finswap;
05574 }
05575 if (adytail != 0.0) {
05576 aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
05577 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
05578 temp16a);
05579
05580 aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
05581 temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
05582
05583 aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
05584 temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
05585
05586 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05587 temp16blen, temp16b, temp32a);
05588 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05589 temp32alen, temp32a, temp48);
05590 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05591 temp48, finother);
05592 finswap = finnow; finnow = finother; finother = finswap;
05593 }
05594 if (bdxtail != 0.0) {
05595 bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
05596 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
05597 temp16a);
05598
05599 bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
05600 temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
05601
05602 bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
05603 temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
05604
05605 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05606 temp16blen, temp16b, temp32a);
05607 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05608 temp32alen, temp32a, temp48);
05609 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05610 temp48, finother);
05611 finswap = finnow; finnow = finother; finother = finswap;
05612 }
05613 if (bdytail != 0.0) {
05614 bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
05615 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
05616 temp16a);
05617
05618 bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
05619 temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
05620
05621 bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
05622 temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
05623
05624 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05625 temp16blen, temp16b, temp32a);
05626 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05627 temp32alen, temp32a, temp48);
05628 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05629 temp48, finother);
05630 finswap = finnow; finnow = finother; finother = finswap;
05631 }
05632 if (cdxtail != 0.0) {
05633 cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
05634 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
05635 temp16a);
05636
05637 cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
05638 temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
05639
05640 cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
05641 temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
05642
05643 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05644 temp16blen, temp16b, temp32a);
05645 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05646 temp32alen, temp32a, temp48);
05647 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05648 temp48, finother);
05649 finswap = finnow; finnow = finother; finother = finswap;
05650 }
05651 if (cdytail != 0.0) {
05652 cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
05653 temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
05654 temp16a);
05655
05656 cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
05657 temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
05658
05659 cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
05660 temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
05661
05662 temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05663 temp16blen, temp16b, temp32a);
05664 temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
05665 temp32alen, temp32a, temp48);
05666 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05667 temp48, finother);
05668 finswap = finnow; finnow = finother; finother = finswap;
05669 }
05670
05671 if ((adxtail != 0.0) || (adytail != 0.0)) {
05672 if ((bdxtail != 0.0) || (bdytail != 0.0)
05673 || (cdxtail != 0.0) || (cdytail != 0.0)) {
05674 Two_Product(bdxtail, cdy, ti1, ti0);
05675 Two_Product(bdx, cdytail, tj1, tj0);
05676 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05677 u[3] = u3;
05678 negate = -bdy;
05679 Two_Product(cdxtail, negate, ti1, ti0);
05680 negate = -bdytail;
05681 Two_Product(cdx, negate, tj1, tj0);
05682 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05683 v[3] = v3;
05684 bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
05685
05686 Two_Product(bdxtail, cdytail, ti1, ti0);
05687 Two_Product(cdxtail, bdytail, tj1, tj0);
05688 Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
05689 bctt[3] = bctt3;
05690 bcttlen = 4;
05691 } else {
05692 bct[0] = 0.0;
05693 bctlen = 1;
05694 bctt[0] = 0.0;
05695 bcttlen = 1;
05696 }
05697
05698 if (adxtail != 0.0) {
05699 temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
05700 axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
05701 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
05702 temp32a);
05703 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05704 temp32alen, temp32a, temp48);
05705 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05706 temp48, finother);
05707 finswap = finnow; finnow = finother; finother = finswap;
05708 if (bdytail != 0.0) {
05709 temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
05710 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05711 temp16a);
05712 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05713 temp16a, finother);
05714 finswap = finnow; finnow = finother; finother = finswap;
05715 }
05716 if (cdytail != 0.0) {
05717 temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
05718 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05719 temp16a);
05720 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05721 temp16a, finother);
05722 finswap = finnow; finnow = finother; finother = finswap;
05723 }
05724
05725 temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
05726 temp32a);
05727 axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
05728 temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
05729 temp16a);
05730 temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
05731 temp16b);
05732 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05733 temp16blen, temp16b, temp32b);
05734 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05735 temp32blen, temp32b, temp64);
05736 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05737 temp64, finother);
05738 finswap = finnow; finnow = finother; finother = finswap;
05739 }
05740 if (adytail != 0.0) {
05741 temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
05742 aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
05743 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
05744 temp32a);
05745 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05746 temp32alen, temp32a, temp48);
05747 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05748 temp48, finother);
05749 finswap = finnow; finnow = finother; finother = finswap;
05750
05751
05752 temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
05753 temp32a);
05754 aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
05755 temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
05756 temp16a);
05757 temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
05758 temp16b);
05759 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05760 temp16blen, temp16b, temp32b);
05761 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05762 temp32blen, temp32b, temp64);
05763 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05764 temp64, finother);
05765 finswap = finnow; finnow = finother; finother = finswap;
05766 }
05767 }
05768 if ((bdxtail != 0.0) || (bdytail != 0.0)) {
05769 if ((cdxtail != 0.0) || (cdytail != 0.0)
05770 || (adxtail != 0.0) || (adytail != 0.0)) {
05771 Two_Product(cdxtail, ady, ti1, ti0);
05772 Two_Product(cdx, adytail, tj1, tj0);
05773 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05774 u[3] = u3;
05775 negate = -cdy;
05776 Two_Product(adxtail, negate, ti1, ti0);
05777 negate = -cdytail;
05778 Two_Product(adx, negate, tj1, tj0);
05779 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05780 v[3] = v3;
05781 catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
05782
05783 Two_Product(cdxtail, adytail, ti1, ti0);
05784 Two_Product(adxtail, cdytail, tj1, tj0);
05785 Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
05786 catt[3] = catt3;
05787 cattlen = 4;
05788 } else {
05789 cat[0] = 0.0;
05790 catlen = 1;
05791 catt[0] = 0.0;
05792 cattlen = 1;
05793 }
05794
05795 if (bdxtail != 0.0) {
05796 temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
05797 bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
05798 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
05799 temp32a);
05800 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05801 temp32alen, temp32a, temp48);
05802 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05803 temp48, finother);
05804 finswap = finnow; finnow = finother; finother = finswap;
05805 if (cdytail != 0.0) {
05806 temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
05807 temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
05808 temp16a);
05809 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05810 temp16a, finother);
05811 finswap = finnow; finnow = finother; finother = finswap;
05812 }
05813 if (adytail != 0.0) {
05814 temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
05815 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05816 temp16a);
05817 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05818 temp16a, finother);
05819 finswap = finnow; finnow = finother; finother = finswap;
05820 }
05821
05822 temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
05823 temp32a);
05824 bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
05825 temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
05826 temp16a);
05827 temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
05828 temp16b);
05829 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05830 temp16blen, temp16b, temp32b);
05831 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05832 temp32blen, temp32b, temp64);
05833 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05834 temp64, finother);
05835 finswap = finnow; finnow = finother; finother = finswap;
05836 }
05837 if (bdytail != 0.0) {
05838 temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
05839 bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
05840 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
05841 temp32a);
05842 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05843 temp32alen, temp32a, temp48);
05844 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05845 temp48, finother);
05846 finswap = finnow; finnow = finother; finother = finswap;
05847
05848
05849 temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
05850 temp32a);
05851 bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
05852 temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
05853 temp16a);
05854 temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
05855 temp16b);
05856 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05857 temp16blen, temp16b, temp32b);
05858 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05859 temp32blen, temp32b, temp64);
05860 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05861 temp64, finother);
05862 finswap = finnow; finnow = finother; finother = finswap;
05863 }
05864 }
05865 if ((cdxtail != 0.0) || (cdytail != 0.0)) {
05866 if ((adxtail != 0.0) || (adytail != 0.0)
05867 || (bdxtail != 0.0) || (bdytail != 0.0)) {
05868 Two_Product(adxtail, bdy, ti1, ti0);
05869 Two_Product(adx, bdytail, tj1, tj0);
05870 Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
05871 u[3] = u3;
05872 negate = -ady;
05873 Two_Product(bdxtail, negate, ti1, ti0);
05874 negate = -adytail;
05875 Two_Product(bdx, negate, tj1, tj0);
05876 Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
05877 v[3] = v3;
05878 abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
05879
05880 Two_Product(adxtail, bdytail, ti1, ti0);
05881 Two_Product(bdxtail, adytail, tj1, tj0);
05882 Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
05883 abtt[3] = abtt3;
05884 abttlen = 4;
05885 } else {
05886 abt[0] = 0.0;
05887 abtlen = 1;
05888 abtt[0] = 0.0;
05889 abttlen = 1;
05890 }
05891
05892 if (cdxtail != 0.0) {
05893 temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
05894 cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
05895 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
05896 temp32a);
05897 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05898 temp32alen, temp32a, temp48);
05899 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05900 temp48, finother);
05901 finswap = finnow; finnow = finother; finother = finswap;
05902 if (adytail != 0.0) {
05903 temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
05904 temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
05905 temp16a);
05906 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05907 temp16a, finother);
05908 finswap = finnow; finnow = finother; finother = finswap;
05909 }
05910 if (bdytail != 0.0) {
05911 temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
05912 temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
05913 temp16a);
05914 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
05915 temp16a, finother);
05916 finswap = finnow; finnow = finother; finother = finswap;
05917 }
05918
05919 temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
05920 temp32a);
05921 cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
05922 temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
05923 temp16a);
05924 temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
05925 temp16b);
05926 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05927 temp16blen, temp16b, temp32b);
05928 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05929 temp32blen, temp32b, temp64);
05930 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05931 temp64, finother);
05932 finswap = finnow; finnow = finother; finother = finswap;
05933 }
05934 if (cdytail != 0.0) {
05935 temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
05936 cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
05937 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
05938 temp32a);
05939 temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05940 temp32alen, temp32a, temp48);
05941 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
05942 temp48, finother);
05943 finswap = finnow; finnow = finother; finother = finswap;
05944
05945
05946 temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
05947 temp32a);
05948 cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
05949 temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
05950 temp16a);
05951 temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
05952 temp16b);
05953 temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
05954 temp16blen, temp16b, temp32b);
05955 temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
05956 temp32blen, temp32b, temp64);
05957 finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
05958 temp64, finother);
05959 finswap = finnow; finnow = finother; finother = finswap;
05960 }
05961 }
05962
05963 return finnow[finlength - 1];
05964 }
05965
05966 #ifdef ANSI_DECLARATORS
05967 REAL incircle(struct mesh *m, struct behavior *b,
05968 vertex pa, vertex pb, vertex pc, vertex pd)
05969 #else
05970 REAL incircle(m, b, pa, pb, pc, pd)
05971 struct mesh *m;
05972 struct behavior *b;
05973 vertex pa;
05974 vertex pb;
05975 vertex pc;
05976 vertex pd;
05977 #endif
05978
05979 {
05980 REAL adx, bdx, cdx, ady, bdy, cdy;
05981 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
05982 REAL alift, blift, clift;
05983 REAL det;
05984 REAL permanent, errbound;
05985
05986 m->incirclecount++;
05987
05988 adx = pa[0] - pd[0];
05989 bdx = pb[0] - pd[0];
05990 cdx = pc[0] - pd[0];
05991 ady = pa[1] - pd[1];
05992 bdy = pb[1] - pd[1];
05993 cdy = pc[1] - pd[1];
05994
05995 bdxcdy = bdx * cdy;
05996 cdxbdy = cdx * bdy;
05997 alift = adx * adx + ady * ady;
05998
05999 cdxady = cdx * ady;
06000 adxcdy = adx * cdy;
06001 blift = bdx * bdx + bdy * bdy;
06002
06003 adxbdy = adx * bdy;
06004 bdxady = bdx * ady;
06005 clift = cdx * cdx + cdy * cdy;
06006
06007 det = alift * (bdxcdy - cdxbdy)
06008 + blift * (cdxady - adxcdy)
06009 + clift * (adxbdy - bdxady);
06010
06011 if (b->noexact) {
06012 return det;
06013 }
06014
06015 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
06016 + (Absolute(cdxady) + Absolute(adxcdy)) * blift
06017 + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
06018 errbound = iccerrboundA * permanent;
06019 if ((det > errbound) || (-det > errbound)) {
06020 return det;
06021 }
06022
06023 return incircleadapt(pa, pb, pc, pd, permanent);
06024 }
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048 #ifdef ANSI_DECLARATORS
06049 REAL orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd,
06050 REAL aheight, REAL bheight, REAL cheight, REAL dheight,
06051 REAL permanent)
06052 #else
06053 REAL orient3dadapt(pa, pb, pc, pd,
06054 aheight, bheight, cheight, dheight, permanent)
06055 vertex pa;
06056 vertex pb;
06057 vertex pc;
06058 vertex pd;
06059 REAL aheight;
06060 REAL bheight;
06061 REAL cheight;
06062 REAL dheight;
06063 REAL permanent;
06064 #endif
06065
06066 {
06067 INEXACT REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06068 REAL det, errbound;
06069
06070 INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
06071 REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
06072 REAL bc[4], ca[4], ab[4];
06073 INEXACT REAL bc3, ca3, ab3;
06074 REAL adet[8], bdet[8], cdet[8];
06075 int alen, blen, clen;
06076 REAL abdet[16];
06077 int ablen;
06078 REAL *finnow, *finother, *finswap;
06079 REAL fin1[192], fin2[192];
06080 int finlength;
06081
06082 REAL adxtail, bdxtail, cdxtail;
06083 REAL adytail, bdytail, cdytail;
06084 REAL adheighttail, bdheighttail, cdheighttail;
06085 INEXACT REAL at_blarge, at_clarge;
06086 INEXACT REAL bt_clarge, bt_alarge;
06087 INEXACT REAL ct_alarge, ct_blarge;
06088 REAL at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
06089 int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
06090 INEXACT REAL bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
06091 INEXACT REAL adxt_cdy1, adxt_bdy1, bdxt_ady1;
06092 REAL bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
06093 REAL adxt_cdy0, adxt_bdy0, bdxt_ady0;
06094 INEXACT REAL bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
06095 INEXACT REAL adyt_cdx1, adyt_bdx1, bdyt_adx1;
06096 REAL bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
06097 REAL adyt_cdx0, adyt_bdx0, bdyt_adx0;
06098 REAL bct[8], cat[8], abt[8];
06099 int bctlen, catlen, abtlen;
06100 INEXACT REAL bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
06101 INEXACT REAL adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
06102 REAL bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
06103 REAL adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
06104 REAL u[4], v[12], w[16];
06105 INEXACT REAL u3;
06106 int vlength, wlength;
06107 REAL negate;
06108
06109 INEXACT REAL bvirt;
06110 REAL avirt, bround, around;
06111 INEXACT REAL c;
06112 INEXACT REAL abig;
06113 REAL ahi, alo, bhi, blo;
06114 REAL err1, err2, err3;
06115 INEXACT REAL _i, _j, _k;
06116 REAL _0;
06117
06118 adx = (REAL) (pa[0] - pd[0]);
06119 bdx = (REAL) (pb[0] - pd[0]);
06120 cdx = (REAL) (pc[0] - pd[0]);
06121 ady = (REAL) (pa[1] - pd[1]);
06122 bdy = (REAL) (pb[1] - pd[1]);
06123 cdy = (REAL) (pc[1] - pd[1]);
06124 adheight = (REAL) (aheight - dheight);
06125 bdheight = (REAL) (bheight - dheight);
06126 cdheight = (REAL) (cheight - dheight);
06127
06128 Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
06129 Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
06130 Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
06131 bc[3] = bc3;
06132 alen = scale_expansion_zeroelim(4, bc, adheight, adet);
06133
06134 Two_Product(cdx, ady, cdxady1, cdxady0);
06135 Two_Product(adx, cdy, adxcdy1, adxcdy0);
06136 Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
06137 ca[3] = ca3;
06138 blen = scale_expansion_zeroelim(4, ca, bdheight, bdet);
06139
06140 Two_Product(adx, bdy, adxbdy1, adxbdy0);
06141 Two_Product(bdx, ady, bdxady1, bdxady0);
06142 Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
06143 ab[3] = ab3;
06144 clen = scale_expansion_zeroelim(4, ab, cdheight, cdet);
06145
06146 ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
06147 finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
06148
06149 det = estimate(finlength, fin1);
06150 errbound = o3derrboundB * permanent;
06151 if ((det >= errbound) || (-det >= errbound)) {
06152 return det;
06153 }
06154
06155 Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
06156 Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
06157 Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
06158 Two_Diff_Tail(pa[1], pd[1], ady, adytail);
06159 Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
06160 Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
06161 Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
06162 Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
06163 Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
06164
06165 if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
06166 (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
06167 (adheighttail == 0.0) &&
06168 (bdheighttail == 0.0) &&
06169 (cdheighttail == 0.0)) {
06170 return det;
06171 }
06172
06173 errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
06174 det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
06175 (bdy * cdxtail + cdx * bdytail)) +
06176 adheighttail * (bdx * cdy - bdy * cdx)) +
06177 (bdheight * ((cdx * adytail + ady * cdxtail) -
06178 (cdy * adxtail + adx * cdytail)) +
06179 bdheighttail * (cdx * ady - cdy * adx)) +
06180 (cdheight * ((adx * bdytail + bdy * adxtail) -
06181 (ady * bdxtail + bdx * adytail)) +
06182 cdheighttail * (adx * bdy - ady * bdx));
06183 if ((det >= errbound) || (-det >= errbound)) {
06184 return det;
06185 }
06186
06187 finnow = fin1;
06188 finother = fin2;
06189
06190 if (adxtail == 0.0) {
06191 if (adytail == 0.0) {
06192 at_b[0] = 0.0;
06193 at_blen = 1;
06194 at_c[0] = 0.0;
06195 at_clen = 1;
06196 } else {
06197 negate = -adytail;
06198 Two_Product(negate, bdx, at_blarge, at_b[0]);
06199 at_b[1] = at_blarge;
06200 at_blen = 2;
06201 Two_Product(adytail, cdx, at_clarge, at_c[0]);
06202 at_c[1] = at_clarge;
06203 at_clen = 2;
06204 }
06205 } else {
06206 if (adytail == 0.0) {
06207 Two_Product(adxtail, bdy, at_blarge, at_b[0]);
06208 at_b[1] = at_blarge;
06209 at_blen = 2;
06210 negate = -adxtail;
06211 Two_Product(negate, cdy, at_clarge, at_c[0]);
06212 at_c[1] = at_clarge;
06213 at_clen = 2;
06214 } else {
06215 Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
06216 Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
06217 Two_Two_Diff(adxt_bdy1, adxt_bdy0, adyt_bdx1, adyt_bdx0,
06218 at_blarge, at_b[2], at_b[1], at_b[0]);
06219 at_b[3] = at_blarge;
06220 at_blen = 4;
06221 Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
06222 Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
06223 Two_Two_Diff(adyt_cdx1, adyt_cdx0, adxt_cdy1, adxt_cdy0,
06224 at_clarge, at_c[2], at_c[1], at_c[0]);
06225 at_c[3] = at_clarge;
06226 at_clen = 4;
06227 }
06228 }
06229 if (bdxtail == 0.0) {
06230 if (bdytail == 0.0) {
06231 bt_c[0] = 0.0;
06232 bt_clen = 1;
06233 bt_a[0] = 0.0;
06234 bt_alen = 1;
06235 } else {
06236 negate = -bdytail;
06237 Two_Product(negate, cdx, bt_clarge, bt_c[0]);
06238 bt_c[1] = bt_clarge;
06239 bt_clen = 2;
06240 Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
06241 bt_a[1] = bt_alarge;
06242 bt_alen = 2;
06243 }
06244 } else {
06245 if (bdytail == 0.0) {
06246 Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
06247 bt_c[1] = bt_clarge;
06248 bt_clen = 2;
06249 negate = -bdxtail;
06250 Two_Product(negate, ady, bt_alarge, bt_a[0]);
06251 bt_a[1] = bt_alarge;
06252 bt_alen = 2;
06253 } else {
06254 Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
06255 Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
06256 Two_Two_Diff(bdxt_cdy1, bdxt_cdy0, bdyt_cdx1, bdyt_cdx0,
06257 bt_clarge, bt_c[2], bt_c[1], bt_c[0]);
06258 bt_c[3] = bt_clarge;
06259 bt_clen = 4;
06260 Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
06261 Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
06262 Two_Two_Diff(bdyt_adx1, bdyt_adx0, bdxt_ady1, bdxt_ady0,
06263 bt_alarge, bt_a[2], bt_a[1], bt_a[0]);
06264 bt_a[3] = bt_alarge;
06265 bt_alen = 4;
06266 }
06267 }
06268 if (cdxtail == 0.0) {
06269 if (cdytail == 0.0) {
06270 ct_a[0] = 0.0;
06271 ct_alen = 1;
06272 ct_b[0] = 0.0;
06273 ct_blen = 1;
06274 } else {
06275 negate = -cdytail;
06276 Two_Product(negate, adx, ct_alarge, ct_a[0]);
06277 ct_a[1] = ct_alarge;
06278 ct_alen = 2;
06279 Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
06280 ct_b[1] = ct_blarge;
06281 ct_blen = 2;
06282 }
06283 } else {
06284 if (cdytail == 0.0) {
06285 Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
06286 ct_a[1] = ct_alarge;
06287 ct_alen = 2;
06288 negate = -cdxtail;
06289 Two_Product(negate, bdy, ct_blarge, ct_b[0]);
06290 ct_b[1] = ct_blarge;
06291 ct_blen = 2;
06292 } else {
06293 Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
06294 Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
06295 Two_Two_Diff(cdxt_ady1, cdxt_ady0, cdyt_adx1, cdyt_adx0,
06296 ct_alarge, ct_a[2], ct_a[1], ct_a[0]);
06297 ct_a[3] = ct_alarge;
06298 ct_alen = 4;
06299 Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
06300 Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
06301 Two_Two_Diff(cdyt_bdx1, cdyt_bdx0, cdxt_bdy1, cdxt_bdy0,
06302 ct_blarge, ct_b[2], ct_b[1], ct_b[0]);
06303 ct_b[3] = ct_blarge;
06304 ct_blen = 4;
06305 }
06306 }
06307
06308 bctlen = fast_expansion_sum_zeroelim(bt_clen, bt_c, ct_blen, ct_b, bct);
06309 wlength = scale_expansion_zeroelim(bctlen, bct, adheight, w);
06310 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06311 finother);
06312 finswap = finnow; finnow = finother; finother = finswap;
06313
06314 catlen = fast_expansion_sum_zeroelim(ct_alen, ct_a, at_clen, at_c, cat);
06315 wlength = scale_expansion_zeroelim(catlen, cat, bdheight, w);
06316 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06317 finother);
06318 finswap = finnow; finnow = finother; finother = finswap;
06319
06320 abtlen = fast_expansion_sum_zeroelim(at_blen, at_b, bt_alen, bt_a, abt);
06321 wlength = scale_expansion_zeroelim(abtlen, abt, cdheight, w);
06322 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06323 finother);
06324 finswap = finnow; finnow = finother; finother = finswap;
06325
06326 if (adheighttail != 0.0) {
06327 vlength = scale_expansion_zeroelim(4, bc, adheighttail, v);
06328 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06329 finother);
06330 finswap = finnow; finnow = finother; finother = finswap;
06331 }
06332 if (bdheighttail != 0.0) {
06333 vlength = scale_expansion_zeroelim(4, ca, bdheighttail, v);
06334 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06335 finother);
06336 finswap = finnow; finnow = finother; finother = finswap;
06337 }
06338 if (cdheighttail != 0.0) {
06339 vlength = scale_expansion_zeroelim(4, ab, cdheighttail, v);
06340 finlength = fast_expansion_sum_zeroelim(finlength, finnow, vlength, v,
06341 finother);
06342 finswap = finnow; finnow = finother; finother = finswap;
06343 }
06344
06345 if (adxtail != 0.0) {
06346 if (bdytail != 0.0) {
06347 Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
06348 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
06349 u[3] = u3;
06350 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06351 finother);
06352 finswap = finnow; finnow = finother; finother = finswap;
06353 if (cdheighttail != 0.0) {
06354 Two_One_Product(adxt_bdyt1, adxt_bdyt0, cdheighttail,
06355 u3, u[2], u[1], u[0]);
06356 u[3] = u3;
06357 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06358 finother);
06359 finswap = finnow; finnow = finother; finother = finswap;
06360 }
06361 }
06362 if (cdytail != 0.0) {
06363 negate = -adxtail;
06364 Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
06365 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
06366 u[3] = u3;
06367 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06368 finother);
06369 finswap = finnow; finnow = finother; finother = finswap;
06370 if (bdheighttail != 0.0) {
06371 Two_One_Product(adxt_cdyt1, adxt_cdyt0, bdheighttail,
06372 u3, u[2], u[1], u[0]);
06373 u[3] = u3;
06374 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06375 finother);
06376 finswap = finnow; finnow = finother; finother = finswap;
06377 }
06378 }
06379 }
06380 if (bdxtail != 0.0) {
06381 if (cdytail != 0.0) {
06382 Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
06383 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
06384 u[3] = u3;
06385 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06386 finother);
06387 finswap = finnow; finnow = finother; finother = finswap;
06388 if (adheighttail != 0.0) {
06389 Two_One_Product(bdxt_cdyt1, bdxt_cdyt0, adheighttail,
06390 u3, u[2], u[1], u[0]);
06391 u[3] = u3;
06392 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06393 finother);
06394 finswap = finnow; finnow = finother; finother = finswap;
06395 }
06396 }
06397 if (adytail != 0.0) {
06398 negate = -bdxtail;
06399 Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
06400 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
06401 u[3] = u3;
06402 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06403 finother);
06404 finswap = finnow; finnow = finother; finother = finswap;
06405 if (cdheighttail != 0.0) {
06406 Two_One_Product(bdxt_adyt1, bdxt_adyt0, cdheighttail,
06407 u3, u[2], u[1], u[0]);
06408 u[3] = u3;
06409 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06410 finother);
06411 finswap = finnow; finnow = finother; finother = finswap;
06412 }
06413 }
06414 }
06415 if (cdxtail != 0.0) {
06416 if (adytail != 0.0) {
06417 Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
06418 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
06419 u[3] = u3;
06420 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06421 finother);
06422 finswap = finnow; finnow = finother; finother = finswap;
06423 if (bdheighttail != 0.0) {
06424 Two_One_Product(cdxt_adyt1, cdxt_adyt0, bdheighttail,
06425 u3, u[2], u[1], u[0]);
06426 u[3] = u3;
06427 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06428 finother);
06429 finswap = finnow; finnow = finother; finother = finswap;
06430 }
06431 }
06432 if (bdytail != 0.0) {
06433 negate = -cdxtail;
06434 Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
06435 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
06436 u[3] = u3;
06437 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06438 finother);
06439 finswap = finnow; finnow = finother; finother = finswap;
06440 if (adheighttail != 0.0) {
06441 Two_One_Product(cdxt_bdyt1, cdxt_bdyt0, adheighttail,
06442 u3, u[2], u[1], u[0]);
06443 u[3] = u3;
06444 finlength = fast_expansion_sum_zeroelim(finlength, finnow, 4, u,
06445 finother);
06446 finswap = finnow; finnow = finother; finother = finswap;
06447 }
06448 }
06449 }
06450
06451 if (adheighttail != 0.0) {
06452 wlength = scale_expansion_zeroelim(bctlen, bct, adheighttail, w);
06453 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06454 finother);
06455 finswap = finnow; finnow = finother; finother = finswap;
06456 }
06457 if (bdheighttail != 0.0) {
06458 wlength = scale_expansion_zeroelim(catlen, cat, bdheighttail, w);
06459 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06460 finother);
06461 finswap = finnow; finnow = finother; finother = finswap;
06462 }
06463 if (cdheighttail != 0.0) {
06464 wlength = scale_expansion_zeroelim(abtlen, abt, cdheighttail, w);
06465 finlength = fast_expansion_sum_zeroelim(finlength, finnow, wlength, w,
06466 finother);
06467 finswap = finnow; finnow = finother; finother = finswap;
06468 }
06469
06470 return finnow[finlength - 1];
06471 }
06472
06473 #ifdef ANSI_DECLARATORS
06474 REAL orient3d(struct mesh *m, struct behavior *b,
06475 vertex pa, vertex pb, vertex pc, vertex pd,
06476 REAL aheight, REAL bheight, REAL cheight, REAL dheight)
06477 #else
06478 REAL orient3d(m, b, pa, pb, pc, pd, aheight, bheight, cheight, dheight)
06479 struct mesh *m;
06480 struct behavior *b;
06481 vertex pa;
06482 vertex pb;
06483 vertex pc;
06484 vertex pd;
06485 REAL aheight;
06486 REAL bheight;
06487 REAL cheight;
06488 REAL dheight;
06489 #endif
06490
06491 {
06492 REAL adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
06493 REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
06494 REAL det;
06495 REAL permanent, errbound;
06496
06497 m->orient3dcount++;
06498
06499 adx = pa[0] - pd[0];
06500 bdx = pb[0] - pd[0];
06501 cdx = pc[0] - pd[0];
06502 ady = pa[1] - pd[1];
06503 bdy = pb[1] - pd[1];
06504 cdy = pc[1] - pd[1];
06505 adheight = aheight - dheight;
06506 bdheight = bheight - dheight;
06507 cdheight = cheight - dheight;
06508
06509 bdxcdy = bdx * cdy;
06510 cdxbdy = cdx * bdy;
06511
06512 cdxady = cdx * ady;
06513 adxcdy = adx * cdy;
06514
06515 adxbdy = adx * bdy;
06516 bdxady = bdx * ady;
06517
06518 det = adheight * (bdxcdy - cdxbdy)
06519 + bdheight * (cdxady - adxcdy)
06520 + cdheight * (adxbdy - bdxady);
06521
06522 if (b->noexact) {
06523 return det;
06524 }
06525
06526 permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight)
06527 + (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight)
06528 + (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
06529 errbound = o3derrboundA * permanent;
06530 if ((det > errbound) || (-det > errbound)) {
06531 return det;
06532 }
06533
06534 return orient3dadapt(pa, pb, pc, pd, aheight, bheight, cheight, dheight,
06535 permanent);
06536 }
06537
06538
06539
06540
06541
06542
06543
06544
06545
06546
06547
06548
06549
06550
06551
06552
06553
06554
06555
06556 #ifdef ANSI_DECLARATORS
06557 REAL nonregular(struct mesh *m, struct behavior *b,
06558 vertex pa, vertex pb, vertex pc, vertex pd)
06559 #else
06560 REAL nonregular(m, b, pa, pb, pc, pd)
06561 struct mesh *m;
06562 struct behavior *b;
06563 vertex pa;
06564 vertex pb;
06565 vertex pc;
06566 vertex pd;
06567 #endif
06568
06569 {
06570 if (b->weighted == 0) {
06571 return incircle(m, b, pa, pb, pc, pd);
06572 } else if (b->weighted == 1) {
06573 return orient3d(m, b, pa, pb, pc, pd,
06574 pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
06575 pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
06576 pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
06577 pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
06578 } else {
06579 return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
06580 }
06581 }
06582
06583
06584
06585
06586
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597 #ifdef ANSI_DECLARATORS
06598 void findcircumcenter(struct mesh *m, struct behavior *b,
06599 vertex torg, vertex tdest, vertex tapex,
06600 vertex circumcenter, REAL *xi, REAL *eta, int offcenter)
06601 #else
06602 void findcircumcenter(m, b, torg, tdest, tapex, circumcenter, xi, eta,
06603 offcenter)
06604 struct mesh *m;
06605 struct behavior *b;
06606 vertex torg;
06607 vertex tdest;
06608 vertex tapex;
06609 vertex circumcenter;
06610 REAL *xi;
06611 REAL *eta;
06612 int offcenter;
06613 #endif
06614
06615 {
06616 REAL xdo, ydo, xao, yao;
06617 REAL dodist, aodist, dadist;
06618 REAL denominator;
06619 REAL dx, dy, dxoff, dyoff;
06620
06621 m->circumcentercount++;
06622
06623
06624 xdo = tdest[0] - torg[0];
06625 ydo = tdest[1] - torg[1];
06626 xao = tapex[0] - torg[0];
06627 yao = tapex[1] - torg[1];
06628 dodist = xdo * xdo + ydo * ydo;
06629 aodist = xao * xao + yao * yao;
06630 dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
06631 (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
06632 if (b->noexact) {
06633 denominator = 0.5 / (xdo * yao - xao * ydo);
06634 } else {
06635
06636
06637
06638 denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
06639
06640 m->counterclockcount--;
06641 }
06642 dx = (yao * dodist - ydo * aodist) * denominator;
06643 dy = (xdo * aodist - xao * dodist) * denominator;
06644
06645
06646
06647
06648
06649
06650 if ((dodist < aodist) && (dodist < dadist)) {
06651 if (offcenter && (b->offconstant > 0.0)) {
06652
06653 dxoff = 0.5 * xdo - b->offconstant * ydo;
06654 dyoff = 0.5 * ydo + b->offconstant * xdo;
06655
06656
06657 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06658 dx = dxoff;
06659 dy = dyoff;
06660 }
06661 }
06662 } else if (aodist < dadist) {
06663 if (offcenter && (b->offconstant > 0.0)) {
06664 dxoff = 0.5 * xao + b->offconstant * yao;
06665 dyoff = 0.5 * yao - b->offconstant * xao;
06666
06667
06668 if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy) {
06669 dx = dxoff;
06670 dy = dyoff;
06671 }
06672 }
06673 } else {
06674 if (offcenter && (b->offconstant > 0.0)) {
06675 dxoff = 0.5 * (tapex[0] - tdest[0]) -
06676 b->offconstant * (tapex[1] - tdest[1]);
06677 dyoff = 0.5 * (tapex[1] - tdest[1]) +
06678 b->offconstant * (tapex[0] - tdest[0]);
06679
06680
06681 if (dxoff * dxoff + dyoff * dyoff <
06682 (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo)) {
06683 dx = xdo + dxoff;
06684 dy = ydo + dyoff;
06685 }
06686 }
06687 }
06688
06689 circumcenter[0] = torg[0] + dx;
06690 circumcenter[1] = torg[1] + dy;
06691
06692
06693
06694
06695
06696
06697 *xi = (yao * dx - xao * dy) * (2.0 * denominator);
06698 *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
06699 }
06700
06703
06704
06705
06706
06707
06708
06709
06710
06711 #ifdef ANSI_DECLARATORS
06712 void triangleinit(struct mesh *m)
06713 #else
06714 void triangleinit(m)
06715 struct mesh *m;
06716 #endif
06717
06718 {
06719 poolzero(&m->vertices);
06720 poolzero(&m->triangles);
06721 poolzero(&m->subsegs);
06722 poolzero(&m->viri);
06723 poolzero(&m->badsubsegs);
06724 poolzero(&m->badtriangles);
06725 poolzero(&m->flipstackers);
06726 poolzero(&m->splaynodes);
06727
06728 m->recenttri.tri = (triangle *) NULL;
06729 m->undeads = 0;
06730 m->samples = 1;
06731 m->checksegments = 0;
06732 m->checkquality = 0;
06733 m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
06734 m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
06735 randomseed = 1;
06736
06737 exactinit();
06738 }
06739
06740
06741
06742
06743
06744
06745
06746
06747
06748
06749
06750 #ifdef ANSI_DECLARATORS
06751 unsigned long randomnation(unsigned int choices)
06752 #else
06753 unsigned long randomnation(choices)
06754 unsigned int choices;
06755 #endif
06756
06757 {
06758 randomseed = (randomseed * 1366l + 150889l) % 714025l;
06759 return randomseed / (714025l / choices + 1);
06760 }
06761
06762
06766
06767
06768
06769
06770
06771
06772 #ifndef REDUCED
06773
06774 #ifdef ANSI_DECLARATORS
06775 void checkmesh(struct mesh *m, struct behavior *b)
06776 #else
06777 void checkmesh(m, b)
06778 struct mesh *m;
06779 struct behavior *b;
06780 #endif
06781
06782 {
06783 struct otri triangleloop;
06784 struct otri oppotri, oppooppotri;
06785 vertex triorg, tridest, triapex;
06786 vertex oppoorg, oppodest;
06787 int horrors;
06788 int saveexact;
06789 triangle ptr;
06790
06791
06792 saveexact = b->noexact;
06793 b->noexact = 0;
06794 if (!b->quiet) {
06795 printf(" Checking consistency of mesh...\n");
06796 }
06797 horrors = 0;
06798
06799 traversalinit(&m->triangles);
06800 triangleloop.tri = triangletraverse(m);
06801 while (triangleloop.tri != (triangle *) NULL) {
06802
06803 for (triangleloop.orient = 0; triangleloop.orient < 3;
06804 triangleloop.orient++) {
06805 org(triangleloop, triorg);
06806 dest(triangleloop, tridest);
06807 if (triangleloop.orient == 0) {
06808
06809 apex(triangleloop, triapex);
06810 if (counterclockwise(m, b, triorg, tridest, triapex) <= 0.0) {
06811 printf(" !! !! Inverted ");
06812 printtriangle(m, b, &triangleloop);
06813 horrors++;
06814 }
06815 }
06816
06817 sym(triangleloop, oppotri);
06818 if (oppotri.tri != m->dummytri) {
06819
06820 sym(oppotri, oppooppotri);
06821 if ((triangleloop.tri != oppooppotri.tri)
06822 || (triangleloop.orient != oppooppotri.orient)) {
06823 printf(" !! !! Asymmetric triangle-triangle bond:\n");
06824 if (triangleloop.tri == oppooppotri.tri) {
06825 printf(" (Right triangle, wrong orientation)\n");
06826 }
06827 printf(" First ");
06828 printtriangle(m, b, &triangleloop);
06829 printf(" Second (nonreciprocating) ");
06830 printtriangle(m, b, &oppotri);
06831 horrors++;
06832 }
06833
06834
06835 org(oppotri, oppoorg);
06836 dest(oppotri, oppodest);
06837 if ((triorg != oppodest) || (tridest != oppoorg)) {
06838 printf(" !! !! Mismatched edge coordinates between two triangles:\n"
06839 );
06840 printf(" First mismatched ");
06841 printtriangle(m, b, &triangleloop);
06842 printf(" Second mismatched ");
06843 printtriangle(m, b, &oppotri);
06844 horrors++;
06845 }
06846 }
06847 }
06848 triangleloop.tri = triangletraverse(m);
06849 }
06850 if (horrors == 0) {
06851 if (!b->quiet) {
06852 printf(" In my studied opinion, the mesh appears to be consistent.\n");
06853 }
06854 } else if (horrors == 1) {
06855 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
06856 } else {
06857 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
06858 }
06859
06860 b->noexact = saveexact;
06861 }
06862
06863 #endif
06864
06865
06866
06867
06868
06869
06870
06871 #ifndef REDUCED
06872
06873 #ifdef ANSI_DECLARATORS
06874 void checkdelaunay(struct mesh *m, struct behavior *b)
06875 #else
06876 void checkdelaunay(m, b)
06877 struct mesh *m;
06878 struct behavior *b;
06879 #endif
06880
06881 {
06882 struct otri triangleloop;
06883 struct otri oppotri;
06884 struct osub opposubseg;
06885 vertex triorg, tridest, triapex;
06886 vertex oppoapex;
06887 int shouldbedelaunay;
06888 int horrors;
06889 int saveexact;
06890 triangle ptr;
06891 subseg sptr;
06892
06893
06894 saveexact = b->noexact;
06895 b->noexact = 0;
06896 if (!b->quiet) {
06897 printf(" Checking Delaunay property of mesh...\n");
06898 }
06899 horrors = 0;
06900
06901 traversalinit(&m->triangles);
06902 triangleloop.tri = triangletraverse(m);
06903 while (triangleloop.tri != (triangle *) NULL) {
06904
06905 for (triangleloop.orient = 0; triangleloop.orient < 3;
06906 triangleloop.orient++) {
06907 org(triangleloop, triorg);
06908 dest(triangleloop, tridest);
06909 apex(triangleloop, triapex);
06910 sym(triangleloop, oppotri);
06911 apex(oppotri, oppoapex);
06912
06913
06914
06915 shouldbedelaunay = (oppotri.tri != m->dummytri) &&
06916 !deadtri(oppotri.tri) && (triangleloop.tri < oppotri.tri) &&
06917 (triorg != m->infvertex1) && (triorg != m->infvertex2) &&
06918 (triorg != m->infvertex3) &&
06919 (tridest != m->infvertex1) && (tridest != m->infvertex2) &&
06920 (tridest != m->infvertex3) &&
06921 (triapex != m->infvertex1) && (triapex != m->infvertex2) &&
06922 (triapex != m->infvertex3) &&
06923 (oppoapex != m->infvertex1) && (oppoapex != m->infvertex2) &&
06924 (oppoapex != m->infvertex3);
06925 if (m->checksegments && shouldbedelaunay) {
06926
06927
06928 tspivot(triangleloop, opposubseg);
06929 if (opposubseg.ss != m->dummysub){
06930 shouldbedelaunay = 0;
06931 }
06932 }
06933 if (shouldbedelaunay) {
06934 if (nonregular(m, b, triorg, tridest, triapex, oppoapex) > 0.0) {
06935 if (!b->weighted) {
06936 printf(" !! !! Non-Delaunay pair of triangles:\n");
06937 printf(" First non-Delaunay ");
06938 printtriangle(m, b, &triangleloop);
06939 printf(" Second non-Delaunay ");
06940 } else {
06941 printf(" !! !! Non-regular pair of triangles:\n");
06942 printf(" First non-regular ");
06943 printtriangle(m, b, &triangleloop);
06944 printf(" Second non-regular ");
06945 }
06946 printtriangle(m, b, &oppotri);
06947 horrors++;
06948 }
06949 }
06950 }
06951 triangleloop.tri = triangletraverse(m);
06952 }
06953 if (horrors == 0) {
06954 if (!b->quiet) {
06955 printf(
06956 " By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
06957 }
06958 } else if (horrors == 1) {
06959 printf(
06960 " !! !! !! !! Precisely one terrifying transgression identified.\n");
06961 } else {
06962 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
06963 }
06964
06965 b->noexact = saveexact;
06966 }
06967
06968 #endif
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978
06979
06980
06981 #ifndef CDT_ONLY
06982
06983 #ifdef ANSI_DECLARATORS
06984 void enqueuebadtriang(struct mesh *m, struct behavior *b,
06985 struct badtriang *badtri)
06986 #else
06987 void enqueuebadtriang(m, b, badtri)
06988 struct mesh *m;
06989 struct behavior *b;
06990 struct badtriang *badtri;
06991 #endif
06992
06993 {
06994 REAL length, multiplier;
06995 int exponent, expincrement;
06996 int queuenumber;
06997 int posexponent;
06998 int i;
06999
07000 if (b->verbose > 2) {
07001 printf(" Queueing bad triangle:\n");
07002 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07003 badtri->triangorg[0], badtri->triangorg[1],
07004 badtri->triangdest[0], badtri->triangdest[1],
07005 badtri->triangapex[0], badtri->triangapex[1]);
07006 }
07007
07008
07009
07010 if (badtri->key >= 1.0) {
07011 length = badtri->key;
07012 posexponent = 1;
07013 } else {
07014
07015
07016 length = 1.0 / badtri->key;
07017 posexponent = 0;
07018 }
07019
07020
07021 exponent = 0;
07022 while (length > 2.0) {
07023
07024 expincrement = 1;
07025 multiplier = 0.5;
07026 while (length * multiplier * multiplier > 1.0) {
07027 expincrement *= 2;
07028 multiplier *= multiplier;
07029 }
07030
07031 exponent += expincrement;
07032 length *= multiplier;
07033 }
07034
07035 exponent = 2 * exponent + (length > SQUAREROOTTWO);
07036
07037
07038
07039 if (posexponent) {
07040 queuenumber = 2047 - exponent;
07041 } else {
07042 queuenumber = 2048 + exponent;
07043 }
07044
07045
07046 if (m->queuefront[queuenumber] == (struct badtriang *) NULL) {
07047
07048
07049 if (queuenumber > m->firstnonemptyq) {
07050
07051 m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
07052 m->firstnonemptyq = queuenumber;
07053 } else {
07054
07055
07056 i = queuenumber + 1;
07057 while (m->queuefront[i] == (struct badtriang *) NULL) {
07058 i++;
07059 }
07060
07061 m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
07062 m->nextnonemptyq[i] = queuenumber;
07063 }
07064
07065 m->queuefront[queuenumber] = badtri;
07066 } else {
07067
07068 m->queuetail[queuenumber]->nexttriang = badtri;
07069 }
07070
07071 m->queuetail[queuenumber] = badtri;
07072
07073 badtri->nexttriang = (struct badtriang *) NULL;
07074 }
07075
07076 #endif
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087 #ifndef CDT_ONLY
07088
07089 #ifdef ANSI_DECLARATORS
07090 void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri,
07091 REAL minedge, vertex enqapex, vertex enqorg, vertex enqdest)
07092 #else
07093 void enqueuebadtri(m, b, enqtri, minedge, enqapex, enqorg, enqdest)
07094 struct mesh *m;
07095 struct behavior *b;
07096 struct otri *enqtri;
07097 REAL minedge;
07098 vertex enqapex;
07099 vertex enqorg;
07100 vertex enqdest;
07101 #endif
07102
07103 {
07104 struct badtriang *newbad;
07105
07106
07107 newbad = (struct badtriang *) poolalloc(&m->badtriangles);
07108 newbad->poortri = encode(*enqtri);
07109 newbad->key = minedge;
07110 newbad->triangapex = enqapex;
07111 newbad->triangorg = enqorg;
07112 newbad->triangdest = enqdest;
07113 enqueuebadtriang(m, b, newbad);
07114 }
07115
07116 #endif
07117
07118
07119
07120
07121
07122
07123
07124 #ifndef CDT_ONLY
07125
07126 #ifdef ANSI_DECLARATORS
07127 struct badtriang *dequeuebadtriang(struct mesh *m)
07128 #else
07129 struct badtriang *dequeuebadtriang(m)
07130 struct mesh *m;
07131 #endif
07132
07133 {
07134 struct badtriang *result;
07135
07136
07137 if (m->firstnonemptyq < 0) {
07138 return (struct badtriang *) NULL;
07139 }
07140
07141 result = m->queuefront[m->firstnonemptyq];
07142
07143 m->queuefront[m->firstnonemptyq] = result->nexttriang;
07144
07145
07146 if (result == m->queuetail[m->firstnonemptyq]) {
07147 m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
07148 }
07149 return result;
07150 }
07151
07152 #endif
07153
07154
07155
07156
07157
07158
07159
07160
07161
07162
07163
07164
07165
07166
07167
07168
07169
07170
07171
07172
07173
07174
07175
07176
07177 #ifndef CDT_ONLY
07178
07179 #ifdef ANSI_DECLARATORS
07180 int checkseg4encroach(struct mesh *m, struct behavior *b,
07181 struct osub *testsubseg)
07182 #else
07183 int checkseg4encroach(m, b, testsubseg)
07184 struct mesh *m;
07185 struct behavior *b;
07186 struct osub *testsubseg;
07187 #endif
07188
07189 {
07190 struct otri neighbortri;
07191 struct osub testsym;
07192 struct badsubseg *encroachedseg;
07193 REAL dotproduct;
07194 int encroached;
07195 int sides;
07196 vertex eorg, edest, eapex;
07197 triangle ptr;
07198
07199 encroached = 0;
07200 sides = 0;
07201
07202 sorg(*testsubseg, eorg);
07203 sdest(*testsubseg, edest);
07204
07205 stpivot(*testsubseg, neighbortri);
07206
07207 if (neighbortri.tri != m->dummytri) {
07208 sides++;
07209
07210 apex(neighbortri, eapex);
07211
07212
07213
07214
07215
07216 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07217 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07218 if (dotproduct < 0.0) {
07219 if (b->conformdel ||
07220 (dotproduct * dotproduct >=
07221 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07222 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07223 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07224 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07225 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07226 encroached = 1;
07227 }
07228 }
07229 }
07230
07231 ssym(*testsubseg, testsym);
07232 stpivot(testsym, neighbortri);
07233
07234 if (neighbortri.tri != m->dummytri) {
07235 sides++;
07236
07237 apex(neighbortri, eapex);
07238
07239
07240 dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
07241 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
07242 if (dotproduct < 0.0) {
07243 if (b->conformdel ||
07244 (dotproduct * dotproduct >=
07245 (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
07246 ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
07247 (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
07248 ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
07249 (edest[1] - eapex[1]) * (edest[1] - eapex[1])))) {
07250 encroached += 2;
07251 }
07252 }
07253 }
07254
07255 if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2)))) {
07256 if (b->verbose > 2) {
07257 printf(
07258 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
07259 eorg[0], eorg[1], edest[0], edest[1]);
07260 }
07261
07262
07263 encroachedseg = (struct badsubseg *) poolalloc(&m->badsubsegs);
07264 if (encroached == 1) {
07265 encroachedseg->encsubseg = sencode(*testsubseg);
07266 encroachedseg->subsegorg = eorg;
07267 encroachedseg->subsegdest = edest;
07268 } else {
07269 encroachedseg->encsubseg = sencode(testsym);
07270 encroachedseg->subsegorg = edest;
07271 encroachedseg->subsegdest = eorg;
07272 }
07273 }
07274
07275 return encroached;
07276 }
07277
07278 #endif
07279
07280
07281
07282
07283
07284
07285
07286
07287
07288
07289
07290 #ifndef CDT_ONLY
07291
07292 #ifdef ANSI_DECLARATORS
07293 void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
07294 #else
07295 void testtriangle(m, b, testtri)
07296 struct mesh *m;
07297 struct behavior *b;
07298 struct otri *testtri;
07299 #endif
07300
07301 {
07302 struct otri tri1, tri2;
07303 struct osub testsub;
07304 vertex torg, tdest, tapex;
07305 vertex base1, base2;
07306 vertex org1, dest1, org2, dest2;
07307 vertex joinvertex;
07308 REAL dxod, dyod, dxda, dyda, dxao, dyao;
07309 REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
07310 REAL apexlen, orglen, destlen, minedge;
07311 REAL angle;
07312 REAL area;
07313 REAL dist1, dist2;
07314 subseg sptr;
07315 triangle ptr;
07316
07317 org(*testtri, torg);
07318 dest(*testtri, tdest);
07319 apex(*testtri, tapex);
07320 dxod = torg[0] - tdest[0];
07321 dyod = torg[1] - tdest[1];
07322 dxda = tdest[0] - tapex[0];
07323 dyda = tdest[1] - tapex[1];
07324 dxao = tapex[0] - torg[0];
07325 dyao = tapex[1] - torg[1];
07326 dxod2 = dxod * dxod;
07327 dyod2 = dyod * dyod;
07328 dxda2 = dxda * dxda;
07329 dyda2 = dyda * dyda;
07330 dxao2 = dxao * dxao;
07331 dyao2 = dyao * dyao;
07332
07333 apexlen = dxod2 + dyod2;
07334 orglen = dxda2 + dyda2;
07335 destlen = dxao2 + dyao2;
07336
07337 if ((apexlen < orglen) && (apexlen < destlen)) {
07338
07339 minedge = apexlen;
07340
07341 angle = dxda * dxao + dyda * dyao;
07342 angle = angle * angle / (orglen * destlen);
07343 base1 = torg;
07344 base2 = tdest;
07345 otricopy(*testtri, tri1);
07346 } else if (orglen < destlen) {
07347
07348 minedge = orglen;
07349
07350 angle = dxod * dxao + dyod * dyao;
07351 angle = angle * angle / (apexlen * destlen);
07352 base1 = tdest;
07353 base2 = tapex;
07354 lnext(*testtri, tri1);
07355 } else {
07356
07357 minedge = destlen;
07358
07359 angle = dxod * dxda + dyod * dyda;
07360 angle = angle * angle / (apexlen * orglen);
07361 base1 = tapex;
07362 base2 = torg;
07363 lprev(*testtri, tri1);
07364 }
07365
07366 if (b->vararea || b->fixedarea || b->usertest) {
07367
07368 area = 0.5 * (dxod * dyda - dyod * dxda);
07369 if (b->fixedarea && (area > b->maxarea)) {
07370
07371 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07372 return;
07373 }
07374
07375
07376 if ((b->vararea) && (area > areabound(*testtri)) &&
07377 (areabound(*testtri) > 0.0)) {
07378
07379 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07380 return;
07381 }
07382
07383 if (b->usertest) {
07384
07385 if (triunsuitable(torg, tdest, tapex, area)) {
07386 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07387 return;
07388 }
07389 }
07390 }
07391
07392
07393 if (angle > b->goodangle) {
07394
07395
07396
07397
07398
07399
07400
07401
07402
07403 if ((vertextype(base1) == SEGMENTVERTEX) &&
07404 (vertextype(base2) == SEGMENTVERTEX)) {
07405
07406
07407 tspivot(tri1, testsub);
07408 if (testsub.ss == m->dummysub) {
07409
07410 otricopy(tri1, tri2);
07411 do {
07412 oprevself(tri1);
07413 tspivot(tri1, testsub);
07414 } while (testsub.ss == m->dummysub);
07415
07416 segorg(testsub, org1);
07417 segdest(testsub, dest1);
07418
07419 do {
07420 dnextself(tri2);
07421 tspivot(tri2, testsub);
07422 } while (testsub.ss == m->dummysub);
07423
07424 segorg(testsub, org2);
07425 segdest(testsub, dest2);
07426
07427 joinvertex = (vertex) NULL;
07428 if ((dest1[0] == org2[0]) && (dest1[1] == org2[1])) {
07429 joinvertex = dest1;
07430 } else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1])) {
07431 joinvertex = org1;
07432 }
07433 if (joinvertex != (vertex) NULL) {
07434
07435
07436 dist1 = ((base1[0] - joinvertex[0]) * (base1[0] - joinvertex[0]) +
07437 (base1[1] - joinvertex[1]) * (base1[1] - joinvertex[1]));
07438 dist2 = ((base2[0] - joinvertex[0]) * (base2[0] - joinvertex[0]) +
07439 (base2[1] - joinvertex[1]) * (base2[1] - joinvertex[1]));
07440
07441 if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2)) {
07442
07443 return;
07444 }
07445 }
07446 }
07447 }
07448
07449
07450 enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
07451 }
07452 }
07453
07454 #endif
07455
07458
07459
07460
07464
07465
07466
07467
07468
07469
07470
07471
07472
07473
07474
07475
07476
07477
07478 #ifdef ANSI_DECLARATORS
07479 void makevertexmap(struct mesh *m, struct behavior *b)
07480 #else
07481 void makevertexmap(m, b)
07482 struct mesh *m;
07483 struct behavior *b;
07484 #endif
07485
07486 {
07487 struct otri triangleloop;
07488 vertex triorg;
07489
07490 if (b->verbose) {
07491 printf(" Constructing mapping from vertices to triangles.\n");
07492 }
07493 traversalinit(&m->triangles);
07494 triangleloop.tri = triangletraverse(m);
07495 while (triangleloop.tri != (triangle *) NULL) {
07496
07497 for (triangleloop.orient = 0; triangleloop.orient < 3;
07498 triangleloop.orient++) {
07499 org(triangleloop, triorg);
07500 setvertex2tri(triorg, encode(triangleloop));
07501 }
07502 triangleloop.tri = triangletraverse(m);
07503 }
07504 }
07505
07506
07507
07508
07509
07510
07511
07512
07513
07514
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532
07533
07534
07535
07536
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570
07571
07572
07573 #ifdef ANSI_DECLARATORS
07574 enum locateresult preciselocate(struct mesh *m, struct behavior *b,
07575 vertex searchpoint, struct otri *searchtri,
07576 int stopatsubsegment)
07577 #else
07578 enum locateresult preciselocate(m, b, searchpoint, searchtri, stopatsubsegment)
07579 struct mesh *m;
07580 struct behavior *b;
07581 vertex searchpoint;
07582 struct otri *searchtri;
07583 int stopatsubsegment;
07584 #endif
07585
07586 {
07587 struct otri backtracktri;
07588 struct osub checkedge;
07589 vertex forg, fdest, fapex;
07590 REAL orgorient, destorient;
07591 int moveleft;
07592 triangle ptr;
07593 subseg sptr;
07594
07595 if (b->verbose > 2) {
07596 printf(" Searching for point (%.12g, %.12g).\n",
07597 searchpoint[0], searchpoint[1]);
07598 }
07599
07600 org(*searchtri, forg);
07601 dest(*searchtri, fdest);
07602 apex(*searchtri, fapex);
07603 while (1) {
07604 if (b->verbose > 2) {
07605 printf(" At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
07606 forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
07607 }
07608
07609 if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
07610 lprevself(*searchtri);
07611 return ONVERTEX;
07612 }
07613
07614
07615 destorient = counterclockwise(m, b, forg, fapex, searchpoint);
07616
07617
07618 orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
07619 if (destorient > 0.0) {
07620 if (orgorient > 0.0) {
07621
07622
07623
07624
07625
07626 moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
07627 (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
07628 } else {
07629 moveleft = 1;
07630 }
07631 } else {
07632 if (orgorient > 0.0) {
07633 moveleft = 0;
07634 } else {
07635
07636
07637 if (destorient == 0.0) {
07638 lprevself(*searchtri);
07639 return ONEDGE;
07640 }
07641 if (orgorient == 0.0) {
07642 lnextself(*searchtri);
07643 return ONEDGE;
07644 }
07645 return INTRIANGLE;
07646 }
07647 }
07648
07649
07650
07651
07652 if (moveleft) {
07653 lprev(*searchtri, backtracktri);
07654 fdest = fapex;
07655 } else {
07656 lnext(*searchtri, backtracktri);
07657 forg = fapex;
07658 }
07659 sym(backtracktri, *searchtri);
07660
07661 if (m->checksegments && stopatsubsegment) {
07662
07663 tspivot(backtracktri, checkedge);
07664 if (checkedge.ss != m->dummysub) {
07665
07666 otricopy(backtracktri, *searchtri);
07667 return OUTSIDE;
07668 }
07669 }
07670
07671 if (searchtri->tri == m->dummytri) {
07672
07673 otricopy(backtracktri, *searchtri);
07674 return OUTSIDE;
07675 }
07676
07677 apex(*searchtri, fapex);
07678 }
07679 }
07680
07681
07682
07683
07684
07685
07686
07687
07688
07689
07690
07691
07692
07693
07694
07695
07696
07697
07698
07699
07700
07701
07702
07703
07704
07705
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716
07717 #ifdef ANSI_DECLARATORS
07718 enum locateresult locate(struct mesh *m, struct behavior *b,
07719 vertex searchpoint, struct otri *searchtri)
07720 #else
07721 enum locateresult locate(m, b, searchpoint, searchtri)
07722 struct mesh *m;
07723 struct behavior *b;
07724 vertex searchpoint;
07725 struct otri *searchtri;
07726 #endif
07727
07728 {
07729 VOID **sampleblock;
07730 char *firsttri;
07731 struct otri sampletri;
07732 vertex torg, tdest;
07733 unsigned long alignptr;
07734 REAL searchdist, dist;
07735 REAL ahead;
07736 long samplesperblock, totalsamplesleft, samplesleft;
07737 long population, totalpopulation;
07738 triangle ptr;
07739
07740 if (b->verbose > 2) {
07741 printf(" Randomly sampling for a triangle near point (%.12g, %.12g).\n",
07742 searchpoint[0], searchpoint[1]);
07743 }
07744
07745
07746 org(*searchtri, torg);
07747 searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07748 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07749 if (b->verbose > 2) {
07750 printf(" Boundary triangle has origin (%.12g, %.12g).\n",
07751 torg[0], torg[1]);
07752 }
07753
07754
07755
07756 if (m->recenttri.tri != (triangle *) NULL) {
07757 if (!deadtri(m->recenttri.tri)) {
07758 org(m->recenttri, torg);
07759 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07760 otricopy(m->recenttri, *searchtri);
07761 return ONVERTEX;
07762 }
07763 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07764 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07765 if (dist < searchdist) {
07766 otricopy(m->recenttri, *searchtri);
07767 searchdist = dist;
07768 if (b->verbose > 2) {
07769 printf(" Choosing recent triangle with origin (%.12g, %.12g).\n",
07770 torg[0], torg[1]);
07771 }
07772 }
07773 }
07774 }
07775
07776
07777
07778
07779
07780 while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
07781 m->triangles.items) {
07782 m->samples++;
07783 }
07784
07785
07786
07787
07788
07789 samplesperblock = (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
07790
07791
07792 samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
07793 m->triangles.maxitems + 1;
07794 totalsamplesleft = m->samples;
07795 population = m->triangles.itemsfirstblock;
07796 totalpopulation = m->triangles.maxitems;
07797 sampleblock = m->triangles.firstblock;
07798 sampletri.orient = 0;
07799 while (totalsamplesleft > 0) {
07800
07801 if (population > totalpopulation) {
07802 population = totalpopulation;
07803 }
07804
07805 alignptr = (unsigned long) (sampleblock + 1);
07806 firsttri = (char *) (alignptr +
07807 (unsigned long) m->triangles.alignbytes -
07808 (alignptr %
07809 (unsigned long) m->triangles.alignbytes));
07810
07811
07812 do {
07813 sampletri.tri = (triangle *) (firsttri +
07814 (randomnation((unsigned int) population) *
07815 m->triangles.itembytes));
07816 if (!deadtri(sampletri.tri)) {
07817 org(sampletri, torg);
07818 dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
07819 (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
07820 if (dist < searchdist) {
07821 otricopy(sampletri, *searchtri);
07822 searchdist = dist;
07823 if (b->verbose > 2) {
07824 printf(" Choosing triangle with origin (%.12g, %.12g).\n",
07825 torg[0], torg[1]);
07826 }
07827 }
07828 }
07829
07830 samplesleft--;
07831 totalsamplesleft--;
07832 } while ((samplesleft > 0) && (totalsamplesleft > 0));
07833
07834 if (totalsamplesleft > 0) {
07835 sampleblock = (VOID **) *sampleblock;
07836 samplesleft = samplesperblock;
07837 totalpopulation -= population;
07838 population = TRIPERBLOCK;
07839 }
07840 }
07841
07842
07843 org(*searchtri, torg);
07844 dest(*searchtri, tdest);
07845
07846 if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
07847 return ONVERTEX;
07848 }
07849 if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
07850 lnextself(*searchtri);
07851 return ONVERTEX;
07852 }
07853
07854 ahead = counterclockwise(m, b, torg, tdest, searchpoint);
07855 if (ahead < 0.0) {
07856
07857
07858 symself(*searchtri);
07859 } else if (ahead == 0.0) {
07860
07861 if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
07862 ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
07863 return ONEDGE;
07864 }
07865 }
07866 return preciselocate(m, b, searchpoint, searchtri, 0);
07867 }
07868
07871
07872
07873
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887
07888 #ifdef ANSI_DECLARATORS
07889 void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri,
07890 int subsegmark)
07891 #else
07892 void insertsubseg(m, b, tri, subsegmark)
07893 struct mesh *m;
07894 struct behavior *b;
07895 struct otri *tri;
07896 int subsegmark;
07897 #endif
07898
07899 {
07900 struct otri oppotri;
07901 struct osub newsubseg;
07902 vertex triorg, tridest;
07903 triangle ptr;
07904 subseg sptr;
07905
07906 org(*tri, triorg);
07907 dest(*tri, tridest);
07908
07909 if (vertexmark(triorg) == 0) {
07910 setvertexmark(triorg, subsegmark);
07911 }
07912 if (vertexmark(tridest) == 0) {
07913 setvertexmark(tridest, subsegmark);
07914 }
07915
07916 tspivot(*tri, newsubseg);
07917 if (newsubseg.ss == m->dummysub) {
07918
07919 makesubseg(m, &newsubseg);
07920 setsorg(newsubseg, tridest);
07921 setsdest(newsubseg, triorg);
07922 setsegorg(newsubseg, tridest);
07923 setsegdest(newsubseg, triorg);
07924
07925
07926
07927
07928 tsbond(*tri, newsubseg);
07929 sym(*tri, oppotri);
07930 ssymself(newsubseg);
07931 tsbond(oppotri, newsubseg);
07932 setmark(newsubseg, subsegmark);
07933 if (b->verbose > 2) {
07934 printf(" Inserting new ");
07935 printsubseg(m, b, &newsubseg);
07936 }
07937 } else {
07938 if (mark(newsubseg) == 0) {
07939 setmark(newsubseg, subsegmark);
07940 }
07941 }
07942 }
07943
07944
07945
07946
07947
07948
07949
07950
07951
07952
07953
07954
07955
07956
07957
07958
07959
07960
07961
07962
07963
07964
07965
07966
07967
07968
07969
07970
07971
07972
07973
07974
07975
07976
07977
07978
07979
07980
07981
07982
07983
07984
07985
07986
07987
07988
07989
07990
07991
07992 #ifdef ANSI_DECLARATORS
07993 void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
07994 #else
07995 void flip(m, b, flipedge)
07996 struct mesh *m;
07997 struct behavior *b;
07998 struct otri *flipedge;
07999 #endif
08000
08001 {
08002 struct otri botleft, botright;
08003 struct otri topleft, topright;
08004 struct otri top;
08005 struct otri botlcasing, botrcasing;
08006 struct otri toplcasing, toprcasing;
08007 struct osub botlsubseg, botrsubseg;
08008 struct osub toplsubseg, toprsubseg;
08009 vertex leftvertex, rightvertex, botvertex;
08010 vertex farvertex;
08011 triangle ptr;
08012 subseg sptr;
08013
08014
08015 org(*flipedge, rightvertex);
08016 dest(*flipedge, leftvertex);
08017 apex(*flipedge, botvertex);
08018 sym(*flipedge, top);
08019 #ifdef SELF_CHECK
08020 if (top.tri == m->dummytri) {
08021 printf("Internal error in flip(): Attempt to flip on boundary.\n");
08022 lnextself(*flipedge);
08023 return;
08024 }
08025 if (m->checksegments) {
08026 tspivot(*flipedge, toplsubseg);
08027 if (toplsubseg.ss != m->dummysub) {
08028 printf("Internal error in flip(): Attempt to flip a segment.\n");
08029 lnextself(*flipedge);
08030 return;
08031 }
08032 }
08033 #endif
08034 apex(top, farvertex);
08035
08036
08037 lprev(top, topleft);
08038 sym(topleft, toplcasing);
08039 lnext(top, topright);
08040 sym(topright, toprcasing);
08041 lnext(*flipedge, botleft);
08042 sym(botleft, botlcasing);
08043 lprev(*flipedge, botright);
08044 sym(botright, botrcasing);
08045
08046 bond(topleft, botlcasing);
08047 bond(botleft, botrcasing);
08048 bond(botright, toprcasing);
08049 bond(topright, toplcasing);
08050
08051 if (m->checksegments) {
08052
08053 tspivot(topleft, toplsubseg);
08054 tspivot(botleft, botlsubseg);
08055 tspivot(botright, botrsubseg);
08056 tspivot(topright, toprsubseg);
08057 if (toplsubseg.ss == m->dummysub) {
08058 tsdissolve(topright);
08059 } else {
08060 tsbond(topright, toplsubseg);
08061 }
08062 if (botlsubseg.ss == m->dummysub) {
08063 tsdissolve(topleft);
08064 } else {
08065 tsbond(topleft, botlsubseg);
08066 }
08067 if (botrsubseg.ss == m->dummysub) {
08068 tsdissolve(botleft);
08069 } else {
08070 tsbond(botleft, botrsubseg);
08071 }
08072 if (toprsubseg.ss == m->dummysub) {
08073 tsdissolve(botright);
08074 } else {
08075 tsbond(botright, toprsubseg);
08076 }
08077 }
08078
08079
08080 setorg(*flipedge, farvertex);
08081 setdest(*flipedge, botvertex);
08082 setapex(*flipedge, rightvertex);
08083 setorg(top, botvertex);
08084 setdest(top, farvertex);
08085 setapex(top, leftvertex);
08086 if (b->verbose > 2) {
08087 printf(" Edge flip results in left ");
08088 printtriangle(m, b, &top);
08089 printf(" and right ");
08090 printtriangle(m, b, flipedge);
08091 }
08092 }
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102
08103
08104
08105
08106
08107
08108
08109
08110
08111
08112
08113
08114
08115
08116
08117
08118
08119
08120
08121
08122
08123
08124
08125
08126
08127 #ifdef ANSI_DECLARATORS
08128 void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
08129 #else
08130 void unflip(m, b, flipedge)
08131 struct mesh *m;
08132 struct behavior *b;
08133 struct otri *flipedge;
08134 #endif
08135
08136 {
08137 struct otri botleft, botright;
08138 struct otri topleft, topright;
08139 struct otri top;
08140 struct otri botlcasing, botrcasing;
08141 struct otri toplcasing, toprcasing;
08142 struct osub botlsubseg, botrsubseg;
08143 struct osub toplsubseg, toprsubseg;
08144 vertex leftvertex, rightvertex, botvertex;
08145 vertex farvertex;
08146 triangle ptr;
08147 subseg sptr;
08148
08149
08150 org(*flipedge, rightvertex);
08151 dest(*flipedge, leftvertex);
08152 apex(*flipedge, botvertex);
08153 sym(*flipedge, top);
08154 #ifdef SELF_CHECK
08155 if (top.tri == m->dummytri) {
08156 printf("Internal error in unflip(): Attempt to flip on boundary.\n");
08157 lnextself(*flipedge);
08158 return;
08159 }
08160 if (m->checksegments) {
08161 tspivot(*flipedge, toplsubseg);
08162 if (toplsubseg.ss != m->dummysub) {
08163 printf("Internal error in unflip(): Attempt to flip a subsegment.\n");
08164 lnextself(*flipedge);
08165 return;
08166 }
08167 }
08168 #endif
08169 apex(top, farvertex);
08170
08171
08172 lprev(top, topleft);
08173 sym(topleft, toplcasing);
08174 lnext(top, topright);
08175 sym(topright, toprcasing);
08176 lnext(*flipedge, botleft);
08177 sym(botleft, botlcasing);
08178 lprev(*flipedge, botright);
08179 sym(botright, botrcasing);
08180
08181 bond(topleft, toprcasing);
08182 bond(botleft, toplcasing);
08183 bond(botright, botlcasing);
08184 bond(topright, botrcasing);
08185
08186 if (m->checksegments) {
08187
08188 tspivot(topleft, toplsubseg);
08189 tspivot(botleft, botlsubseg);
08190 tspivot(botright, botrsubseg);
08191 tspivot(topright, toprsubseg);
08192 if (toplsubseg.ss == m->dummysub) {
08193 tsdissolve(botleft);
08194 } else {
08195 tsbond(botleft, toplsubseg);
08196 }
08197 if (botlsubseg.ss == m->dummysub) {
08198 tsdissolve(botright);
08199 } else {
08200 tsbond(botright, botlsubseg);
08201 }
08202 if (botrsubseg.ss == m->dummysub) {
08203 tsdissolve(topright);
08204 } else {
08205 tsbond(topright, botrsubseg);
08206 }
08207 if (toprsubseg.ss == m->dummysub) {
08208 tsdissolve(topleft);
08209 } else {
08210 tsbond(topleft, toprsubseg);
08211 }
08212 }
08213
08214
08215 setorg(*flipedge, botvertex);
08216 setdest(*flipedge, farvertex);
08217 setapex(*flipedge, leftvertex);
08218 setorg(top, farvertex);
08219 setdest(top, botvertex);
08220 setapex(top, rightvertex);
08221 if (b->verbose > 2) {
08222 printf(" Edge unflip results in left ");
08223 printtriangle(m, b, flipedge);
08224 printf(" and right ");
08225 printtriangle(m, b, &top);
08226 }
08227 }
08228
08229
08230
08231
08232
08233
08234
08235
08236
08237
08238
08239
08240
08241
08242
08243
08244
08245
08246
08247
08248
08249
08250
08251
08252
08253
08254
08255
08256
08257
08258
08259
08260
08261
08262
08263
08264
08265
08266
08267
08268
08269
08270
08271
08272
08273
08274
08275
08276 #ifdef ANSI_DECLARATORS
08277 enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b,
08278 vertex newvertex, struct otri *searchtri,
08279 struct osub *splitseg,
08280 int segmentflaws, int triflaws)
08281 #else
08282 enum insertvertexresult insertvertex(m, b, newvertex, searchtri, splitseg,
08283 segmentflaws, triflaws)
08284 struct mesh *m;
08285 struct behavior *b;
08286 vertex newvertex;
08287 struct otri *searchtri;
08288 struct osub *splitseg;
08289 int segmentflaws;
08290 int triflaws;
08291 #endif
08292
08293 {
08294 struct otri horiz;
08295 struct otri top;
08296 struct otri botleft, botright;
08297 struct otri topleft, topright;
08298 struct otri newbotleft, newbotright;
08299 struct otri newtopright;
08300 struct otri botlcasing, botrcasing;
08301 struct otri toplcasing={NULL, 0}, toprcasing={NULL, 0};
08302 struct otri testtri;
08303 struct osub botlsubseg, botrsubseg;
08304 struct osub toplsubseg, toprsubseg;
08305 struct osub brokensubseg;
08306 struct osub checksubseg;
08307 struct osub rightsubseg;
08308 struct osub newsubseg;
08309 struct badsubseg *encroached;
08310 struct flipstacker *newflip;
08311 vertex first;
08312 vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
08313 vertex segmentorg, segmentdest;
08314 REAL attrib;
08315 REAL area;
08316 enum insertvertexresult success;
08317 enum locateresult intersect;
08318 int doflip;
08319 int mirrorflag;
08320 int enq;
08321 int i;
08322 triangle ptr;
08323 subseg sptr;
08324
08325 if (b->verbose > 1) {
08326 printf(" Inserting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
08327 }
08328
08329 if (splitseg == (struct osub *) NULL) {
08330
08331
08332 if (searchtri->tri == m->dummytri) {
08333
08334 horiz.tri = m->dummytri;
08335 horiz.orient = 0;
08336 symself(horiz);
08337
08338 intersect = locate(m, b, newvertex, &horiz);
08339 } else {
08340
08341 otricopy(*searchtri, horiz);
08342 intersect = preciselocate(m, b, newvertex, &horiz, 1);
08343 }
08344 } else {
08345
08346
08347 otricopy(*searchtri, horiz);
08348 intersect = ONEDGE;
08349 }
08350
08351 if (intersect == ONVERTEX) {
08352
08353
08354 otricopy(horiz, *searchtri);
08355 otricopy(horiz, m->recenttri);
08356 return DUPLICATEVERTEX;
08357 }
08358 if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
08359
08360 if (m->checksegments && (splitseg == (struct osub *) NULL)) {
08361
08362 tspivot(horiz, brokensubseg);
08363 if (brokensubseg.ss != m->dummysub) {
08364
08365 if (segmentflaws) {
08366 enq = b->nobisect != 2;
08367 if (enq && (b->nobisect == 1)) {
08368
08369
08370 sym(horiz, testtri);
08371 enq = testtri.tri != m->dummytri;
08372 }
08373 if (enq) {
08374
08375 encroached = (struct badsubseg *) poolalloc(&m->badsubsegs);
08376 encroached->encsubseg = sencode(brokensubseg);
08377 sorg(brokensubseg, encroached->subsegorg);
08378 sdest(brokensubseg, encroached->subsegdest);
08379 if (b->verbose > 2) {
08380 printf(
08381 " Queueing encroached subsegment (%.12g, %.12g) (%.12g, %.12g).\n",
08382 encroached->subsegorg[0], encroached->subsegorg[1],
08383 encroached->subsegdest[0], encroached->subsegdest[1]);
08384 }
08385 }
08386 }
08387
08388
08389 otricopy(horiz, *searchtri);
08390 otricopy(horiz, m->recenttri);
08391 return VIOLATINGVERTEX;
08392 }
08393 }
08394
08395
08396
08397 lprev(horiz, botright);
08398 sym(botright, botrcasing);
08399 sym(horiz, topright);
08400
08401 mirrorflag = topright.tri != m->dummytri;
08402 if (mirrorflag) {
08403 lnextself(topright);
08404 sym(topright, toprcasing);
08405 maketriangle(m, b, &newtopright);
08406 } else {
08407
08408 m->hullsize++;
08409 }
08410 maketriangle(m, b, &newbotright);
08411
08412
08413 org(horiz, rightvertex);
08414 dest(horiz, leftvertex);
08415 apex(horiz, botvertex);
08416 setorg(newbotright, botvertex);
08417 setdest(newbotright, rightvertex);
08418 setapex(newbotright, newvertex);
08419 setorg(horiz, newvertex);
08420 for (i = 0; i < m->eextras; i++) {
08421
08422 setelemattribute(newbotright, i, elemattribute(botright, i));
08423 }
08424 if (b->vararea) {
08425
08426 setareabound(newbotright, areabound(botright));
08427 }
08428 if (mirrorflag) {
08429 dest(topright, topvertex);
08430 setorg(newtopright, rightvertex);
08431 setdest(newtopright, topvertex);
08432 setapex(newtopright, newvertex);
08433 setorg(topright, newvertex);
08434 for (i = 0; i < m->eextras; i++) {
08435
08436 setelemattribute(newtopright, i, elemattribute(topright, i));
08437 }
08438 if (b->vararea) {
08439
08440 setareabound(newtopright, areabound(topright));
08441 }
08442 }
08443
08444
08445
08446 if (m->checksegments) {
08447 tspivot(botright, botrsubseg);
08448 if (botrsubseg.ss != m->dummysub) {
08449 tsdissolve(botright);
08450 tsbond(newbotright, botrsubseg);
08451 }
08452 if (mirrorflag) {
08453 tspivot(topright, toprsubseg);
08454 if (toprsubseg.ss != m->dummysub) {
08455 tsdissolve(topright);
08456 tsbond(newtopright, toprsubseg);
08457 }
08458 }
08459 }
08460
08461
08462 bond(newbotright, botrcasing);
08463 lprevself(newbotright);
08464 bond(newbotright, botright);
08465 lprevself(newbotright);
08466 if (mirrorflag) {
08467 bond(newtopright, toprcasing);
08468 lnextself(newtopright);
08469 bond(newtopright, topright);
08470 lnextself(newtopright);
08471 bond(newtopright, newbotright);
08472 }
08473
08474 if (splitseg != (struct osub *) NULL) {
08475
08476 setsdest(*splitseg, newvertex);
08477 segorg(*splitseg, segmentorg);
08478 segdest(*splitseg, segmentdest);
08479 ssymself(*splitseg);
08480 spivot(*splitseg, rightsubseg);
08481 insertsubseg(m, b, &newbotright, mark(*splitseg));
08482 tspivot(newbotright, newsubseg);
08483 setsegorg(newsubseg, segmentorg);
08484 setsegdest(newsubseg, segmentdest);
08485 sbond(*splitseg, newsubseg);
08486 ssymself(newsubseg);
08487 sbond(newsubseg, rightsubseg);
08488 ssymself(*splitseg);
08489
08490
08491 if (vertexmark(newvertex) == 0) {
08492 setvertexmark(newvertex, mark(*splitseg));
08493 }
08494 }
08495
08496 if (m->checkquality) {
08497 poolrestart(&m->flipstackers);
08498 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08499 m->lastflip->flippedtri = encode(horiz);
08500 m->lastflip->prevflip = (struct flipstacker *) &insertvertex;
08501 }
08502
08503 #ifdef SELF_CHECK
08504 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08505 printf("Internal error in insertvertex():\n");
08506 printf(
08507 " Clockwise triangle prior to edge vertex insertion (bottom).\n");
08508 }
08509 if (mirrorflag) {
08510 if (counterclockwise(m, b, leftvertex, rightvertex, topvertex) < 0.0) {
08511 printf("Internal error in insertvertex():\n");
08512 printf(" Clockwise triangle prior to edge vertex insertion (top).\n");
08513 }
08514 if (counterclockwise(m, b, rightvertex, topvertex, newvertex) < 0.0) {
08515 printf("Internal error in insertvertex():\n");
08516 printf(
08517 " Clockwise triangle after edge vertex insertion (top right).\n");
08518 }
08519 if (counterclockwise(m, b, topvertex, leftvertex, newvertex) < 0.0) {
08520 printf("Internal error in insertvertex():\n");
08521 printf(
08522 " Clockwise triangle after edge vertex insertion (top left).\n");
08523 }
08524 }
08525 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08526 printf("Internal error in insertvertex():\n");
08527 printf(
08528 " Clockwise triangle after edge vertex insertion (bottom left).\n");
08529 }
08530 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08531 printf("Internal error in insertvertex():\n");
08532 printf(
08533 " Clockwise triangle after edge vertex insertion (bottom right).\n");
08534 }
08535 #endif
08536 if (b->verbose > 2) {
08537 printf(" Updating bottom left ");
08538 printtriangle(m, b, &botright);
08539 if (mirrorflag) {
08540 printf(" Updating top left ");
08541 printtriangle(m, b, &topright);
08542 printf(" Creating top right ");
08543 printtriangle(m, b, &newtopright);
08544 }
08545 printf(" Creating bottom right ");
08546 printtriangle(m, b, &newbotright);
08547 }
08548
08549
08550
08551 lnextself(horiz);
08552 } else {
08553
08554 lnext(horiz, botleft);
08555 lprev(horiz, botright);
08556 sym(botleft, botlcasing);
08557 sym(botright, botrcasing);
08558 maketriangle(m, b, &newbotleft);
08559 maketriangle(m, b, &newbotright);
08560
08561
08562 org(horiz, rightvertex);
08563 dest(horiz, leftvertex);
08564 apex(horiz, botvertex);
08565 setorg(newbotleft, leftvertex);
08566 setdest(newbotleft, botvertex);
08567 setapex(newbotleft, newvertex);
08568 setorg(newbotright, botvertex);
08569 setdest(newbotright, rightvertex);
08570 setapex(newbotright, newvertex);
08571 setapex(horiz, newvertex);
08572 for (i = 0; i < m->eextras; i++) {
08573
08574 attrib = elemattribute(horiz, i);
08575 setelemattribute(newbotleft, i, attrib);
08576 setelemattribute(newbotright, i, attrib);
08577 }
08578 if (b->vararea) {
08579
08580 area = areabound(horiz);
08581 setareabound(newbotleft, area);
08582 setareabound(newbotright, area);
08583 }
08584
08585
08586
08587 if (m->checksegments) {
08588 tspivot(botleft, botlsubseg);
08589 if (botlsubseg.ss != m->dummysub) {
08590 tsdissolve(botleft);
08591 tsbond(newbotleft, botlsubseg);
08592 }
08593 tspivot(botright, botrsubseg);
08594 if (botrsubseg.ss != m->dummysub) {
08595 tsdissolve(botright);
08596 tsbond(newbotright, botrsubseg);
08597 }
08598 }
08599
08600
08601 bond(newbotleft, botlcasing);
08602 bond(newbotright, botrcasing);
08603 lnextself(newbotleft);
08604 lprevself(newbotright);
08605 bond(newbotleft, newbotright);
08606 lnextself(newbotleft);
08607 bond(botleft, newbotleft);
08608 lprevself(newbotright);
08609 bond(botright, newbotright);
08610
08611 if (m->checkquality) {
08612 poolrestart(&m->flipstackers);
08613 m->lastflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08614 m->lastflip->flippedtri = encode(horiz);
08615 m->lastflip->prevflip = (struct flipstacker *) NULL;
08616 }
08617
08618 #ifdef SELF_CHECK
08619 if (counterclockwise(m, b, rightvertex, leftvertex, botvertex) < 0.0) {
08620 printf("Internal error in insertvertex():\n");
08621 printf(" Clockwise triangle prior to vertex insertion.\n");
08622 }
08623 if (counterclockwise(m, b, rightvertex, leftvertex, newvertex) < 0.0) {
08624 printf("Internal error in insertvertex():\n");
08625 printf(" Clockwise triangle after vertex insertion (top).\n");
08626 }
08627 if (counterclockwise(m, b, leftvertex, botvertex, newvertex) < 0.0) {
08628 printf("Internal error in insertvertex():\n");
08629 printf(" Clockwise triangle after vertex insertion (left).\n");
08630 }
08631 if (counterclockwise(m, b, botvertex, rightvertex, newvertex) < 0.0) {
08632 printf("Internal error in insertvertex():\n");
08633 printf(" Clockwise triangle after vertex insertion (right).\n");
08634 }
08635 #endif
08636 if (b->verbose > 2) {
08637 printf(" Updating top ");
08638 printtriangle(m, b, &horiz);
08639 printf(" Creating left ");
08640 printtriangle(m, b, &newbotleft);
08641 printf(" Creating right ");
08642 printtriangle(m, b, &newbotright);
08643 }
08644 }
08645
08646
08647
08648 success = SUCCESSFULVERTEX;
08649
08650
08651
08652
08653 org(horiz, first);
08654 rightvertex = first;
08655 dest(horiz, leftvertex);
08656
08657 while (1) {
08658
08659 doflip = 1;
08660
08661 if (m->checksegments) {
08662
08663 tspivot(horiz, checksubseg);
08664 if (checksubseg.ss != m->dummysub) {
08665
08666 doflip = 0;
08667 #ifndef CDT_ONLY
08668 if (segmentflaws) {
08669
08670 if (checkseg4encroach(m, b, &checksubseg)) {
08671 success = ENCROACHINGVERTEX;
08672 }
08673 }
08674 #endif
08675 }
08676 }
08677
08678 if (doflip) {
08679
08680 sym(horiz, top);
08681 if (top.tri == m->dummytri) {
08682
08683 doflip = 0;
08684 } else {
08685
08686 apex(top, farvertex);
08687
08688
08689
08690
08691
08692 if ((leftvertex == m->infvertex1) || (leftvertex == m->infvertex2) ||
08693 (leftvertex == m->infvertex3)) {
08694
08695
08696
08697
08698 doflip = counterclockwise(m, b, newvertex, rightvertex, farvertex)
08699 > 0.0;
08700 } else if ((rightvertex == m->infvertex1) ||
08701 (rightvertex == m->infvertex2) ||
08702 (rightvertex == m->infvertex3)) {
08703
08704
08705
08706
08707 doflip = counterclockwise(m, b, farvertex, leftvertex, newvertex)
08708 > 0.0;
08709 } else if ((farvertex == m->infvertex1) ||
08710 (farvertex == m->infvertex2) ||
08711 (farvertex == m->infvertex3)) {
08712
08713
08714 doflip = 0;
08715 } else {
08716
08717 doflip = incircle(m, b, leftvertex, newvertex, rightvertex,
08718 farvertex) > 0.0;
08719 }
08720 if (doflip) {
08721
08722
08723
08724 lprev(top, topleft);
08725 sym(topleft, toplcasing);
08726 lnext(top, topright);
08727 sym(topright, toprcasing);
08728 lnext(horiz, botleft);
08729 sym(botleft, botlcasing);
08730 lprev(horiz, botright);
08731 sym(botright, botrcasing);
08732
08733 bond(topleft, botlcasing);
08734 bond(botleft, botrcasing);
08735 bond(botright, toprcasing);
08736 bond(topright, toplcasing);
08737 if (m->checksegments) {
08738
08739 tspivot(topleft, toplsubseg);
08740 tspivot(botleft, botlsubseg);
08741 tspivot(botright, botrsubseg);
08742 tspivot(topright, toprsubseg);
08743 if (toplsubseg.ss == m->dummysub) {
08744 tsdissolve(topright);
08745 } else {
08746 tsbond(topright, toplsubseg);
08747 }
08748 if (botlsubseg.ss == m->dummysub) {
08749 tsdissolve(topleft);
08750 } else {
08751 tsbond(topleft, botlsubseg);
08752 }
08753 if (botrsubseg.ss == m->dummysub) {
08754 tsdissolve(botleft);
08755 } else {
08756 tsbond(botleft, botrsubseg);
08757 }
08758 if (toprsubseg.ss == m->dummysub) {
08759 tsdissolve(botright);
08760 } else {
08761 tsbond(botright, toprsubseg);
08762 }
08763 }
08764
08765 setorg(horiz, farvertex);
08766 setdest(horiz, newvertex);
08767 setapex(horiz, rightvertex);
08768 setorg(top, newvertex);
08769 setdest(top, farvertex);
08770 setapex(top, leftvertex);
08771 for (i = 0; i < m->eextras; i++) {
08772
08773 attrib = 0.5 * (elemattribute(top, i) + elemattribute(horiz, i));
08774 setelemattribute(top, i, attrib);
08775 setelemattribute(horiz, i, attrib);
08776 }
08777 if (b->vararea) {
08778 if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
08779 area = -1.0;
08780 } else {
08781
08782
08783
08784 area = 0.5 * (areabound(top) + areabound(horiz));
08785 }
08786 setareabound(top, area);
08787 setareabound(horiz, area);
08788 }
08789
08790 if (m->checkquality) {
08791 newflip = (struct flipstacker *) poolalloc(&m->flipstackers);
08792 newflip->flippedtri = encode(horiz);
08793 newflip->prevflip = m->lastflip;
08794 m->lastflip = newflip;
08795 }
08796
08797 #ifdef SELF_CHECK
08798 if (newvertex != (vertex) NULL) {
08799 if (counterclockwise(m, b, leftvertex, newvertex, rightvertex) <
08800 0.0) {
08801 printf("Internal error in insertvertex():\n");
08802 printf(" Clockwise triangle prior to edge flip (bottom).\n");
08803 }
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814 if (counterclockwise(m, b, farvertex, leftvertex, newvertex) <
08815 0.0) {
08816 printf("Internal error in insertvertex():\n");
08817 printf(" Clockwise triangle after edge flip (left).\n");
08818 }
08819 if (counterclockwise(m, b, newvertex, rightvertex, farvertex) <
08820 0.0) {
08821 printf("Internal error in insertvertex():\n");
08822 printf(" Clockwise triangle after edge flip (right).\n");
08823 }
08824 }
08825 #endif
08826 if (b->verbose > 2) {
08827 printf(" Edge flip results in left ");
08828 lnextself(topleft);
08829 printtriangle(m, b, &topleft);
08830 printf(" and right ");
08831 printtriangle(m, b, &horiz);
08832 }
08833
08834
08835
08836 lprevself(horiz);
08837 leftvertex = farvertex;
08838 }
08839 }
08840 }
08841 if (!doflip) {
08842
08843 #ifndef CDT_ONLY
08844 if (triflaws) {
08845
08846 testtriangle(m, b, &horiz);
08847 }
08848 #endif
08849
08850 lnextself(horiz);
08851 sym(horiz, testtri);
08852
08853
08854
08855 if ((leftvertex == first) || (testtri.tri == m->dummytri)) {
08856
08857 lnext(horiz, *searchtri);
08858 lnext(horiz, m->recenttri);
08859 return success;
08860 }
08861
08862 lnext(testtri, horiz);
08863 rightvertex = leftvertex;
08864 dest(horiz, leftvertex);
08865 }
08866 }
08867 }
08868
08869
08870
08871
08872
08873
08874
08875
08876
08877
08878
08879
08880
08881
08882
08883
08884
08885
08886
08887
08888
08889
08890
08891
08892
08893
08894
08895
08896
08897
08898
08899
08900
08901
08902
08903
08904
08905
08906
08907
08908
08909
08910
08911
08912
08913
08914
08915
08916
08917
08918
08919
08920
08921
08922
08923
08924
08925
08926
08927
08928
08929
08930
08931
08932
08933 #ifdef ANSI_DECLARATORS
08934 void triangulatepolygon(struct mesh *m, struct behavior *b,
08935 struct otri *firstedge, struct otri *lastedge,
08936 int edgecount, int doflip, int triflaws)
08937 #else
08938 void triangulatepolygon(m, b, firstedge, lastedge, edgecount, doflip, triflaws)
08939 struct mesh *m;
08940 struct behavior *b;
08941 struct otri *firstedge;
08942 struct otri *lastedge;
08943 int edgecount;
08944 int doflip;
08945 int triflaws;
08946 #endif
08947
08948 {
08949 struct otri testtri;
08950 struct otri besttri;
08951 struct otri tempedge;
08952 vertex leftbasevertex, rightbasevertex;
08953 vertex testvertex;
08954 vertex bestvertex;
08955 int bestnumber;
08956 int i;
08957 triangle ptr;
08958
08959
08960 apex(*lastedge, leftbasevertex);
08961 dest(*firstedge, rightbasevertex);
08962 if (b->verbose > 2) {
08963 printf(" Triangulating interior polygon at edge\n");
08964 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", leftbasevertex[0],
08965 leftbasevertex[1], rightbasevertex[0], rightbasevertex[1]);
08966 }
08967
08968 onext(*firstedge, besttri);
08969 dest(besttri, bestvertex);
08970 otricopy(besttri, testtri);
08971 bestnumber = 1;
08972 for (i = 2; i <= edgecount - 2; i++) {
08973 onextself(testtri);
08974 dest(testtri, testvertex);
08975
08976 if (incircle(m, b, leftbasevertex, rightbasevertex, bestvertex,
08977 testvertex) > 0.0) {
08978 otricopy(testtri, besttri);
08979 bestvertex = testvertex;
08980 bestnumber = i;
08981 }
08982 }
08983 if (b->verbose > 2) {
08984 printf(" Connecting edge to (%.12g, %.12g)\n", bestvertex[0],
08985 bestvertex[1]);
08986 }
08987 if (bestnumber > 1) {
08988
08989 oprev(besttri, tempedge);
08990 triangulatepolygon(m, b, firstedge, &tempedge, bestnumber + 1, 1,
08991 triflaws);
08992 }
08993 if (bestnumber < edgecount - 2) {
08994
08995 sym(besttri, tempedge);
08996 triangulatepolygon(m, b, &besttri, lastedge, edgecount - bestnumber, 1,
08997 triflaws);
08998
08999 sym(tempedge, besttri);
09000 }
09001 if (doflip) {
09002
09003 flip(m, b, &besttri);
09004 #ifndef CDT_ONLY
09005 if (triflaws) {
09006
09007 sym(besttri, testtri);
09008 testtriangle(m, b, &testtri);
09009 }
09010 #endif
09011 }
09012
09013 otricopy(besttri, *lastedge);
09014 }
09015
09016
09017
09018
09019
09020
09021
09022
09023
09024
09025
09026
09027
09028
09029
09030 #ifndef CDT_ONLY
09031
09032 #ifdef ANSI_DECLARATORS
09033 void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
09034 #else
09035 void deletevertex(m, b, deltri)
09036 struct mesh *m;
09037 struct behavior *b;
09038 struct otri *deltri;
09039 #endif
09040
09041 {
09042 struct otri countingtri;
09043 struct otri firstedge, lastedge;
09044 struct otri deltriright;
09045 struct otri lefttri, righttri;
09046 struct otri leftcasing, rightcasing;
09047 struct osub leftsubseg, rightsubseg;
09048 vertex delvertex;
09049 vertex neworg;
09050 int edgecount;
09051 triangle ptr;
09052 subseg sptr;
09053
09054 org(*deltri, delvertex);
09055 if (b->verbose > 1) {
09056 printf(" Deleting (%.12g, %.12g).\n", delvertex[0], delvertex[1]);
09057 }
09058 vertexdealloc(m, delvertex);
09059
09060
09061 onext(*deltri, countingtri);
09062 edgecount = 1;
09063 while (!otriequal(*deltri, countingtri)) {
09064 #ifdef SELF_CHECK
09065 if (countingtri.tri == m->dummytri) {
09066 printf("Internal error in deletevertex():\n");
09067 printf(" Attempt to delete boundary vertex.\n");
09068 internalerror();
09069 }
09070 #endif
09071 edgecount++;
09072 onextself(countingtri);
09073 }
09074
09075 #ifdef SELF_CHECK
09076 if (edgecount < 3) {
09077 printf("Internal error in deletevertex():\n Vertex has degree %d.\n",
09078 edgecount);
09079 internalerror();
09080 }
09081 #endif
09082 if (edgecount > 3) {
09083
09084
09085
09086 onext(*deltri, firstedge);
09087 oprev(*deltri, lastedge);
09088 triangulatepolygon(m, b, &firstedge, &lastedge, edgecount, 0,
09089 !b->nobisect);
09090 }
09091
09092 lprev(*deltri, deltriright);
09093 dnext(*deltri, lefttri);
09094 sym(lefttri, leftcasing);
09095 oprev(deltriright, righttri);
09096 sym(righttri, rightcasing);
09097 bond(*deltri, leftcasing);
09098 bond(deltriright, rightcasing);
09099 tspivot(lefttri, leftsubseg);
09100 if (leftsubseg.ss != m->dummysub) {
09101 tsbond(*deltri, leftsubseg);
09102 }
09103 tspivot(righttri, rightsubseg);
09104 if (rightsubseg.ss != m->dummysub) {
09105 tsbond(deltriright, rightsubseg);
09106 }
09107
09108
09109 org(lefttri, neworg);
09110 setorg(*deltri, neworg);
09111 if (!b->nobisect) {
09112 testtriangle(m, b, deltri);
09113 }
09114
09115
09116 triangledealloc(m, lefttri.tri);
09117 triangledealloc(m, righttri.tri);
09118 }
09119
09120 #endif
09121
09122
09123
09124
09125
09126
09127
09128
09129
09130
09131
09132
09133 #ifndef CDT_ONLY
09134
09135 #ifdef ANSI_DECLARATORS
09136 void undovertex(struct mesh *m, struct behavior *b)
09137 #else
09138 void undovertex(m, b)
09139 struct mesh *m;
09140 struct behavior *b;
09141 #endif
09142
09143 {
09144 struct otri fliptri;
09145 struct otri botleft, botright, topright;
09146 struct otri botlcasing, botrcasing, toprcasing;
09147 struct otri gluetri;
09148 struct osub botlsubseg, botrsubseg, toprsubseg;
09149 vertex botvertex, rightvertex;
09150 triangle ptr;
09151 subseg sptr;
09152
09153
09154
09155 while (m->lastflip != (struct flipstacker *) NULL) {
09156
09157 decode(m->lastflip->flippedtri, fliptri);
09158
09159
09160
09161
09162
09163 if (m->lastflip->prevflip == (struct flipstacker *) NULL) {
09164
09165
09166 dprev(fliptri, botleft);
09167 lnextself(botleft);
09168 onext(fliptri, botright);
09169 lprevself(botright);
09170 sym(botleft, botlcasing);
09171 sym(botright, botrcasing);
09172 dest(botleft, botvertex);
09173
09174 setapex(fliptri, botvertex);
09175 lnextself(fliptri);
09176 bond(fliptri, botlcasing);
09177 tspivot(botleft, botlsubseg);
09178 tsbond(fliptri, botlsubseg);
09179 lnextself(fliptri);
09180 bond(fliptri, botrcasing);
09181 tspivot(botright, botrsubseg);
09182 tsbond(fliptri, botrsubseg);
09183
09184
09185 triangledealloc(m, botleft.tri);
09186 triangledealloc(m, botright.tri);
09187 } else if (m->lastflip->prevflip == (struct flipstacker *) &insertvertex) {
09188
09189
09190 lprev(fliptri, gluetri);
09191 sym(gluetri, botright);
09192 lnextself(botright);
09193 sym(botright, botrcasing);
09194 dest(botright, rightvertex);
09195
09196 setorg(fliptri, rightvertex);
09197 bond(gluetri, botrcasing);
09198 tspivot(botright, botrsubseg);
09199 tsbond(gluetri, botrsubseg);
09200
09201
09202 triangledealloc(m, botright.tri);
09203
09204 sym(fliptri, gluetri);
09205 if (gluetri.tri != m->dummytri) {
09206 lnextself(gluetri);
09207 dnext(gluetri, topright);
09208 sym(topright, toprcasing);
09209
09210 setorg(gluetri, rightvertex);
09211 bond(gluetri, toprcasing);
09212 tspivot(topright, toprsubseg);
09213 tsbond(gluetri, toprsubseg);
09214
09215
09216 triangledealloc(m, topright.tri);
09217 }
09218
09219
09220 m->lastflip->prevflip = (struct flipstacker *) NULL;
09221 } else {
09222
09223 unflip(m, b, &fliptri);
09224 }
09225
09226
09227 m->lastflip = m->lastflip->prevflip;
09228 }
09229 }
09230
09231 #endif
09232
09235
09236
09237
09241
09242
09243
09244
09245
09246
09247
09248
09249
09250
09251
09252
09253
09254
09255
09256
09257
09258
09259
09260
09261
09262
09263
09264
09265
09266
09267
09268
09269
09270
09271
09272
09273
09274
09275
09276
09277
09278
09279
09280
09281
09282 #ifdef ANSI_DECLARATORS
09283 void vertexsort(vertex *sortarray, int arraysize)
09284 #else
09285 void vertexsort(sortarray, arraysize)
09286 vertex *sortarray;
09287 int arraysize;
09288 #endif
09289
09290 {
09291 int left, right;
09292 int pivot;
09293 REAL pivotx, pivoty;
09294 vertex temp;
09295
09296 if (arraysize == 2) {
09297
09298 if ((sortarray[0][0] > sortarray[1][0]) ||
09299 ((sortarray[0][0] == sortarray[1][0]) &&
09300 (sortarray[0][1] > sortarray[1][1]))) {
09301 temp = sortarray[1];
09302 sortarray[1] = sortarray[0];
09303 sortarray[0] = temp;
09304 }
09305 return;
09306 }
09307
09308 pivot = (int) randomnation((unsigned int) arraysize);
09309 pivotx = sortarray[pivot][0];
09310 pivoty = sortarray[pivot][1];
09311
09312 left = -1;
09313 right = arraysize;
09314 while (left < right) {
09315
09316 do {
09317 left++;
09318 } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
09319 ((sortarray[left][0] == pivotx) &&
09320 (sortarray[left][1] < pivoty))));
09321
09322 do {
09323 right--;
09324 } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
09325 ((sortarray[right][0] == pivotx) &&
09326 (sortarray[right][1] > pivoty))));
09327 if (left < right) {
09328
09329 temp = sortarray[left];
09330 sortarray[left] = sortarray[right];
09331 sortarray[right] = temp;
09332 }
09333 }
09334 if (left > 1) {
09335
09336 vertexsort(sortarray, left);
09337 }
09338 if (right < arraysize - 2) {
09339
09340 vertexsort(&sortarray[right + 1], arraysize - right - 1);
09341 }
09342 }
09343
09344
09345
09346
09347
09348
09349
09350
09351
09352
09353
09354
09355
09356 #ifdef ANSI_DECLARATORS
09357 void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
09358 #else
09359 void vertexmedian(sortarray, arraysize, median, axis)
09360 vertex *sortarray;
09361 int arraysize;
09362 int median;
09363 int axis;
09364 #endif
09365
09366 {
09367 int left, right;
09368 int pivot;
09369 REAL pivot1, pivot2;
09370 vertex temp;
09371
09372 if (arraysize == 2) {
09373
09374 if ((sortarray[0][axis] > sortarray[1][axis]) ||
09375 ((sortarray[0][axis] == sortarray[1][axis]) &&
09376 (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
09377 temp = sortarray[1];
09378 sortarray[1] = sortarray[0];
09379 sortarray[0] = temp;
09380 }
09381 return;
09382 }
09383
09384 pivot = (int) randomnation((unsigned int) arraysize);
09385 pivot1 = sortarray[pivot][axis];
09386 pivot2 = sortarray[pivot][1 - axis];
09387
09388 left = -1;
09389 right = arraysize;
09390 while (left < right) {
09391
09392 do {
09393 left++;
09394 } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
09395 ((sortarray[left][axis] == pivot1) &&
09396 (sortarray[left][1 - axis] < pivot2))));
09397
09398 do {
09399 right--;
09400 } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
09401 ((sortarray[right][axis] == pivot1) &&
09402 (sortarray[right][1 - axis] > pivot2))));
09403 if (left < right) {
09404
09405 temp = sortarray[left];
09406 sortarray[left] = sortarray[right];
09407 sortarray[right] = temp;
09408 }
09409 }
09410
09411
09412 if (left > median) {
09413
09414 vertexmedian(sortarray, left, median, axis);
09415 }
09416 if (right < median - 1) {
09417
09418 vertexmedian(&sortarray[right + 1], arraysize - right - 1,
09419 median - right - 1, axis);
09420 }
09421 }
09422
09423
09424
09425
09426
09427
09428
09429
09430
09431
09432
09433
09434 #ifdef ANSI_DECLARATORS
09435 void alternateaxes(vertex *sortarray, int arraysize, int axis)
09436 #else
09437 void alternateaxes(sortarray, arraysize, axis)
09438 vertex *sortarray;
09439 int arraysize;
09440 int axis;
09441 #endif
09442
09443 {
09444 int divider;
09445
09446 divider = arraysize >> 1;
09447 if (arraysize <= 3) {
09448
09449
09450 axis = 0;
09451 }
09452
09453 vertexmedian(sortarray, arraysize, divider, axis);
09454
09455 if (arraysize - divider >= 2) {
09456 if (divider >= 2) {
09457 alternateaxes(sortarray, divider, 1 - axis);
09458 }
09459 alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
09460 }
09461 }
09462
09463
09464
09465
09466
09467
09468
09469
09470
09471
09472
09473
09474
09475
09476
09477
09478
09479
09480
09481
09482
09483
09484
09485
09486
09487
09488
09489
09490
09491
09492
09493
09494
09495
09496
09497
09498 #ifdef ANSI_DECLARATORS
09499 void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft,
09500 struct otri *innerleft, struct otri *innerright,
09501 struct otri *farright, int axis)
09502 #else
09503 void mergehulls(m, b, farleft, innerleft, innerright, farright, axis)
09504 struct mesh *m;
09505 struct behavior *b;
09506 struct otri *farleft;
09507 struct otri *innerleft;
09508 struct otri *innerright;
09509 struct otri *farright;
09510 int axis;
09511 #endif
09512
09513 {
09514 struct otri leftcand, rightcand;
09515 struct otri baseedge;
09516 struct otri nextedge;
09517 struct otri sidecasing, topcasing, outercasing;
09518 struct otri checkedge;
09519 vertex innerleftdest;
09520 vertex innerrightorg;
09521 vertex innerleftapex, innerrightapex;
09522 vertex farleftpt, farrightpt;
09523 vertex farleftapex, farrightapex;
09524 vertex lowerleft, lowerright;
09525 vertex upperleft, upperright;
09526 vertex nextapex;
09527 vertex checkvertex;
09528 int changemade;
09529 int badedge;
09530 int leftfinished, rightfinished;
09531 triangle ptr;
09532
09533 dest(*innerleft, innerleftdest);
09534 apex(*innerleft, innerleftapex);
09535 org(*innerright, innerrightorg);
09536 apex(*innerright, innerrightapex);
09537
09538 if (b->dwyer && (axis == 1)) {
09539 org(*farleft, farleftpt);
09540 apex(*farleft, farleftapex);
09541 dest(*farright, farrightpt);
09542 apex(*farright, farrightapex);
09543
09544
09545
09546 while (farleftapex[1] < farleftpt[1]) {
09547 lnextself(*farleft);
09548 symself(*farleft);
09549 farleftpt = farleftapex;
09550 apex(*farleft, farleftapex);
09551 }
09552 sym(*innerleft, checkedge);
09553 apex(checkedge, checkvertex);
09554 while (checkvertex[1] > innerleftdest[1]) {
09555 lnext(checkedge, *innerleft);
09556 innerleftapex = innerleftdest;
09557 innerleftdest = checkvertex;
09558 sym(*innerleft, checkedge);
09559 apex(checkedge, checkvertex);
09560 }
09561 while (innerrightapex[1] < innerrightorg[1]) {
09562 lnextself(*innerright);
09563 symself(*innerright);
09564 innerrightorg = innerrightapex;
09565 apex(*innerright, innerrightapex);
09566 }
09567 sym(*farright, checkedge);
09568 apex(checkedge, checkvertex);
09569 while (checkvertex[1] > farrightpt[1]) {
09570 lnext(checkedge, *farright);
09571 farrightapex = farrightpt;
09572 farrightpt = checkvertex;
09573 sym(*farright, checkedge);
09574 apex(checkedge, checkvertex);
09575 }
09576 }
09577
09578 do {
09579 changemade = 0;
09580
09581 if (counterclockwise(m, b, innerleftdest, innerleftapex, innerrightorg) >
09582 0.0) {
09583 lprevself(*innerleft);
09584 symself(*innerleft);
09585 innerleftdest = innerleftapex;
09586 apex(*innerleft, innerleftapex);
09587 changemade = 1;
09588 }
09589
09590 if (counterclockwise(m, b, innerrightapex, innerrightorg, innerleftdest) >
09591 0.0) {
09592 lnextself(*innerright);
09593 symself(*innerright);
09594 innerrightorg = innerrightapex;
09595 apex(*innerright, innerrightapex);
09596 changemade = 1;
09597 }
09598 } while (changemade);
09599
09600 sym(*innerleft, leftcand);
09601 sym(*innerright, rightcand);
09602
09603 maketriangle(m, b, &baseedge);
09604
09605 bond(baseedge, *innerleft);
09606 lnextself(baseedge);
09607 bond(baseedge, *innerright);
09608 lnextself(baseedge);
09609 setorg(baseedge, innerrightorg);
09610 setdest(baseedge, innerleftdest);
09611
09612 if (b->verbose > 2) {
09613 printf(" Creating base bounding ");
09614 printtriangle(m, b, &baseedge);
09615 }
09616
09617 org(*farleft, farleftpt);
09618 if (innerleftdest == farleftpt) {
09619 lnext(baseedge, *farleft);
09620 }
09621 dest(*farright, farrightpt);
09622 if (innerrightorg == farrightpt) {
09623 lprev(baseedge, *farright);
09624 }
09625
09626 lowerleft = innerleftdest;
09627 lowerright = innerrightorg;
09628
09629 apex(leftcand, upperleft);
09630 apex(rightcand, upperright);
09631
09632 while (1) {
09633
09634
09635
09636
09637 leftfinished = counterclockwise(m, b, upperleft, lowerleft, lowerright) <=
09638 0.0;
09639 rightfinished = counterclockwise(m, b, upperright, lowerleft, lowerright)
09640 <= 0.0;
09641 if (leftfinished && rightfinished) {
09642
09643 maketriangle(m, b, &nextedge);
09644 setorg(nextedge, lowerleft);
09645 setdest(nextedge, lowerright);
09646
09647
09648 bond(nextedge, baseedge);
09649 lnextself(nextedge);
09650 bond(nextedge, rightcand);
09651 lnextself(nextedge);
09652 bond(nextedge, leftcand);
09653 if (b->verbose > 2) {
09654 printf(" Creating top bounding ");
09655 printtriangle(m, b, &nextedge);
09656 }
09657
09658 if (b->dwyer && (axis == 1)) {
09659 org(*farleft, farleftpt);
09660 apex(*farleft, farleftapex);
09661 dest(*farright, farrightpt);
09662 apex(*farright, farrightapex);
09663 sym(*farleft, checkedge);
09664 apex(checkedge, checkvertex);
09665
09666
09667
09668 while (checkvertex[0] < farleftpt[0]) {
09669 lprev(checkedge, *farleft);
09670 farleftapex = farleftpt;
09671 farleftpt = checkvertex;
09672 sym(*farleft, checkedge);
09673 apex(checkedge, checkvertex);
09674 }
09675 while (farrightapex[0] > farrightpt[0]) {
09676 lprevself(*farright);
09677 symself(*farright);
09678 farrightpt = farrightapex;
09679 apex(*farright, farrightapex);
09680 }
09681 }
09682 return;
09683 }
09684
09685 if (!leftfinished) {
09686
09687 lprev(leftcand, nextedge);
09688 symself(nextedge);
09689 apex(nextedge, nextapex);
09690
09691
09692 if (nextapex != (vertex) NULL) {
09693
09694 badedge = incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
09695 0.0;
09696 while (badedge) {
09697
09698
09699 lnextself(nextedge);
09700 sym(nextedge, topcasing);
09701 lnextself(nextedge);
09702 sym(nextedge, sidecasing);
09703 bond(nextedge, topcasing);
09704 bond(leftcand, sidecasing);
09705 lnextself(leftcand);
09706 sym(leftcand, outercasing);
09707 lprevself(nextedge);
09708 bond(nextedge, outercasing);
09709
09710 setorg(leftcand, lowerleft);
09711 setdest(leftcand, NULL);
09712 setapex(leftcand, nextapex);
09713 setorg(nextedge, NULL);
09714 setdest(nextedge, upperleft);
09715 setapex(nextedge, nextapex);
09716
09717 upperleft = nextapex;
09718
09719 otricopy(sidecasing, nextedge);
09720 apex(nextedge, nextapex);
09721 if (nextapex != (vertex) NULL) {
09722
09723 badedge = incircle(m, b, lowerleft, lowerright, upperleft,
09724 nextapex) > 0.0;
09725 } else {
09726
09727 badedge = 0;
09728 }
09729 }
09730 }
09731 }
09732
09733 if (!rightfinished) {
09734
09735 lnext(rightcand, nextedge);
09736 symself(nextedge);
09737 apex(nextedge, nextapex);
09738
09739
09740 if (nextapex != (vertex) NULL) {
09741
09742 badedge = incircle(m, b, lowerleft, lowerright, upperright, nextapex) >
09743 0.0;
09744 while (badedge) {
09745
09746
09747 lprevself(nextedge);
09748 sym(nextedge, topcasing);
09749 lprevself(nextedge);
09750 sym(nextedge, sidecasing);
09751 bond(nextedge, topcasing);
09752 bond(rightcand, sidecasing);
09753 lprevself(rightcand);
09754 sym(rightcand, outercasing);
09755 lnextself(nextedge);
09756 bond(nextedge, outercasing);
09757
09758 setorg(rightcand, NULL);
09759 setdest(rightcand, lowerright);
09760 setapex(rightcand, nextapex);
09761 setorg(nextedge, upperright);
09762 setdest(nextedge, NULL);
09763 setapex(nextedge, nextapex);
09764
09765 upperright = nextapex;
09766
09767 otricopy(sidecasing, nextedge);
09768 apex(nextedge, nextapex);
09769 if (nextapex != (vertex) NULL) {
09770
09771 badedge = incircle(m, b, lowerleft, lowerright, upperright,
09772 nextapex) > 0.0;
09773 } else {
09774
09775 badedge = 0;
09776 }
09777 }
09778 }
09779 }
09780 if (leftfinished || (!rightfinished &&
09781 (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
09782 0.0))) {
09783
09784
09785 bond(baseedge, rightcand);
09786 lprev(rightcand, baseedge);
09787 setdest(baseedge, lowerleft);
09788 lowerright = upperright;
09789 sym(baseedge, rightcand);
09790 apex(rightcand, upperright);
09791 } else {
09792
09793
09794 bond(baseedge, leftcand);
09795 lnext(leftcand, baseedge);
09796 setorg(baseedge, lowerright);
09797 lowerleft = upperleft;
09798 sym(baseedge, leftcand);
09799 apex(leftcand, upperleft);
09800 }
09801 if (b->verbose > 2) {
09802 printf(" Connecting ");
09803 printtriangle(m, b, &baseedge);
09804 }
09805 }
09806 }
09807
09808
09809
09810
09811
09812
09813
09814
09815
09816
09817
09818
09819
09820
09821
09822
09823
09824
09825 #ifdef ANSI_DECLARATORS
09826 void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray,
09827 int vertices, int axis,
09828 struct otri *farleft, struct otri *farright)
09829 #else
09830 void divconqrecurse(m, b, sortarray, vertices, axis, farleft, farright)
09831 struct mesh *m;
09832 struct behavior *b;
09833 vertex *sortarray;
09834 int vertices;
09835 int axis;
09836 struct otri *farleft;
09837 struct otri *farright;
09838 #endif
09839
09840 {
09841 struct otri midtri, tri1, tri2, tri3;
09842 struct otri innerleft, innerright;
09843 REAL area;
09844 int divider;
09845
09846 if (b->verbose > 2) {
09847 printf(" Triangulating %d vertices.\n", vertices);
09848 }
09849 if (vertices == 2) {
09850
09851
09852 maketriangle(m, b, farleft);
09853 setorg(*farleft, sortarray[0]);
09854 setdest(*farleft, sortarray[1]);
09855
09856 maketriangle(m, b, farright);
09857 setorg(*farright, sortarray[1]);
09858 setdest(*farright, sortarray[0]);
09859
09860 bond(*farleft, *farright);
09861 lprevself(*farleft);
09862 lnextself(*farright);
09863 bond(*farleft, *farright);
09864 lprevself(*farleft);
09865 lnextself(*farright);
09866 bond(*farleft, *farright);
09867 if (b->verbose > 2) {
09868 printf(" Creating ");
09869 printtriangle(m, b, farleft);
09870 printf(" Creating ");
09871 printtriangle(m, b, farright);
09872 }
09873
09874 lprev(*farright, *farleft);
09875 return;
09876 } else if (vertices == 3) {
09877
09878
09879
09880 maketriangle(m, b, &midtri);
09881 maketriangle(m, b, &tri1);
09882 maketriangle(m, b, &tri2);
09883 maketriangle(m, b, &tri3);
09884 area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
09885 if (area == 0.0) {
09886
09887 setorg(midtri, sortarray[0]);
09888 setdest(midtri, sortarray[1]);
09889 setorg(tri1, sortarray[1]);
09890 setdest(tri1, sortarray[0]);
09891 setorg(tri2, sortarray[2]);
09892 setdest(tri2, sortarray[1]);
09893 setorg(tri3, sortarray[1]);
09894 setdest(tri3, sortarray[2]);
09895
09896 bond(midtri, tri1);
09897 bond(tri2, tri3);
09898 lnextself(midtri);
09899 lprevself(tri1);
09900 lnextself(tri2);
09901 lprevself(tri3);
09902 bond(midtri, tri3);
09903 bond(tri1, tri2);
09904 lnextself(midtri);
09905 lprevself(tri1);
09906 lnextself(tri2);
09907 lprevself(tri3);
09908 bond(midtri, tri1);
09909 bond(tri2, tri3);
09910
09911 otricopy(tri1, *farleft);
09912
09913 otricopy(tri2, *farright);
09914 } else {
09915
09916
09917 setorg(midtri, sortarray[0]);
09918 setdest(tri1, sortarray[0]);
09919 setorg(tri3, sortarray[0]);
09920
09921 if (area > 0.0) {
09922
09923 setdest(midtri, sortarray[1]);
09924 setorg(tri1, sortarray[1]);
09925 setdest(tri2, sortarray[1]);
09926 setapex(midtri, sortarray[2]);
09927 setorg(tri2, sortarray[2]);
09928 setdest(tri3, sortarray[2]);
09929 } else {
09930
09931 setdest(midtri, sortarray[2]);
09932 setorg(tri1, sortarray[2]);
09933 setdest(tri2, sortarray[2]);
09934 setapex(midtri, sortarray[1]);
09935 setorg(tri2, sortarray[1]);
09936 setdest(tri3, sortarray[1]);
09937 }
09938
09939 bond(midtri, tri1);
09940 lnextself(midtri);
09941 bond(midtri, tri2);
09942 lnextself(midtri);
09943 bond(midtri, tri3);
09944 lprevself(tri1);
09945 lnextself(tri2);
09946 bond(tri1, tri2);
09947 lprevself(tri1);
09948 lprevself(tri3);
09949 bond(tri1, tri3);
09950 lnextself(tri2);
09951 lprevself(tri3);
09952 bond(tri2, tri3);
09953
09954 otricopy(tri1, *farleft);
09955
09956 if (area > 0.0) {
09957 otricopy(tri2, *farright);
09958 } else {
09959 lnext(*farleft, *farright);
09960 }
09961 }
09962 if (b->verbose > 2) {
09963 printf(" Creating ");
09964 printtriangle(m, b, &midtri);
09965 printf(" Creating ");
09966 printtriangle(m, b, &tri1);
09967 printf(" Creating ");
09968 printtriangle(m, b, &tri2);
09969 printf(" Creating ");
09970 printtriangle(m, b, &tri3);
09971 }
09972 return;
09973 } else {
09974
09975 divider = vertices >> 1;
09976
09977 divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
09978 divconqrecurse(m, b, &sortarray[divider], vertices - divider, 1 - axis,
09979 &innerright, farright);
09980 if (b->verbose > 1) {
09981 printf(" Joining triangulations with %d and %d vertices.\n", divider,
09982 vertices - divider);
09983 }
09984
09985 mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
09986 }
09987 }
09988
09989 #ifdef ANSI_DECLARATORS
09990 long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
09991 #else
09992 long removeghosts(m, b, startghost)
09993 struct mesh *m;
09994 struct behavior *b;
09995 struct otri *startghost;
09996 #endif
09997
09998 {
09999 struct otri searchedge;
10000 struct otri dissolveedge;
10001 struct otri deadtriangle;
10002 vertex markorg;
10003 long hullsize;
10004 triangle ptr;
10005
10006 if (b->verbose) {
10007 printf(" Removing ghost triangles.\n");
10008 }
10009
10010 lprev(*startghost, searchedge);
10011 symself(searchedge);
10012 m->dummytri[0] = encode(searchedge);
10013
10014 otricopy(*startghost, dissolveedge);
10015 hullsize = 0;
10016 do {
10017 hullsize++;
10018 lnext(dissolveedge, deadtriangle);
10019 lprevself(dissolveedge);
10020 symself(dissolveedge);
10021
10022
10023 if (!b->poly) {
10024
10025 if (dissolveedge.tri != m->dummytri) {
10026 org(dissolveedge, markorg);
10027 if (vertexmark(markorg) == 0) {
10028 setvertexmark(markorg, 1);
10029 }
10030 }
10031 }
10032
10033 dissolve(dissolveedge);
10034
10035 sym(deadtriangle, dissolveedge);
10036
10037 triangledealloc(m, deadtriangle.tri);
10038 } while (!otriequal(dissolveedge, *startghost));
10039 return hullsize;
10040 }
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052 #ifdef ANSI_DECLARATORS
10053 long divconqdelaunay(struct mesh *m, struct behavior *b)
10054 #else
10055 long divconqdelaunay(m, b)
10056 struct mesh *m;
10057 struct behavior *b;
10058 #endif
10059
10060 {
10061 vertex *sortarray;
10062 struct otri hullleft, hullright;
10063 int divider;
10064 int i, j;
10065
10066 if (b->verbose) {
10067 printf(" Sorting vertices.\n");
10068 }
10069
10070
10071 sortarray = (vertex *) trimalloc(m->invertices * (int) sizeof(vertex));
10072 traversalinit(&m->vertices);
10073 for (i = 0; i < m->invertices; i++) {
10074 sortarray[i] = vertextraverse(m);
10075 }
10076
10077 vertexsort(sortarray, m->invertices);
10078
10079 i = 0;
10080 for (j = 1; j < m->invertices; j++) {
10081 if ((sortarray[i][0] == sortarray[j][0])
10082 && (sortarray[i][1] == sortarray[j][1])) {
10083 if (!b->quiet) {
10084 printf(
10085 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10086 sortarray[j][0], sortarray[j][1]);
10087 }
10088 setvertextype(sortarray[j], UNDEADVERTEX);
10089 m->undeads++;
10090 } else {
10091 i++;
10092 sortarray[i] = sortarray[j];
10093 }
10094 }
10095 i++;
10096 if (b->dwyer) {
10097
10098 divider = i >> 1;
10099 if (i - divider >= 2) {
10100 if (divider >= 2) {
10101 alternateaxes(sortarray, divider, 1);
10102 }
10103 alternateaxes(&sortarray[divider], i - divider, 1);
10104 }
10105 }
10106
10107 if (b->verbose) {
10108 printf(" Forming triangulation.\n");
10109 }
10110
10111
10112 divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
10113 trifree((VOID *) sortarray);
10114
10115 return removeghosts(m, b, &hullleft);
10116 }
10117
10120
10121
10122
10126
10127
10128
10129
10130
10131
10132
10133
10134
10135
10136
10137 #ifndef REDUCED
10138
10139 #ifdef ANSI_DECLARATORS
10140 void boundingbox(struct mesh *m, struct behavior *b)
10141 #else
10142 void boundingbox(m, b)
10143 struct mesh *m;
10144 struct behavior *b;
10145 #endif
10146
10147 {
10148 struct otri inftri;
10149 REAL width;
10150
10151 if (b->verbose) {
10152 printf(" Creating triangular bounding box.\n");
10153 }
10154
10155 width = m->xmax - m->xmin;
10156 if (m->ymax - m->ymin > width) {
10157 width = m->ymax - m->ymin;
10158 }
10159 if (width == 0.0) {
10160 width = 1.0;
10161 }
10162
10163 m->infvertex1 = (vertex) trimalloc(m->vertices.itembytes);
10164 m->infvertex2 = (vertex) trimalloc(m->vertices.itembytes);
10165 m->infvertex3 = (vertex) trimalloc(m->vertices.itembytes);
10166 m->infvertex1[0] = m->xmin - 50.0 * width;
10167 m->infvertex1[1] = m->ymin - 40.0 * width;
10168 m->infvertex2[0] = m->xmax + 50.0 * width;
10169 m->infvertex2[1] = m->ymin - 40.0 * width;
10170 m->infvertex3[0] = 0.5 * (m->xmin + m->xmax);
10171 m->infvertex3[1] = m->ymax + 60.0 * width;
10172
10173
10174 maketriangle(m, b, &inftri);
10175 setorg(inftri, m->infvertex1);
10176 setdest(inftri, m->infvertex2);
10177 setapex(inftri, m->infvertex3);
10178
10179
10180 m->dummytri[0] = (triangle) inftri.tri;
10181 if (b->verbose > 2) {
10182 printf(" Creating ");
10183 printtriangle(m, b, &inftri);
10184 }
10185 }
10186
10187 #endif
10188
10189
10190
10191
10192
10193
10194
10195
10196
10197
10198
10199
10200
10201
10202
10203 #ifndef REDUCED
10204
10205 #ifdef ANSI_DECLARATORS
10206 long removebox(struct mesh *m, struct behavior *b)
10207 #else
10208 long removebox(m, b)
10209 struct mesh *m;
10210 struct behavior *b;
10211 #endif
10212
10213 {
10214 struct otri deadtriangle;
10215 struct otri searchedge;
10216 struct otri checkedge;
10217 struct otri nextedge, finaledge, dissolveedge;
10218 vertex markorg;
10219 long hullsize;
10220 triangle ptr;
10221
10222 if (b->verbose) {
10223 printf(" Removing triangular bounding box.\n");
10224 }
10225
10226 nextedge.tri = m->dummytri;
10227 nextedge.orient = 0;
10228 symself(nextedge);
10229
10230 lprev(nextedge, finaledge);
10231 lnextself(nextedge);
10232 symself(nextedge);
10233
10234
10235 lprev(nextedge, searchedge);
10236 symself(searchedge);
10237
10238
10239 lnext(nextedge, checkedge);
10240 symself(checkedge);
10241 if (checkedge.tri == m->dummytri) {
10242
10243
10244
10245 lprevself(searchedge);
10246 symself(searchedge);
10247 }
10248
10249
10250 m->dummytri[0] = encode(searchedge);
10251 hullsize = -2l;
10252 while (!otriequal(nextedge, finaledge)) {
10253 hullsize++;
10254 lprev(nextedge, dissolveedge);
10255 symself(dissolveedge);
10256
10257
10258 if (!b->poly) {
10259
10260
10261
10262
10263 if (dissolveedge.tri != m->dummytri) {
10264 org(dissolveedge, markorg);
10265 if (vertexmark(markorg) == 0) {
10266 setvertexmark(markorg, 1);
10267 }
10268 }
10269 }
10270
10271 dissolve(dissolveedge);
10272 lnext(nextedge, deadtriangle);
10273 sym(deadtriangle, nextedge);
10274
10275 triangledealloc(m, deadtriangle.tri);
10276
10277 if (nextedge.tri == m->dummytri) {
10278
10279 otricopy(dissolveedge, nextedge);
10280 }
10281 }
10282 triangledealloc(m, finaledge.tri);
10283
10284 trifree((VOID *) m->infvertex1);
10285 trifree((VOID *) m->infvertex2);
10286 trifree((VOID *) m->infvertex3);
10287
10288 return hullsize;
10289 }
10290
10291 #endif
10292
10293
10294
10295
10296
10297
10298
10299
10300
10301
10302 #ifndef REDUCED
10303
10304 #ifdef ANSI_DECLARATORS
10305 long incrementaldelaunay(struct mesh *m, struct behavior *b)
10306 #else
10307 long incrementaldelaunay(m, b)
10308 struct mesh *m;
10309 struct behavior *b;
10310 #endif
10311
10312 {
10313 struct otri starttri;
10314 vertex vertexloop;
10315
10316
10317 boundingbox(m, b);
10318 if (b->verbose) {
10319 printf(" Incrementally inserting vertices.\n");
10320 }
10321 traversalinit(&m->vertices);
10322 vertexloop = vertextraverse(m);
10323 while (vertexloop != (vertex) NULL) {
10324 starttri.tri = m->dummytri;
10325 if (insertvertex(m, b, vertexloop, &starttri, (struct osub *) NULL, 0, 0)
10326 == DUPLICATEVERTEX) {
10327 if (!b->quiet) {
10328 printf(
10329 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10330 vertexloop[0], vertexloop[1]);
10331 }
10332 setvertextype(vertexloop, UNDEADVERTEX);
10333 m->undeads++;
10334 }
10335 vertexloop = vertextraverse(m);
10336 }
10337
10338 return removebox(m, b);
10339 }
10340
10341 #endif
10342
10345
10346
10347
10351 #ifndef REDUCED
10352
10353 #ifdef ANSI_DECLARATORS
10354 void eventheapinsert(struct event **heap, int heapsize, struct event *newevent)
10355 #else
10356 void eventheapinsert(heap, heapsize, newevent)
10357 struct event **heap;
10358 int heapsize;
10359 struct event *newevent;
10360 #endif
10361
10362 {
10363 REAL eventx, eventy;
10364 int eventnum;
10365 int parent;
10366 int notdone;
10367
10368 eventx = newevent->xkey;
10369 eventy = newevent->ykey;
10370 eventnum = heapsize;
10371 notdone = eventnum > 0;
10372 while (notdone) {
10373 parent = (eventnum - 1) >> 1;
10374 if ((heap[parent]->ykey < eventy) ||
10375 ((heap[parent]->ykey == eventy)
10376 && (heap[parent]->xkey <= eventx))) {
10377 notdone = 0;
10378 } else {
10379 heap[eventnum] = heap[parent];
10380 heap[eventnum]->heapposition = eventnum;
10381
10382 eventnum = parent;
10383 notdone = eventnum > 0;
10384 }
10385 }
10386 heap[eventnum] = newevent;
10387 newevent->heapposition = eventnum;
10388 }
10389
10390 #endif
10391
10392 #ifndef REDUCED
10393
10394 #ifdef ANSI_DECLARATORS
10395 void eventheapify(struct event **heap, int heapsize, int eventnum)
10396 #else
10397 void eventheapify(heap, heapsize, eventnum)
10398 struct event **heap;
10399 int heapsize;
10400 int eventnum;
10401 #endif
10402
10403 {
10404 struct event *thisevent;
10405 REAL eventx, eventy;
10406 int leftchild, rightchild;
10407 int smallest;
10408 int notdone;
10409
10410 thisevent = heap[eventnum];
10411 eventx = thisevent->xkey;
10412 eventy = thisevent->ykey;
10413 leftchild = 2 * eventnum + 1;
10414 notdone = leftchild < heapsize;
10415 while (notdone) {
10416 if ((heap[leftchild]->ykey < eventy) ||
10417 ((heap[leftchild]->ykey == eventy)
10418 && (heap[leftchild]->xkey < eventx))) {
10419 smallest = leftchild;
10420 } else {
10421 smallest = eventnum;
10422 }
10423 rightchild = leftchild + 1;
10424 if (rightchild < heapsize) {
10425 if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
10426 ((heap[rightchild]->ykey == heap[smallest]->ykey)
10427 && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
10428 smallest = rightchild;
10429 }
10430 }
10431 if (smallest == eventnum) {
10432 notdone = 0;
10433 } else {
10434 heap[eventnum] = heap[smallest];
10435 heap[eventnum]->heapposition = eventnum;
10436 heap[smallest] = thisevent;
10437 thisevent->heapposition = smallest;
10438
10439 eventnum = smallest;
10440 leftchild = 2 * eventnum + 1;
10441 notdone = leftchild < heapsize;
10442 }
10443 }
10444 }
10445
10446 #endif
10447
10448 #ifndef REDUCED
10449
10450 #ifdef ANSI_DECLARATORS
10451 void eventheapdelete(struct event **heap, int heapsize, int eventnum)
10452 #else
10453 void eventheapdelete(heap, heapsize, eventnum)
10454 struct event **heap;
10455 int heapsize;
10456 int eventnum;
10457 #endif
10458
10459 {
10460 struct event *moveevent;
10461 REAL eventx, eventy;
10462 int parent;
10463 int notdone;
10464
10465 moveevent = heap[heapsize - 1];
10466 if (eventnum > 0) {
10467 eventx = moveevent->xkey;
10468 eventy = moveevent->ykey;
10469 do {
10470 parent = (eventnum - 1) >> 1;
10471 if ((heap[parent]->ykey < eventy) ||
10472 ((heap[parent]->ykey == eventy)
10473 && (heap[parent]->xkey <= eventx))) {
10474 notdone = 0;
10475 } else {
10476 heap[eventnum] = heap[parent];
10477 heap[eventnum]->heapposition = eventnum;
10478
10479 eventnum = parent;
10480 notdone = eventnum > 0;
10481 }
10482 } while (notdone);
10483 }
10484 heap[eventnum] = moveevent;
10485 moveevent->heapposition = eventnum;
10486 eventheapify(heap, heapsize - 1, eventnum);
10487 }
10488
10489 #endif
10490
10491 #ifndef REDUCED
10492
10493 #ifdef ANSI_DECLARATORS
10494 void createeventheap(struct mesh *m, struct event ***eventheap,
10495 struct event **events, struct event **freeevents)
10496 #else
10497 void createeventheap(m, eventheap, events, freeevents)
10498 struct mesh *m;
10499 struct event ***eventheap;
10500 struct event **events;
10501 struct event **freeevents;
10502 #endif
10503
10504 {
10505 vertex thisvertex;
10506 int maxevents;
10507 int i;
10508
10509 maxevents = (3 * m->invertices) / 2;
10510 *eventheap = (struct event **) trimalloc(maxevents *
10511 (int) sizeof(struct event *));
10512 *events = (struct event *) trimalloc(maxevents * (int) sizeof(struct event));
10513 traversalinit(&m->vertices);
10514 for (i = 0; i < m->invertices; i++) {
10515 thisvertex = vertextraverse(m);
10516 (*events)[i].eventptr = (VOID *) thisvertex;
10517 (*events)[i].xkey = thisvertex[0];
10518 (*events)[i].ykey = thisvertex[1];
10519 eventheapinsert(*eventheap, i, *events + i);
10520 }
10521 *freeevents = (struct event *) NULL;
10522 for (i = maxevents - 1; i >= m->invertices; i--) {
10523 (*events)[i].eventptr = (VOID *) *freeevents;
10524 *freeevents = *events + i;
10525 }
10526 }
10527
10528 #endif
10529
10530 #ifndef REDUCED
10531
10532 #ifdef ANSI_DECLARATORS
10533 int rightofhyperbola(struct mesh *m, struct otri *fronttri, vertex newsite)
10534 #else
10535 int rightofhyperbola(m, fronttri, newsite)
10536 struct mesh *m;
10537 struct otri *fronttri;
10538 vertex newsite;
10539 #endif
10540
10541 {
10542 vertex leftvertex, rightvertex;
10543 REAL dxa, dya, dxb, dyb;
10544
10545 m->hyperbolacount++;
10546
10547 dest(*fronttri, leftvertex);
10548 apex(*fronttri, rightvertex);
10549 if ((leftvertex[1] < rightvertex[1]) ||
10550 ((leftvertex[1] == rightvertex[1]) &&
10551 (leftvertex[0] < rightvertex[0]))) {
10552 if (newsite[0] >= rightvertex[0]) {
10553 return 1;
10554 }
10555 } else {
10556 if (newsite[0] <= leftvertex[0]) {
10557 return 0;
10558 }
10559 }
10560 dxa = leftvertex[0] - newsite[0];
10561 dya = leftvertex[1] - newsite[1];
10562 dxb = rightvertex[0] - newsite[0];
10563 dyb = rightvertex[1] - newsite[1];
10564 return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
10565 }
10566
10567 #endif
10568
10569 #ifndef REDUCED
10570
10571 #ifdef ANSI_DECLARATORS
10572 REAL circletop(struct mesh *m, vertex pa, vertex pb, vertex pc, REAL ccwabc)
10573 #else
10574 REAL circletop(m, pa, pb, pc, ccwabc)
10575 struct mesh *m;
10576 vertex pa;
10577 vertex pb;
10578 vertex pc;
10579 REAL ccwabc;
10580 #endif
10581
10582 {
10583 REAL xac, yac, xbc, ybc, xab, yab;
10584 REAL aclen2, bclen2, ablen2;
10585
10586 m->circletopcount++;
10587
10588 xac = pa[0] - pc[0];
10589 yac = pa[1] - pc[1];
10590 xbc = pb[0] - pc[0];
10591 ybc = pb[1] - pc[1];
10592 xab = pa[0] - pb[0];
10593 yab = pa[1] - pb[1];
10594 aclen2 = xac * xac + yac * yac;
10595 bclen2 = xbc * xbc + ybc * ybc;
10596 ablen2 = xab * xab + yab * yab;
10597 return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
10598 / (2.0 * ccwabc);
10599 }
10600
10601 #endif
10602
10603 #ifndef REDUCED
10604
10605 #ifdef ANSI_DECLARATORS
10606 void check4deadevent(struct otri *checktri, struct event **freeevents,
10607 struct event **eventheap, int *heapsize)
10608 #else
10609 void check4deadevent(checktri, freeevents, eventheap, heapsize)
10610 struct otri *checktri;
10611 struct event **freeevents;
10612 struct event **eventheap;
10613 int *heapsize;
10614 #endif
10615
10616 {
10617 struct event *deadevent;
10618 vertex eventvertex;
10619 int eventnum;
10620
10621 org(*checktri, eventvertex);
10622 if (eventvertex != (vertex) NULL) {
10623 deadevent = (struct event *) eventvertex;
10624 eventnum = deadevent->heapposition;
10625 deadevent->eventptr = (VOID *) *freeevents;
10626 *freeevents = deadevent;
10627 eventheapdelete(eventheap, *heapsize, eventnum);
10628 (*heapsize)--;
10629 setorg(*checktri, NULL);
10630 }
10631 }
10632
10633 #endif
10634
10635 #ifndef REDUCED
10636
10637 #ifdef ANSI_DECLARATORS
10638 struct splaynode *splay(struct mesh *m, struct splaynode *splaytree,
10639 vertex searchpoint, struct otri *searchtri)
10640 #else
10641 struct splaynode *splay(m, splaytree, searchpoint, searchtri)
10642 struct mesh *m;
10643 struct splaynode *splaytree;
10644 vertex searchpoint;
10645 struct otri *searchtri;
10646 #endif
10647
10648 {
10649 struct splaynode *child, *grandchild;
10650 struct splaynode *lefttree, *righttree;
10651 struct splaynode *leftright;
10652 vertex checkvertex;
10653 int rightofroot, rightofchild;
10654
10655 if (splaytree == (struct splaynode *) NULL) {
10656 return (struct splaynode *) NULL;
10657 }
10658 dest(splaytree->keyedge, checkvertex);
10659 if (checkvertex == splaytree->keydest) {
10660 rightofroot = rightofhyperbola(m, &splaytree->keyedge, searchpoint);
10661 if (rightofroot) {
10662 otricopy(splaytree->keyedge, *searchtri);
10663 child = splaytree->rchild;
10664 } else {
10665 child = splaytree->lchild;
10666 }
10667 if (child == (struct splaynode *) NULL) {
10668 return splaytree;
10669 }
10670 dest(child->keyedge, checkvertex);
10671 if (checkvertex != child->keydest) {
10672 child = splay(m, child, searchpoint, searchtri);
10673 if (child == (struct splaynode *) NULL) {
10674 if (rightofroot) {
10675 splaytree->rchild = (struct splaynode *) NULL;
10676 } else {
10677 splaytree->lchild = (struct splaynode *) NULL;
10678 }
10679 return splaytree;
10680 }
10681 }
10682 rightofchild = rightofhyperbola(m, &child->keyedge, searchpoint);
10683 if (rightofchild) {
10684 otricopy(child->keyedge, *searchtri);
10685 grandchild = splay(m, child->rchild, searchpoint, searchtri);
10686 child->rchild = grandchild;
10687 } else {
10688 grandchild = splay(m, child->lchild, searchpoint, searchtri);
10689 child->lchild = grandchild;
10690 }
10691 if (grandchild == (struct splaynode *) NULL) {
10692 if (rightofroot) {
10693 splaytree->rchild = child->lchild;
10694 child->lchild = splaytree;
10695 } else {
10696 splaytree->lchild = child->rchild;
10697 child->rchild = splaytree;
10698 }
10699 return child;
10700 }
10701 if (rightofchild) {
10702 if (rightofroot) {
10703 splaytree->rchild = child->lchild;
10704 child->lchild = splaytree;
10705 } else {
10706 splaytree->lchild = grandchild->rchild;
10707 grandchild->rchild = splaytree;
10708 }
10709 child->rchild = grandchild->lchild;
10710 grandchild->lchild = child;
10711 } else {
10712 if (rightofroot) {
10713 splaytree->rchild = grandchild->lchild;
10714 grandchild->lchild = splaytree;
10715 } else {
10716 splaytree->lchild = child->rchild;
10717 child->rchild = splaytree;
10718 }
10719 child->lchild = grandchild->rchild;
10720 grandchild->rchild = child;
10721 }
10722 return grandchild;
10723 } else {
10724 lefttree = splay(m, splaytree->lchild, searchpoint, searchtri);
10725 righttree = splay(m, splaytree->rchild, searchpoint, searchtri);
10726
10727 pooldealloc(&m->splaynodes, (VOID *) splaytree);
10728 if (lefttree == (struct splaynode *) NULL) {
10729 return righttree;
10730 } else if (righttree == (struct splaynode *) NULL) {
10731 return lefttree;
10732 } else if (lefttree->rchild == (struct splaynode *) NULL) {
10733 lefttree->rchild = righttree->lchild;
10734 righttree->lchild = lefttree;
10735 return righttree;
10736 } else if (righttree->lchild == (struct splaynode *) NULL) {
10737 righttree->lchild = lefttree->rchild;
10738 lefttree->rchild = righttree;
10739 return lefttree;
10740 } else {
10741
10742 leftright = lefttree->rchild;
10743 while (leftright->rchild != (struct splaynode *) NULL) {
10744 leftright = leftright->rchild;
10745 }
10746 leftright->rchild = righttree;
10747 return lefttree;
10748 }
10749 }
10750 }
10751
10752 #endif
10753
10754 #ifndef REDUCED
10755
10756 #ifdef ANSI_DECLARATORS
10757 struct splaynode *splayinsert(struct mesh *m, struct splaynode *splayroot,
10758 struct otri *newkey, vertex searchpoint)
10759 #else
10760 struct splaynode *splayinsert(m, splayroot, newkey, searchpoint)
10761 struct mesh *m;
10762 struct splaynode *splayroot;
10763 struct otri *newkey;
10764 vertex searchpoint;
10765 #endif
10766
10767 {
10768 struct splaynode *newsplaynode;
10769
10770 newsplaynode = (struct splaynode *) poolalloc(&m->splaynodes);
10771 otricopy(*newkey, newsplaynode->keyedge);
10772 dest(*newkey, newsplaynode->keydest);
10773 if (splayroot == (struct splaynode *) NULL) {
10774 newsplaynode->lchild = (struct splaynode *) NULL;
10775 newsplaynode->rchild = (struct splaynode *) NULL;
10776 } else if (rightofhyperbola(m, &splayroot->keyedge, searchpoint)) {
10777 newsplaynode->lchild = splayroot;
10778 newsplaynode->rchild = splayroot->rchild;
10779 splayroot->rchild = (struct splaynode *) NULL;
10780 } else {
10781 newsplaynode->lchild = splayroot->lchild;
10782 newsplaynode->rchild = splayroot;
10783 splayroot->lchild = (struct splaynode *) NULL;
10784 }
10785 return newsplaynode;
10786 }
10787
10788 #endif
10789
10790 #ifndef REDUCED
10791
10792 #ifdef ANSI_DECLARATORS
10793 struct splaynode *circletopinsert(struct mesh *m, struct behavior *b,
10794 struct splaynode *splayroot,
10795 struct otri *newkey,
10796 vertex pa, vertex pb, vertex pc, REAL topy)
10797 #else
10798 struct splaynode *circletopinsert(m, b, splayroot, newkey, pa, pb, pc, topy)
10799 struct mesh *m;
10800 struct behavior *b;
10801 struct splaynode *splayroot;
10802 struct otri *newkey;
10803 vertex pa;
10804 vertex pb;
10805 vertex pc;
10806 REAL topy;
10807 #endif
10808
10809 {
10810 REAL ccwabc;
10811 REAL xac, yac, xbc, ybc;
10812 REAL aclen2, bclen2;
10813 REAL searchpoint[2];
10814 struct otri dummytri;
10815
10816 ccwabc = counterclockwise(m, b, pa, pb, pc);
10817 xac = pa[0] - pc[0];
10818 yac = pa[1] - pc[1];
10819 xbc = pb[0] - pc[0];
10820 ybc = pb[1] - pc[1];
10821 aclen2 = xac * xac + yac * yac;
10822 bclen2 = xbc * xbc + ybc * ybc;
10823 searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
10824 searchpoint[1] = topy;
10825 return splayinsert(m, splay(m, splayroot, (vertex) searchpoint, &dummytri),
10826 newkey, (vertex) searchpoint);
10827 }
10828
10829 #endif
10830
10831 #ifndef REDUCED
10832
10833 #ifdef ANSI_DECLARATORS
10834 struct splaynode *frontlocate(struct mesh *m, struct splaynode *splayroot,
10835 struct otri *bottommost, vertex searchvertex,
10836 struct otri *searchtri, int *farright)
10837 #else
10838 struct splaynode *frontlocate(m, splayroot, bottommost, searchvertex,
10839 searchtri, farright)
10840 struct mesh *m;
10841 struct splaynode *splayroot;
10842 struct otri *bottommost;
10843 vertex searchvertex;
10844 struct otri *searchtri;
10845 int *farright;
10846 #endif
10847
10848 {
10849 int farrightflag;
10850 triangle ptr;
10851
10852 otricopy(*bottommost, *searchtri);
10853 splayroot = splay(m, splayroot, searchvertex, searchtri);
10854
10855 farrightflag = 0;
10856 while (!farrightflag && rightofhyperbola(m, searchtri, searchvertex)) {
10857 onextself(*searchtri);
10858 farrightflag = otriequal(*searchtri, *bottommost);
10859 }
10860 *farright = farrightflag;
10861 return splayroot;
10862 }
10863
10864 #endif
10865
10866 #ifndef REDUCED
10867
10868 #ifdef ANSI_DECLARATORS
10869 long sweeplinedelaunay(struct mesh *m, struct behavior *b)
10870 #else
10871 long sweeplinedelaunay(m, b)
10872 struct mesh *m;
10873 struct behavior *b;
10874 #endif
10875
10876 {
10877 struct event **eventheap;
10878 struct event *events;
10879 struct event *freeevents;
10880 struct event *nextevent;
10881 struct event *newevent;
10882 struct splaynode *splayroot;
10883 struct otri bottommost;
10884 struct otri searchtri;
10885 struct otri fliptri;
10886 struct otri lefttri, righttri, farlefttri, farrighttri;
10887 struct otri inserttri;
10888 vertex firstvertex, secondvertex;
10889 vertex nextvertex, lastvertex;
10890 vertex connectvertex;
10891 vertex leftvertex, midvertex, rightvertex;
10892 REAL lefttest, righttest;
10893 int heapsize;
10894 int check4events, farrightflag;
10895 triangle ptr;
10896
10897 poolinit(&m->splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK,
10898 SPLAYNODEPERBLOCK, 0);
10899 splayroot = (struct splaynode *) NULL;
10900
10901 if (b->verbose) {
10902 printf(" Placing vertices in event heap.\n");
10903 }
10904 createeventheap(m, &eventheap, &events, &freeevents);
10905 heapsize = m->invertices;
10906
10907 if (b->verbose) {
10908 printf(" Forming triangulation.\n");
10909 }
10910 maketriangle(m, b, &lefttri);
10911 maketriangle(m, b, &righttri);
10912 bond(lefttri, righttri);
10913 lnextself(lefttri);
10914 lprevself(righttri);
10915 bond(lefttri, righttri);
10916 lnextself(lefttri);
10917 lprevself(righttri);
10918 bond(lefttri, righttri);
10919 firstvertex = (vertex) eventheap[0]->eventptr;
10920 eventheap[0]->eventptr = (VOID *) freeevents;
10921 freeevents = eventheap[0];
10922 eventheapdelete(eventheap, heapsize, 0);
10923 heapsize--;
10924 do {
10925 if (heapsize == 0) {
10926 printf("Error: Input vertices are all identical.\n");
10927 triexit(1);
10928 }
10929 secondvertex = (vertex) eventheap[0]->eventptr;
10930 eventheap[0]->eventptr = (VOID *) freeevents;
10931 freeevents = eventheap[0];
10932 eventheapdelete(eventheap, heapsize, 0);
10933 heapsize--;
10934 if ((firstvertex[0] == secondvertex[0]) &&
10935 (firstvertex[1] == secondvertex[1])) {
10936 if (!b->quiet) {
10937 printf(
10938 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10939 secondvertex[0], secondvertex[1]);
10940 }
10941 setvertextype(secondvertex, UNDEADVERTEX);
10942 m->undeads++;
10943 }
10944 } while ((firstvertex[0] == secondvertex[0]) &&
10945 (firstvertex[1] == secondvertex[1]));
10946 setorg(lefttri, firstvertex);
10947 setdest(lefttri, secondvertex);
10948 setorg(righttri, secondvertex);
10949 setdest(righttri, firstvertex);
10950 lprev(lefttri, bottommost);
10951 lastvertex = secondvertex;
10952 while (heapsize > 0) {
10953 nextevent = eventheap[0];
10954 eventheapdelete(eventheap, heapsize, 0);
10955 heapsize--;
10956 check4events = 1;
10957 if (nextevent->xkey < m->xmin) {
10958 decode(nextevent->eventptr, fliptri);
10959 oprev(fliptri, farlefttri);
10960 check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
10961 onext(fliptri, farrighttri);
10962 check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
10963
10964 if (otriequal(farlefttri, bottommost)) {
10965 lprev(fliptri, bottommost);
10966 }
10967 flip(m, b, &fliptri);
10968 setapex(fliptri, NULL);
10969 lprev(fliptri, lefttri);
10970 lnext(fliptri, righttri);
10971 sym(lefttri, farlefttri);
10972
10973 if (randomnation(SAMPLERATE) == 0) {
10974 symself(fliptri);
10975 dest(fliptri, leftvertex);
10976 apex(fliptri, midvertex);
10977 org(fliptri, rightvertex);
10978 splayroot = circletopinsert(m, b, splayroot, &lefttri, leftvertex,
10979 midvertex, rightvertex, nextevent->ykey);
10980 }
10981 } else {
10982 nextvertex = (vertex) nextevent->eventptr;
10983 if ((nextvertex[0] == lastvertex[0]) &&
10984 (nextvertex[1] == lastvertex[1])) {
10985 if (!b->quiet) {
10986 printf(
10987 "Warning: A duplicate vertex at (%.12g, %.12g) appeared and was ignored.\n",
10988 nextvertex[0], nextvertex[1]);
10989 }
10990 setvertextype(nextvertex, UNDEADVERTEX);
10991 m->undeads++;
10992 check4events = 0;
10993 } else {
10994 lastvertex = nextvertex;
10995
10996 splayroot = frontlocate(m, splayroot, &bottommost, nextvertex,
10997 &searchtri, &farrightflag);
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007 check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
11008
11009 otricopy(searchtri, farrighttri);
11010 sym(searchtri, farlefttri);
11011 maketriangle(m, b, &lefttri);
11012 maketriangle(m, b, &righttri);
11013 dest(farrighttri, connectvertex);
11014 setorg(lefttri, connectvertex);
11015 setdest(lefttri, nextvertex);
11016 setorg(righttri, nextvertex);
11017 setdest(righttri, connectvertex);
11018 bond(lefttri, righttri);
11019 lnextself(lefttri);
11020 lprevself(righttri);
11021 bond(lefttri, righttri);
11022 lnextself(lefttri);
11023 lprevself(righttri);
11024 bond(lefttri, farlefttri);
11025 bond(righttri, farrighttri);
11026 if (!farrightflag && otriequal(farrighttri, bottommost)) {
11027 otricopy(lefttri, bottommost);
11028 }
11029
11030 if (randomnation(SAMPLERATE) == 0) {
11031 splayroot = splayinsert(m, splayroot, &lefttri, nextvertex);
11032 } else if (randomnation(SAMPLERATE) == 0) {
11033 lnext(righttri, inserttri);
11034 splayroot = splayinsert(m, splayroot, &inserttri, nextvertex);
11035 }
11036 }
11037 }
11038 nextevent->eventptr = (VOID *) freeevents;
11039 freeevents = nextevent;
11040
11041 if (check4events) {
11042 apex(farlefttri, leftvertex);
11043 dest(lefttri, midvertex);
11044 apex(lefttri, rightvertex);
11045 lefttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
11046 if (lefttest > 0.0) {
11047 newevent = freeevents;
11048 freeevents = (struct event *) freeevents->eventptr;
11049 newevent->xkey = m->xminextreme;
11050 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
11051 lefttest);
11052 newevent->eventptr = (VOID *) encode(lefttri);
11053 eventheapinsert(eventheap, heapsize, newevent);
11054 heapsize++;
11055 setorg(lefttri, newevent);
11056 }
11057 apex(righttri, leftvertex);
11058 org(righttri, midvertex);
11059 apex(farrighttri, rightvertex);
11060 righttest = counterclockwise(m, b, leftvertex, midvertex, rightvertex);
11061 if (righttest > 0.0) {
11062 newevent = freeevents;
11063 freeevents = (struct event *) freeevents->eventptr;
11064 newevent->xkey = m->xminextreme;
11065 newevent->ykey = circletop(m, leftvertex, midvertex, rightvertex,
11066 righttest);
11067 newevent->eventptr = (VOID *) encode(farrighttri);
11068 eventheapinsert(eventheap, heapsize, newevent);
11069 heapsize++;
11070 setorg(farrighttri, newevent);
11071 }
11072 }
11073 }
11074
11075 pooldeinit(&m->splaynodes);
11076 lprevself(bottommost);
11077 return removeghosts(m, b, &bottommost);
11078 }
11079
11080 #endif
11081
11084
11085
11086
11090
11091
11092
11093
11094
11095
11096 #ifdef ANSI_DECLARATORS
11097 long delaunay(struct mesh *m, struct behavior *b)
11098 #else
11099 long delaunay(m, b)
11100 struct mesh *m;
11101 struct behavior *b;
11102 #endif
11103
11104 {
11105 long hulledges;
11106
11107 m->eextras = 0;
11108 initializetrisubpools(m, b);
11109
11110 #ifdef REDUCED
11111 if (!b->quiet) {
11112 printf(
11113 "Constructing Delaunay triangulation by divide-and-conquer method.\n");
11114 }
11115 hulledges = divconqdelaunay(m, b);
11116 #else
11117 if (!b->quiet) {
11118 printf("Constructing Delaunay triangulation ");
11119 if (b->incremental) {
11120 printf("by incremental method.\n");
11121 } else if (b->sweepline) {
11122 printf("by sweepline method.\n");
11123 } else {
11124 printf("by divide-and-conquer method.\n");
11125 }
11126 }
11127 if (b->incremental) {
11128 hulledges = incrementaldelaunay(m, b);
11129 } else if (b->sweepline) {
11130 hulledges = sweeplinedelaunay(m, b);
11131 } else {
11132 hulledges = divconqdelaunay(m, b);
11133 }
11134 #endif
11135
11136 if (m->triangles.items == 0) {
11137
11138 return 0l;
11139 } else {
11140 return hulledges;
11141 }
11142 }
11143
11144
11145
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169 #ifndef CDT_ONLY
11170
11171 #ifdef TRILIBRARY
11172
11173 #ifdef ANSI_DECLARATORS
11174 int reconstruct(struct mesh *m, struct behavior *b, int *trianglelist,
11175 REAL *triangleattriblist, REAL *trianglearealist,
11176 int elements, int corners, int attribs,
11177 int *segmentlist,int *segmentmarkerlist, int numberofsegments)
11178 #else
11179 int reconstruct(m, b, trianglelist, triangleattriblist, trianglearealist,
11180 elements, corners, attribs, segmentlist, segmentmarkerlist,
11181 numberofsegments)
11182 struct mesh *m;
11183 struct behavior *b;
11184 int *trianglelist;
11185 REAL *triangleattriblist;
11186 REAL *trianglearealist;
11187 int elements;
11188 int corners;
11189 int attribs;
11190 int *segmentlist;
11191 int *segmentmarkerlist;
11192 int numberofsegments;
11193 #endif
11194
11195 #else
11196
11197 #ifdef ANSI_DECLARATORS
11198 long reconstruct(struct mesh *m, struct behavior *b, char *elefilename,
11199 char *areafilename, char* polyfilename, FILE* polyfile)
11200 #else
11201 long reconstruct(m, b, elefilename, areafilename, polyfilename, polyfile)
11202 struct mesh *m;
11203 struct behavior *b;
11204 char *elefilename;
11205 char *areafilename;
11206 char* polyfilename;
11207 FILE* polyfile;
11208 #endif
11209
11210 #endif
11211
11212 {
11213 #ifdef TRILIBRARY
11214 int vertexindex;
11215 int attribindex;
11216 #else
11217 FILE *elefile;
11218 FILE *areafile;
11219 char inputline[INPUTLINESIZE];
11220 char *stringptr;
11221 int areaelements;
11222 #endif
11223 struct otri triangleloop;
11224 struct otri triangleleft;
11225 struct otri checktri;
11226 struct otri checkleft;
11227 struct otri checkneighbor;
11228 struct osub subsegloop;
11229 triangle *vertexarray;
11230 triangle* prevlink;
11231 triangle nexttri;
11232 vertex tdest, tapex;
11233 vertex checkdest, checkapex;
11234 vertex shorg;
11235 vertex killvertex;
11236 vertex segmentorg, segmentdest;
11237 REAL area;
11238 int corner[3];
11239 int end[2];
11240 int killvertexindex;
11241 int incorners;
11242 int segmentmarkers;
11243 int boundmarker;
11244 int aroundvertex;
11245 long hullsize;
11246 int notfound;
11247 long elementnumber, segmentnumber;
11248 int i, j;
11249 triangle ptr;
11250
11251 #ifdef TRILIBRARY
11252 m->inelements = elements;
11253 incorners = corners;
11254 if (incorners < 3) {
11255 printf("Error: Triangles must have at least 3 vertices.\n");
11256 triexit(1);
11257 }
11258 m->eextras = attribs;
11259 #else
11260
11261 if (!b->quiet) {
11262 printf("Opening %s.\n", elefilename);
11263 }
11264 elefile = fopen(elefilename, "r");
11265 if (elefile == (FILE *) NULL) {
11266 printf(" Error: Cannot access file %s.\n", elefilename);
11267 triexit(1);
11268 }
11269
11270
11271 stringptr = readline(inputline, elefile, elefilename);
11272 m->inelements = (int) strtol(stringptr, &stringptr, 0);
11273 stringptr = findfield(stringptr);
11274 if (*stringptr == '\0') {
11275 incorners = 3;
11276 } else {
11277 incorners = (int) strtol(stringptr, &stringptr, 0);
11278 if (incorners < 3) {
11279 printf("Error: Triangles in %s must have at least 3 vertices.\n",
11280 elefilename);
11281 triexit(1);
11282 }
11283 }
11284 stringptr = findfield(stringptr);
11285 if (*stringptr == '\0') {
11286 m->eextras = 0;
11287 } else {
11288 m->eextras = (int) strtol(stringptr, &stringptr, 0);
11289 }
11290 #endif
11291
11292 initializetrisubpools(m, b);
11293
11294
11295 for (elementnumber = 1; elementnumber <= m->inelements; elementnumber++) {
11296 maketriangle(m, b, &triangleloop);
11297
11298 triangleloop.tri[3] = (triangle) triangleloop.tri;
11299 }
11300
11301 segmentmarkers = 0;
11302 if (b->poly) {
11303 #ifdef TRILIBRARY
11304 m->insegments = numberofsegments;
11305 segmentmarkers = segmentmarkerlist != (int *) NULL;
11306 #else
11307
11308
11309 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11310 m->insegments = (int) strtol(stringptr, &stringptr, 0);
11311 stringptr = findfield(stringptr);
11312 if (*stringptr != '\0') {
11313 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
11314 }
11315 #endif
11316
11317
11318 for (segmentnumber = 1; segmentnumber <= m->insegments; segmentnumber++) {
11319 makesubseg(m, &subsegloop);
11320
11321 subsegloop.ss[2] = (subseg) subsegloop.ss;
11322 }
11323 }
11324
11325 #ifdef TRILIBRARY
11326 vertexindex = 0;
11327 attribindex = 0;
11328 #else
11329 if (b->vararea) {
11330
11331 if (!b->quiet) {
11332 printf("Opening %s.\n", areafilename);
11333 }
11334 areafile = fopen(areafilename, "r");
11335 if (areafile == (FILE *) NULL) {
11336 printf(" Error: Cannot access file %s.\n", areafilename);
11337 triexit(1);
11338 }
11339 stringptr = readline(inputline, areafile, areafilename);
11340 areaelements = (int) strtol(stringptr, &stringptr, 0);
11341 if (areaelements != m->inelements) {
11342 printf("Error: %s and %s disagree on number of triangles.\n",
11343 elefilename, areafilename);
11344 triexit(1);
11345 }
11346 }
11347 #endif
11348
11349 if (!b->quiet) {
11350 printf("Reconstructing mesh.\n");
11351 }
11352
11353
11354
11355 vertexarray = (triangle *) trimalloc(m->vertices.items *
11356 (int) sizeof(triangle));
11357
11358 for (i = 0; i < m->vertices.items; i++) {
11359 vertexarray[i] = (triangle) m->dummytri;
11360 }
11361
11362 if (b->verbose) {
11363 printf(" Assembling triangles.\n");
11364 }
11365
11366
11367 traversalinit(&m->triangles);
11368 triangleloop.tri = triangletraverse(m);
11369 elementnumber = b->firstnumber;
11370 while (triangleloop.tri != (triangle *) NULL) {
11371 #ifdef TRILIBRARY
11372
11373 for (j = 0; j < 3; j++) {
11374 corner[j] = trianglelist[vertexindex++];
11375 if ((corner[j] < b->firstnumber) ||
11376 (corner[j] >= b->firstnumber + m->invertices)) {
11377 printf("Error: Triangle %ld has an invalid vertex index.\n",
11378 elementnumber);
11379 triexit(1);
11380 }
11381 }
11382 #else
11383
11384 stringptr = readline(inputline, elefile, elefilename);
11385 for (j = 0; j < 3; j++) {
11386 stringptr = findfield(stringptr);
11387 if (*stringptr == '\0') {
11388 printf("Error: Triangle %ld is missing vertex %d in %s.\n",
11389 elementnumber, j + 1, elefilename);
11390 triexit(1);
11391 } else {
11392 corner[j] = (int) strtol(stringptr, &stringptr, 0);
11393 if ((corner[j] < b->firstnumber) ||
11394 (corner[j] >= b->firstnumber + m->invertices)) {
11395 printf("Error: Triangle %ld has an invalid vertex index.\n",
11396 elementnumber);
11397 triexit(1);
11398 }
11399 }
11400 }
11401 #endif
11402
11403
11404 for (j = 3; j < incorners; j++) {
11405 #ifdef TRILIBRARY
11406 killvertexindex = trianglelist[vertexindex++];
11407 #else
11408 stringptr = findfield(stringptr);
11409 if (*stringptr != '\0') {
11410 killvertexindex = (int) strtol(stringptr, &stringptr, 0);
11411 #endif
11412 if ((killvertexindex >= b->firstnumber) &&
11413 (killvertexindex < b->firstnumber + m->invertices)) {
11414
11415 killvertex = getvertex(m, b, killvertexindex);
11416 if (vertextype(killvertex) != DEADVERTEX) {
11417 vertexdealloc(m, killvertex);
11418 }
11419 }
11420 #ifndef TRILIBRARY
11421 }
11422 #endif
11423 }
11424
11425
11426 for (j = 0; j < m->eextras; j++) {
11427 #ifdef TRILIBRARY
11428 setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
11429 #else
11430 stringptr = findfield(stringptr);
11431 if (*stringptr == '\0') {
11432 setelemattribute(triangleloop, j, 0);
11433 } else {
11434 setelemattribute(triangleloop, j,
11435 (REAL) strtod(stringptr, &stringptr));
11436 }
11437 #endif
11438 }
11439
11440 if (b->vararea) {
11441 #ifdef TRILIBRARY
11442 area = trianglearealist[elementnumber - b->firstnumber];
11443 #else
11444
11445 stringptr = readline(inputline, areafile, areafilename);
11446 stringptr = findfield(stringptr);
11447 if (*stringptr == '\0') {
11448 area = -1.0;
11449 } else {
11450 area = (REAL) strtod(stringptr, &stringptr);
11451 }
11452 #endif
11453 setareabound(triangleloop, area);
11454 }
11455
11456
11457 triangleloop.orient = 0;
11458 setorg(triangleloop, getvertex(m, b, corner[0]));
11459 setdest(triangleloop, getvertex(m, b, corner[1]));
11460 setapex(triangleloop, getvertex(m, b, corner[2]));
11461
11462 for (triangleloop.orient = 0; triangleloop.orient < 3;
11463 triangleloop.orient++) {
11464
11465 aroundvertex = corner[triangleloop.orient];
11466
11467 nexttri = vertexarray[aroundvertex - b->firstnumber];
11468
11469 triangleloop.tri[6 + triangleloop.orient] = nexttri;
11470
11471 vertexarray[aroundvertex - b->firstnumber] = encode(triangleloop);
11472 decode(nexttri, checktri);
11473 if (checktri.tri != m->dummytri) {
11474 dest(triangleloop, tdest);
11475 apex(triangleloop, tapex);
11476
11477 do {
11478 dest(checktri, checkdest);
11479 apex(checktri, checkapex);
11480 if (tapex == checkdest) {
11481
11482 lprev(triangleloop, triangleleft);
11483 bond(triangleleft, checktri);
11484 }
11485 if (tdest == checkapex) {
11486
11487 lprev(checktri, checkleft);
11488 bond(triangleloop, checkleft);
11489 }
11490
11491 nexttri = checktri.tri[6 + checktri.orient];
11492 decode(nexttri, checktri);
11493 } while (checktri.tri != m->dummytri);
11494 }
11495 }
11496 triangleloop.tri = triangletraverse(m);
11497 elementnumber++;
11498 }
11499
11500 #ifdef TRILIBRARY
11501 vertexindex = 0;
11502 #else
11503 fclose(elefile);
11504 if (b->vararea) {
11505 fclose(areafile);
11506 }
11507 #endif
11508
11509 hullsize = 0;
11510 if (b->poly) {
11511 if (b->verbose) {
11512 printf(" Marking segments in triangulation.\n");
11513 }
11514
11515
11516 boundmarker = 0;
11517 traversalinit(&m->subsegs);
11518 subsegloop.ss = subsegtraverse(m);
11519 segmentnumber = b->firstnumber;
11520 while (subsegloop.ss != (subseg *) NULL) {
11521 #ifdef TRILIBRARY
11522 end[0] = segmentlist[vertexindex++];
11523 end[1] = segmentlist[vertexindex++];
11524 if (segmentmarkers) {
11525 boundmarker = segmentmarkerlist[segmentnumber - b->firstnumber];
11526 }
11527 #else
11528
11529 stringptr = readline(inputline, polyfile, b->inpolyfilename);
11530
11531 stringptr = findfield(stringptr);
11532 if (*stringptr == '\0') {
11533 printf("Error: Segment %ld has no endpoints in %s.\n", segmentnumber,
11534 polyfilename);
11535 triexit(1);
11536 } else {
11537 end[0] = (int) strtol(stringptr, &stringptr, 0);
11538 }
11539 stringptr = findfield(stringptr);
11540 if (*stringptr == '\0') {
11541 printf("Error: Segment %ld is missing its second endpoint in %s.\n",
11542 segmentnumber, polyfilename);
11543 triexit(1);
11544 } else {
11545 end[1] = (int) strtol(stringptr, &stringptr, 0);
11546 }
11547 if (segmentmarkers) {
11548 stringptr = findfield(stringptr);
11549 if (*stringptr == '\0') {
11550 boundmarker = 0;
11551 } else {
11552 boundmarker = (int) strtol(stringptr, &stringptr, 0);
11553 }
11554 }
11555 #endif
11556 for (j = 0; j < 2; j++) {
11557 if ((end[j] < b->firstnumber) ||
11558 (end[j] >= b->firstnumber + m->invertices)) {
11559 printf("Error: Segment %ld has an invalid vertex index.\n",
11560 segmentnumber);
11561 triexit(1);
11562 }
11563 }
11564
11565
11566 subsegloop.ssorient = 0;
11567 segmentorg = getvertex(m, b, end[0]);
11568 segmentdest = getvertex(m, b, end[1]);
11569 setsorg(subsegloop, segmentorg);
11570 setsdest(subsegloop, segmentdest);
11571 setsegorg(subsegloop, segmentorg);
11572 setsegdest(subsegloop, segmentdest);
11573 setmark(subsegloop, boundmarker);
11574
11575 for (subsegloop.ssorient = 0; subsegloop.ssorient < 2;
11576 subsegloop.ssorient++) {
11577
11578 aroundvertex = end[1 - subsegloop.ssorient];
11579
11580 prevlink = &vertexarray[aroundvertex - b->firstnumber];
11581 nexttri = vertexarray[aroundvertex - b->firstnumber];
11582 decode(nexttri, checktri);
11583 sorg(subsegloop, shorg);
11584 notfound = 1;
11585
11586
11587
11588
11589
11590
11591
11592 while (notfound && (checktri.tri != m->dummytri)) {
11593 dest(checktri, checkdest);
11594 if (shorg == checkdest) {
11595
11596 * prevlink = checktri.tri[6 + checktri.orient];
11597
11598 tsbond(checktri, subsegloop);
11599
11600 sym(checktri, checkneighbor);
11601 if (checkneighbor.tri == m->dummytri) {
11602
11603
11604
11605 insertsubseg(m, b, &checktri, 1);
11606 hullsize++;
11607 }
11608 notfound = 0;
11609 }
11610
11611 prevlink = &checktri.tri[6 + checktri.orient];
11612 nexttri = checktri.tri[6 + checktri.orient];
11613 decode(nexttri, checktri);
11614 }
11615 }
11616 subsegloop.ss = subsegtraverse(m);
11617 segmentnumber++;
11618 }
11619 }
11620
11621
11622
11623 for (i = 0; i < m->vertices.items; i++) {
11624
11625 nexttri = vertexarray[i];
11626 decode(nexttri, checktri);
11627 while (checktri.tri != m->dummytri) {
11628
11629
11630 nexttri = checktri.tri[6 + checktri.orient];
11631
11632 tsdissolve(checktri);
11633 sym(checktri, checkneighbor);
11634 if (checkneighbor.tri == m->dummytri) {
11635 insertsubseg(m, b, &checktri, 1);
11636 hullsize++;
11637 }
11638 decode(nexttri, checktri);
11639 }
11640 }
11641
11642 trifree((VOID *) vertexarray);
11643 return hullsize;
11644 }
11645
11646 #endif
11647
11650
11651
11652
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673 #ifdef ANSI_DECLARATORS
11674 enum finddirectionresult finddirection(struct mesh *m, struct behavior *b,
11675 struct otri *searchtri,
11676 vertex searchpoint)
11677 #else
11678 enum finddirectionresult finddirection(m, b, searchtri, searchpoint)
11679 struct mesh *m;
11680 struct behavior *b;
11681 struct otri *searchtri;
11682 vertex searchpoint;
11683 #endif
11684
11685 {
11686 struct otri checktri;
11687 vertex startvertex;
11688 vertex leftvertex, rightvertex;
11689 REAL leftccw, rightccw;
11690 int leftflag, rightflag;
11691 triangle ptr;
11692
11693 org(*searchtri, startvertex);
11694 dest(*searchtri, rightvertex);
11695 apex(*searchtri, leftvertex);
11696
11697 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11698 leftflag = leftccw > 0.0;
11699
11700 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11701 rightflag = rightccw > 0.0;
11702 if (leftflag && rightflag) {
11703
11704
11705 onext(*searchtri, checktri);
11706 if (checktri.tri == m->dummytri) {
11707 leftflag = 0;
11708 } else {
11709 rightflag = 0;
11710 }
11711 }
11712 while (leftflag) {
11713
11714 onextself(*searchtri);
11715 if (searchtri->tri == m->dummytri) {
11716 printf("Internal error in finddirection(): Unable to find a\n");
11717 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11718 startvertex[1]);
11719 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11720 internalerror();
11721 }
11722 apex(*searchtri, leftvertex);
11723 rightccw = leftccw;
11724 leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
11725 leftflag = leftccw > 0.0;
11726 }
11727 while (rightflag) {
11728
11729 oprevself(*searchtri);
11730 if (searchtri->tri == m->dummytri) {
11731 printf("Internal error in finddirection(): Unable to find a\n");
11732 printf(" triangle leading from (%.12g, %.12g) to", startvertex[0],
11733 startvertex[1]);
11734 printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
11735 internalerror();
11736 }
11737 dest(*searchtri, rightvertex);
11738 leftccw = rightccw;
11739 rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
11740 rightflag = rightccw > 0.0;
11741 }
11742 if (leftccw == 0.0) {
11743 return LEFTCOLLINEAR;
11744 } else if (rightccw == 0.0) {
11745 return RIGHTCOLLINEAR;
11746 } else {
11747 return WITHIN;
11748 }
11749 }
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768 #ifdef ANSI_DECLARATORS
11769 void segmentintersection(struct mesh *m, struct behavior *b,
11770 struct otri *splittri, struct osub *splitsubseg,
11771 vertex endpoint2)
11772 #else
11773 void segmentintersection(m, b, splittri, splitsubseg, endpoint2)
11774 struct mesh *m;
11775 struct behavior *b;
11776 struct otri *splittri;
11777 struct osub *splitsubseg;
11778 vertex endpoint2;
11779 #endif
11780
11781 {
11782 struct osub opposubseg;
11783 vertex endpoint1;
11784 vertex torg, tdest;
11785 vertex leftvertex, rightvertex;
11786 vertex newvertex;
11787 enum insertvertexresult success;
11788
11789 REAL ex, ey;
11790 REAL tx, ty;
11791 REAL etx, ety;
11792 REAL split, denom;
11793 int i;
11794 triangle ptr;
11795 subseg sptr;
11796
11797
11798 apex(*splittri, endpoint1);
11799 org(*splittri, torg);
11800 dest(*splittri, tdest);
11801
11802 tx = tdest[0] - torg[0];
11803 ty = tdest[1] - torg[1];
11804 ex = endpoint2[0] - endpoint1[0];
11805 ey = endpoint2[1] - endpoint1[1];
11806 etx = torg[0] - endpoint2[0];
11807 ety = torg[1] - endpoint2[1];
11808 denom = ty * ex - tx * ey;
11809 if (denom == 0.0) {
11810 printf("Internal error in segmentintersection():");
11811 printf(" Attempt to find intersection of parallel segments.\n");
11812 internalerror();
11813 }
11814 split = (ey * etx - ex * ety) / denom;
11815
11816 newvertex = (vertex) poolalloc(&m->vertices);
11817
11818 for (i = 0; i < 2 + m->nextras; i++) {
11819 newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
11820 }
11821 setvertexmark(newvertex, mark(*splitsubseg));
11822 setvertextype(newvertex, INPUTVERTEX);
11823 if (b->verbose > 1) {
11824 printf(
11825 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
11826 torg[0], torg[1], tdest[0], tdest[1], newvertex[0], newvertex[1]);
11827 }
11828
11829 success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
11830 if (success != SUCCESSFULVERTEX) {
11831 printf("Internal error in segmentintersection():\n");
11832 printf(" Failure to split a segment.\n");
11833 internalerror();
11834 }
11835
11836 setvertex2tri(newvertex, encode(*splittri));
11837 if (m->steinerleft > 0) {
11838 m->steinerleft--;
11839 }
11840
11841
11842 ssymself(*splitsubseg);
11843 spivot(*splitsubseg, opposubseg);
11844 sdissolve(*splitsubseg);
11845 sdissolve(opposubseg);
11846 do {
11847 setsegorg(*splitsubseg, newvertex);
11848 snextself(*splitsubseg);
11849 } while (splitsubseg->ss != m->dummysub);
11850 do {
11851 setsegorg(opposubseg, newvertex);
11852 snextself(opposubseg);
11853 } while (opposubseg.ss != m->dummysub);
11854
11855
11856
11857 finddirection(m, b, splittri, endpoint1);
11858 dest(*splittri, rightvertex);
11859 apex(*splittri, leftvertex);
11860 if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1])) {
11861 onextself(*splittri);
11862 } else if ((rightvertex[0] != endpoint1[0]) ||
11863 (rightvertex[1] != endpoint1[1])) {
11864 printf("Internal error in segmentintersection():\n");
11865 printf(" Topological inconsistency after splitting a segment.\n");
11866 internalerror();
11867 }
11868
11869 }
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895 #ifdef ANSI_DECLARATORS
11896 int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri,
11897 vertex endpoint2, int newmark)
11898 #else
11899 int scoutsegment(m, b, searchtri, endpoint2, newmark)
11900 struct mesh *m;
11901 struct behavior *b;
11902 struct otri *searchtri;
11903 vertex endpoint2;
11904 int newmark;
11905 #endif
11906
11907 {
11908 struct otri crosstri;
11909 struct osub crosssubseg;
11910 vertex leftvertex, rightvertex;
11911 enum finddirectionresult collinear;
11912 subseg sptr;
11913
11914 collinear = finddirection(m, b, searchtri, endpoint2);
11915 dest(*searchtri, rightvertex);
11916 apex(*searchtri, leftvertex);
11917 if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
11918 ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1]))) {
11919
11920 if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) {
11921 lprevself(*searchtri);
11922 }
11923
11924 insertsubseg(m, b, searchtri, newmark);
11925 return 1;
11926 } else if (collinear == LEFTCOLLINEAR) {
11927
11928
11929 lprevself(*searchtri);
11930 insertsubseg(m, b, searchtri, newmark);
11931
11932 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11933 } else if (collinear == RIGHTCOLLINEAR) {
11934
11935 insertsubseg(m, b, searchtri, newmark);
11936
11937 lnextself(*searchtri);
11938
11939 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11940 } else {
11941 lnext(*searchtri, crosstri);
11942 tspivot(crosstri, crosssubseg);
11943
11944 if (crosssubseg.ss == m->dummysub) {
11945 return 0;
11946 } else {
11947
11948 segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
11949 otricopy(crosstri, *searchtri);
11950 insertsubseg(m, b, searchtri, newmark);
11951
11952 return scoutsegment(m, b, searchtri, endpoint2, newmark);
11953 }
11954 }
11955 }
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976 #ifndef REDUCED
11977 #ifndef CDT_ONLY
11978
11979 #ifdef ANSI_DECLARATORS
11980 void conformingedge(struct mesh *m, struct behavior *b,
11981 vertex endpoint1, vertex endpoint2, int newmark)
11982 #else
11983 void conformingedge(m, b, endpoint1, endpoint2, newmark)
11984 struct mesh *m;
11985 struct behavior *b;
11986 vertex endpoint1;
11987 vertex endpoint2;
11988 int newmark;
11989 #endif
11990
11991 {
11992 struct otri searchtri1, searchtri2;
11993 struct osub brokensubseg;
11994 vertex newvertex;
11995 vertex midvertex1, midvertex2;
11996 enum insertvertexresult success;
11997 int i;
11998 subseg sptr;
11999
12000 if (b->verbose > 2) {
12001 printf("Forcing segment into triangulation by recursive splitting:\n");
12002 printf(" (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
12003 endpoint2[0], endpoint2[1]);
12004 }
12005
12006 newvertex = (vertex) poolalloc(&m->vertices);
12007
12008 for (i = 0; i < 2 + m->nextras; i++) {
12009 newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
12010 }
12011 setvertexmark(newvertex, newmark);
12012 setvertextype(newvertex, SEGMENTVERTEX);
12013
12014 searchtri1.tri = m->dummytri;
12015
12016 success = insertvertex(m, b, newvertex, &searchtri1, (struct osub *) NULL,
12017 0, 0);
12018 if (success == DUPLICATEVERTEX) {
12019 if (b->verbose > 2) {
12020 printf(" Segment intersects existing vertex (%.12g, %.12g).\n",
12021 newvertex[0], newvertex[1]);
12022 }
12023
12024 vertexdealloc(m, newvertex);
12025 org(searchtri1, newvertex);
12026 } else {
12027 if (success == VIOLATINGVERTEX) {
12028 if (b->verbose > 2) {
12029 printf(" Two segments intersect at (%.12g, %.12g).\n",
12030 newvertex[0], newvertex[1]);
12031 }
12032
12033 tspivot(searchtri1, brokensubseg);
12034 success = insertvertex(m, b, newvertex, &searchtri1, &brokensubseg,
12035 0, 0);
12036 if (success != SUCCESSFULVERTEX) {
12037 printf("Internal error in conformingedge():\n");
12038 printf(" Failure to split a segment.\n");
12039 internalerror();
12040 }
12041 }
12042
12043 if (m->steinerleft > 0) {
12044 m->steinerleft--;
12045 }
12046 }
12047 otricopy(searchtri1, searchtri2);
12048
12049
12050
12051
12052
12053 finddirection(m, b, &searchtri2, endpoint2);
12054 if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark)) {
12055
12056
12057 org(searchtri1, midvertex1);
12058 conformingedge(m, b, midvertex1, endpoint1, newmark);
12059 }
12060 if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark)) {
12061
12062
12063 org(searchtri2, midvertex2);
12064 conformingedge(m, b, midvertex2, endpoint2, newmark);
12065 }
12066 }
12067
12068 #endif
12069 #endif
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109 #ifdef ANSI_DECLARATORS
12110 void delaunayfixup(struct mesh *m, struct behavior *b,
12111 struct otri *fixuptri, int leftside)
12112 #else
12113 void delaunayfixup(m, b, fixuptri, leftside)
12114 struct mesh *m;
12115 struct behavior *b;
12116 struct otri *fixuptri;
12117 int leftside;
12118 #endif
12119
12120 {
12121 struct otri neartri;
12122 struct otri fartri;
12123 struct osub faredge;
12124 vertex nearvertex, leftvertex, rightvertex, farvertex;
12125 triangle ptr;
12126 subseg sptr;
12127
12128 lnext(*fixuptri, neartri);
12129 sym(neartri, fartri);
12130
12131 if (fartri.tri == m->dummytri) {
12132 return;
12133 }
12134 tspivot(neartri, faredge);
12135 if (faredge.ss != m->dummysub) {
12136 return;
12137 }
12138
12139 apex(neartri, nearvertex);
12140 org(neartri, leftvertex);
12141 dest(neartri, rightvertex);
12142 apex(fartri, farvertex);
12143
12144 if (leftside) {
12145 if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0) {
12146
12147
12148 return;
12149 }
12150 } else {
12151 if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0) {
12152
12153
12154 return;
12155 }
12156 }
12157 if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0) {
12158
12159
12160
12161
12162 if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
12163 0.0) {
12164 return;
12165 }
12166
12167 }
12168 flip(m, b, &neartri);
12169 lprevself(*fixuptri);
12170
12171 delaunayfixup(m, b, fixuptri, leftside);
12172 delaunayfixup(m, b, &fartri, leftside);
12173 }
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229 #ifdef ANSI_DECLARATORS
12230 void constrainededge(struct mesh *m, struct behavior *b,
12231 struct otri *starttri, vertex endpoint2, int newmark)
12232 #else
12233 void constrainededge(m, b, starttri, endpoint2, newmark)
12234 struct mesh *m;
12235 struct behavior *b;
12236 struct otri *starttri;
12237 vertex endpoint2;
12238 int newmark;
12239 #endif
12240
12241 {
12242 struct otri fixuptri, fixuptri2;
12243 struct osub crosssubseg;
12244 vertex endpoint1;
12245 vertex farvertex;
12246 REAL area;
12247 int collision;
12248 int done;
12249 triangle ptr;
12250 subseg sptr;
12251
12252 org(*starttri, endpoint1);
12253 lnext(*starttri, fixuptri);
12254 flip(m, b, &fixuptri);
12255
12256
12257 collision = 0;
12258 done = 0;
12259 do {
12260 org(fixuptri, farvertex);
12261
12262
12263 if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1])) {
12264 oprev(fixuptri, fixuptri2);
12265
12266 delaunayfixup(m, b, &fixuptri, 0);
12267 delaunayfixup(m, b, &fixuptri2, 1);
12268 done = 1;
12269 } else {
12270
12271
12272
12273 area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
12274 if (area == 0.0) {
12275
12276 collision = 1;
12277 oprev(fixuptri, fixuptri2);
12278
12279 delaunayfixup(m, b, &fixuptri, 0);
12280 delaunayfixup(m, b, &fixuptri2, 1);
12281 done = 1;
12282 } else {
12283 if (area > 0.0) {
12284 oprev(fixuptri, fixuptri2);
12285
12286
12287 delaunayfixup(m, b, &fixuptri2, 1);
12288
12289
12290
12291 lprevself(fixuptri);
12292 } else {
12293 delaunayfixup(m, b, &fixuptri, 0);
12294
12295
12296
12297 oprevself(fixuptri);
12298 }
12299
12300 tspivot(fixuptri, crosssubseg);
12301 if (crosssubseg.ss == m->dummysub) {
12302 flip(m, b, &fixuptri);
12303 } else {
12304
12305 collision = 1;
12306
12307 segmentintersection(m, b, &fixuptri, &crosssubseg, endpoint2);
12308 done = 1;
12309 }
12310 }
12311 }
12312 } while (!done);
12313
12314 insertsubseg(m, b, &fixuptri, newmark);
12315
12316
12317 if (collision) {
12318
12319 if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark)) {
12320 constrainededge(m, b, &fixuptri, endpoint2, newmark);
12321 }
12322 }
12323 }
12324
12325
12326
12327
12328
12329
12330
12331 #ifdef ANSI_DECLARATORS
12332 void insertsegment(struct mesh *m, struct behavior *b,
12333 vertex endpoint1, vertex endpoint2, int newmark)
12334 #else
12335 void insertsegment(m, b, endpoint1, endpoint2, newmark)
12336 struct mesh *m;
12337 struct behavior *b;
12338 vertex endpoint1;
12339 vertex endpoint2;
12340 int newmark;
12341 #endif
12342
12343 {
12344 struct otri searchtri1, searchtri2;
12345 triangle encodedtri;
12346 vertex checkvertex;
12347 triangle ptr;
12348
12349 if (b->verbose > 1) {
12350 printf(" Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
12351 endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
12352 }
12353
12354
12355 checkvertex = (vertex) NULL;
12356 encodedtri = vertex2tri(endpoint1);
12357 if (encodedtri != (triangle) NULL) {
12358 decode(encodedtri, searchtri1);
12359 org(searchtri1, checkvertex);
12360 }
12361 if (checkvertex != endpoint1) {
12362
12363 searchtri1.tri = m->dummytri;
12364 searchtri1.orient = 0;
12365 symself(searchtri1);
12366
12367 if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX) {
12368 printf(
12369 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12370 printf(" (%.12g, %.12g) in triangulation.\n",
12371 endpoint1[0], endpoint1[1]);
12372 internalerror();
12373 }
12374 }
12375
12376 otricopy(searchtri1, m->recenttri);
12377
12378
12379 if (scoutsegment(m, b, &searchtri1, endpoint2, newmark)) {
12380
12381 return;
12382 }
12383
12384
12385 org(searchtri1, endpoint1);
12386
12387
12388 checkvertex = (vertex) NULL;
12389 encodedtri = vertex2tri(endpoint2);
12390 if (encodedtri != (triangle) NULL) {
12391 decode(encodedtri, searchtri2);
12392 org(searchtri2, checkvertex);
12393 }
12394 if (checkvertex != endpoint2) {
12395
12396 searchtri2.tri = m->dummytri;
12397 searchtri2.orient = 0;
12398 symself(searchtri2);
12399
12400 if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX) {
12401 printf(
12402 "Internal error in insertsegment(): Unable to locate PSLG vertex\n");
12403 printf(" (%.12g, %.12g) in triangulation.\n",
12404 endpoint2[0], endpoint2[1]);
12405 internalerror();
12406 }
12407 }
12408
12409 otricopy(searchtri2, m->recenttri);
12410
12411
12412 if (scoutsegment(m, b, &searchtri2, endpoint1, newmark)) {
12413
12414 return;
12415 }
12416
12417
12418 org(searchtri2, endpoint2);
12419
12420 #ifndef REDUCED
12421 #ifndef CDT_ONLY
12422 if (b->splitseg) {
12423
12424 conformingedge(m, b, endpoint1, endpoint2, newmark);
12425 } else {
12426 #endif
12427 #endif
12428
12429 constrainededge(m, b, &searchtri1, endpoint2, newmark);
12430 #ifndef REDUCED
12431 #ifndef CDT_ONLY
12432 }
12433 #endif
12434 #endif
12435 }
12436
12437
12438
12439
12440
12441
12442
12443 #ifdef ANSI_DECLARATORS
12444 void markhull(struct mesh *m, struct behavior *b)
12445 #else
12446 void markhull(m, b)
12447 struct mesh *m;
12448 struct behavior *b;
12449 #endif
12450
12451 {
12452 struct otri hulltri;
12453 struct otri nexttri;
12454 struct otri starttri;
12455 triangle ptr;
12456
12457
12458 hulltri.tri = m->dummytri;
12459 hulltri.orient = 0;
12460 symself(hulltri);
12461
12462 otricopy(hulltri, starttri);
12463
12464 do {
12465
12466 insertsubseg(m, b, &hulltri, 1);
12467
12468 lnextself(hulltri);
12469 oprev(hulltri, nexttri);
12470 while (nexttri.tri != m->dummytri) {
12471 otricopy(nexttri, hulltri);
12472 oprev(hulltri, nexttri);
12473 }
12474 } while (!otriequal(hulltri, starttri));
12475 }
12476
12477
12478
12479
12480
12481
12482
12483
12484
12485
12486
12487 #ifdef TRILIBRARY
12488
12489 #ifdef ANSI_DECLARATORS
12490 void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist,
12491 int *segmentmarkerlist, int numberofsegments)
12492 #else
12493 void formskeleton(m, b, segmentlist, segmentmarkerlist, numberofsegments)
12494 struct mesh *m;
12495 struct behavior *b;
12496 int *segmentlist;
12497 int *segmentmarkerlist;
12498 int numberofsegments;
12499 #endif
12500
12501 #else
12502
12503 #ifdef ANSI_DECLARATORS
12504 void formskeleton(struct mesh *m, struct behavior *b,
12505 FILE* polyfile, char* polyfilename)
12506 #else
12507 void formskeleton(m, b, polyfile, polyfilename)
12508 struct mesh *m;
12509 struct behavior *b;
12510 FILE* polyfile;
12511 char* polyfilename;
12512 #endif
12513
12514 #endif
12515
12516 {
12517 #ifdef TRILIBRARY
12518 char polyfilename[6];
12519 int index;
12520 #else
12521 char inputline[INPUTLINESIZE];
12522 char *stringptr;
12523 #endif
12524 vertex endpoint1, endpoint2;
12525 int segmentmarkers;
12526 int end1, end2;
12527 int boundmarker;
12528 int i;
12529
12530 if (b->poly) {
12531 if (!b->quiet) {
12532 printf("Recovering segments in Delaunay triangulation.\n");
12533 }
12534 #ifdef TRILIBRARY
12535 strcpy(polyfilename, "input");
12536 m->insegments = numberofsegments;
12537 segmentmarkers = segmentmarkerlist != (int *) NULL;
12538 index = 0;
12539 #else
12540
12541
12542 stringptr = readline(inputline, polyfile, polyfilename);
12543 m->insegments = (int) strtol(stringptr, &stringptr, 0);
12544 stringptr = findfield(stringptr);
12545 if (*stringptr == '\0') {
12546 segmentmarkers = 0;
12547 } else {
12548 segmentmarkers = (int) strtol(stringptr, &stringptr, 0);
12549 }
12550 #endif
12551
12552
12553 if (m->triangles.items == 0) {
12554 return;
12555 }
12556
12557
12558
12559 if (m->insegments > 0) {
12560 makevertexmap(m, b);
12561 if (b->verbose) {
12562 printf(" Recovering PSLG segments.\n");
12563 }
12564 }
12565
12566 boundmarker = 0;
12567
12568 for (i = 0; i < m->insegments; i++) {
12569 #ifdef TRILIBRARY
12570 end1 = segmentlist[index++];
12571 end2 = segmentlist[index++];
12572 if (segmentmarkers) {
12573 boundmarker = segmentmarkerlist[i];
12574 }
12575 #else
12576 stringptr = readline(inputline, polyfile, b->inpolyfilename);
12577 stringptr = findfield(stringptr);
12578 if (*stringptr == '\0') {
12579 printf("Error: Segment %d has no endpoints in %s.\n",
12580 b->firstnumber + i, polyfilename);
12581 triexit(1);
12582 } else {
12583 end1 = (int) strtol(stringptr, &stringptr, 0);
12584 }
12585 stringptr = findfield(stringptr);
12586 if (*stringptr == '\0') {
12587 printf("Error: Segment %d is missing its second endpoint in %s.\n",
12588 b->firstnumber + i, polyfilename);
12589 triexit(1);
12590 } else {
12591 end2 = (int) strtol(stringptr, &stringptr, 0);
12592 }
12593 if (segmentmarkers) {
12594 stringptr = findfield(stringptr);
12595 if (*stringptr == '\0') {
12596 boundmarker = 0;
12597 } else {
12598 boundmarker = (int) strtol(stringptr, &stringptr, 0);
12599 }
12600 }
12601 #endif
12602 if ((end1 < b->firstnumber) ||
12603 (end1 >= b->firstnumber + m->invertices)) {
12604 if (!b->quiet) {
12605 printf("Warning: Invalid first endpoint of segment %d in %s.\n",
12606 b->firstnumber + i, polyfilename);
12607 }
12608 } else if ((end2 < b->firstnumber) ||
12609 (end2 >= b->firstnumber + m->invertices)) {
12610 if (!b->quiet) {
12611 printf("Warning: Invalid second endpoint of segment %d in %s.\n",
12612 b->firstnumber + i, polyfilename);
12613 }
12614 } else {
12615
12616 endpoint1 = getvertex(m, b, end1);
12617 endpoint2 = getvertex(m, b, end2);
12618 if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
12619 if (!b->quiet) {
12620 printf("Warning: Endpoints of segment %d are coincident in %s.\n",
12621 b->firstnumber + i, polyfilename);
12622 }
12623 } else {
12624 insertsegment(m, b, endpoint1, endpoint2, boundmarker);
12625 }
12626 }
12627 }
12628 } else {
12629 m->insegments = 0;
12630 }
12631 if (b->convex || !b->poly) {
12632
12633 if (b->verbose) {
12634 printf(" Enclosing convex hull with segments.\n");
12635 }
12636 markhull(m, b);
12637 }
12638 }
12639
12642
12643
12644
12648
12649
12650
12651
12652
12653
12654
12655
12656 #ifdef ANSI_DECLARATORS
12657 void infecthull(struct mesh *m, struct behavior *b)
12658 #else
12659 void infecthull(m, b)
12660 struct mesh *m;
12661 struct behavior *b;
12662 #endif
12663
12664 {
12665 struct otri hulltri;
12666 struct otri nexttri;
12667 struct otri starttri;
12668 struct osub hullsubseg;
12669 triangle **deadtriangle;
12670 vertex horg, hdest;
12671 triangle ptr;
12672 subseg sptr;
12673
12674 if (b->verbose) {
12675 printf(" Marking concavities (external triangles) for elimination.\n");
12676 }
12677
12678 hulltri.tri = m->dummytri;
12679 hulltri.orient = 0;
12680 symself(hulltri);
12681
12682 otricopy(hulltri, starttri);
12683
12684 do {
12685
12686 if (!infected(hulltri)) {
12687
12688 tspivot(hulltri, hullsubseg);
12689 if (hullsubseg.ss == m->dummysub) {
12690
12691 if (!infected(hulltri)) {
12692 infect(hulltri);
12693 deadtriangle = (triangle **) poolalloc(&m->viri);
12694 *deadtriangle = hulltri.tri;
12695 }
12696 } else {
12697
12698 if (mark(hullsubseg) == 0) {
12699 setmark(hullsubseg, 1);
12700 org(hulltri, horg);
12701 dest(hulltri, hdest);
12702 if (vertexmark(horg) == 0) {
12703 setvertexmark(horg, 1);
12704 }
12705 if (vertexmark(hdest) == 0) {
12706 setvertexmark(hdest, 1);
12707 }
12708 }
12709 }
12710 }
12711
12712 lnextself(hulltri);
12713 oprev(hulltri, nexttri);
12714 while (nexttri.tri != m->dummytri) {
12715 otricopy(nexttri, hulltri);
12716 oprev(hulltri, nexttri);
12717 }
12718 } while (!otriequal(hulltri, starttri));
12719 }
12720
12721
12722
12723
12724
12725
12726
12727
12728
12729
12730
12731
12732
12733
12734
12735
12736
12737
12738 #ifdef ANSI_DECLARATORS
12739 void plague(struct mesh *m, struct behavior *b)
12740 #else
12741 void plague(m, b)
12742 struct mesh *m;
12743 struct behavior *b;
12744 #endif
12745
12746 {
12747 struct otri testtri;
12748 struct otri neighbor;
12749 triangle **virusloop;
12750 triangle **deadtriangle;
12751 struct osub neighborsubseg;
12752 vertex testvertex;
12753 vertex norg, ndest;
12754 vertex deadorg, deaddest, deadapex;
12755 int killorg;
12756 triangle ptr;
12757 subseg sptr;
12758
12759 if (b->verbose) {
12760 printf(" Marking neighbors of marked triangles.\n");
12761 }
12762
12763
12764 traversalinit(&m->viri);
12765 virusloop = (triangle **) traverse(&m->viri);
12766 while (virusloop != (triangle **) NULL) {
12767 testtri.tri = *virusloop;
12768
12769
12770
12771
12772 uninfect(testtri);
12773 if (b->verbose > 2) {
12774
12775
12776 testtri.orient = 0;
12777 org(testtri, deadorg);
12778 dest(testtri, deaddest);
12779 apex(testtri, deadapex);
12780 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12781 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12782 deadapex[0], deadapex[1]);
12783 }
12784
12785 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12786
12787 sym(testtri, neighbor);
12788
12789 tspivot(testtri, neighborsubseg);
12790
12791 if ((neighbor.tri == m->dummytri) || infected(neighbor)) {
12792 if (neighborsubseg.ss != m->dummysub) {
12793
12794
12795
12796 subsegdealloc(m, neighborsubseg.ss);
12797 if (neighbor.tri != m->dummytri) {
12798
12799
12800 uninfect(neighbor);
12801 tsdissolve(neighbor);
12802 infect(neighbor);
12803 }
12804 }
12805 } else {
12806 if (neighborsubseg.ss == m->dummysub) {
12807
12808
12809 if (b->verbose > 2) {
12810 org(neighbor, deadorg);
12811 dest(neighbor, deaddest);
12812 apex(neighbor, deadapex);
12813 printf(
12814 " Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
12815 deadorg[0], deadorg[1], deaddest[0], deaddest[1],
12816 deadapex[0], deadapex[1]);
12817 }
12818 infect(neighbor);
12819
12820 deadtriangle = (triangle **) poolalloc(&m->viri);
12821 *deadtriangle = neighbor.tri;
12822 } else {
12823
12824 stdissolve(neighborsubseg);
12825
12826 if (mark(neighborsubseg) == 0) {
12827 setmark(neighborsubseg, 1);
12828 }
12829 org(neighbor, norg);
12830 dest(neighbor, ndest);
12831 if (vertexmark(norg) == 0) {
12832 setvertexmark(norg, 1);
12833 }
12834 if (vertexmark(ndest) == 0) {
12835 setvertexmark(ndest, 1);
12836 }
12837 }
12838 }
12839 }
12840
12841
12842 infect(testtri);
12843 virusloop = (triangle **) traverse(&m->viri);
12844 }
12845
12846 if (b->verbose) {
12847 printf(" Deleting marked triangles.\n");
12848 }
12849
12850 traversalinit(&m->viri);
12851 virusloop = (triangle **) traverse(&m->viri);
12852 while (virusloop != (triangle **) NULL) {
12853 testtri.tri = *virusloop;
12854
12855
12856
12857
12858 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12859 org(testtri, testvertex);
12860
12861 if (testvertex != (vertex) NULL) {
12862 killorg = 1;
12863
12864 setorg(testtri, NULL);
12865
12866 onext(testtri, neighbor);
12867
12868 while ((neighbor.tri != m->dummytri) &&
12869 (!otriequal(neighbor, testtri))) {
12870 if (infected(neighbor)) {
12871
12872 setorg(neighbor, NULL);
12873 } else {
12874
12875 killorg = 0;
12876 }
12877
12878 onextself(neighbor);
12879 }
12880
12881 if (neighbor.tri == m->dummytri) {
12882
12883 oprev(testtri, neighbor);
12884
12885 while (neighbor.tri != m->dummytri) {
12886 if (infected(neighbor)) {
12887
12888 setorg(neighbor, NULL);
12889 } else {
12890
12891 killorg = 0;
12892 }
12893
12894 oprevself(neighbor);
12895 }
12896 }
12897 if (killorg) {
12898 if (b->verbose > 1) {
12899 printf(" Deleting vertex (%.12g, %.12g)\n",
12900 testvertex[0], testvertex[1]);
12901 }
12902 setvertextype(testvertex, UNDEADVERTEX);
12903 m->undeads++;
12904 }
12905 }
12906 }
12907
12908
12909
12910 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
12911 sym(testtri, neighbor);
12912 if (neighbor.tri == m->dummytri) {
12913
12914
12915
12916 m->hullsize--;
12917 } else {
12918
12919 dissolve(neighbor);
12920
12921
12922 m->hullsize++;
12923 }
12924 }
12925
12926 triangledealloc(m, testtri.tri);
12927 virusloop = (triangle **) traverse(&m->viri);
12928 }
12929
12930 poolrestart(&m->viri);
12931 }
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948 #ifdef ANSI_DECLARATORS
12949 void regionplague(struct mesh *m, struct behavior *b,
12950 REAL attribute, REAL area)
12951 #else
12952 void regionplague(m, b, attribute, area)
12953 struct mesh *m;
12954 struct behavior *b;
12955 REAL attribute;
12956 REAL area;
12957 #endif
12958
12959 {
12960 struct otri testtri;
12961 struct otri neighbor;
12962 triangle **virusloop;
12963 triangle **regiontri;
12964 struct osub neighborsubseg;
12965 vertex regionorg, regiondest, regionapex;
12966 triangle ptr;
12967 subseg sptr;
12968
12969 if (b->verbose > 1) {
12970 printf(" Marking neighbors of marked triangles.\n");
12971 }
12972
12973
12974
12975 traversalinit(&m->viri);
12976 virusloop = (triangle **) traverse(&m->viri);
12977 while (virusloop != (triangle **) NULL) {
12978 testtri.tri = *virusloop;
12979
12980
12981
12982
12983 uninfect(testtri);
12984 if (b->regionattrib) {
12985
12986 setelemattribute(testtri, m->eextras, attribute);
12987 }
12988 if (b->vararea) {
12989
12990 setareabound(testtri, area);
12991 }
12992 if (b->verbose > 2) {
12993
12994
12995 testtri.orient = 0;
12996 org(testtri, regionorg);
12997 dest(testtri, regiondest);
12998 apex(testtri, regionapex);
12999 printf(" Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13000 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
13001 regionapex[0], regionapex[1]);
13002 }
13003
13004 for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
13005
13006 sym(testtri, neighbor);
13007
13008 tspivot(testtri, neighborsubseg);
13009
13010
13011 if ((neighbor.tri != m->dummytri) && !infected(neighbor)
13012 && (neighborsubseg.ss == m->dummysub)) {
13013 if (b->verbose > 2) {
13014 org(neighbor, regionorg);
13015 dest(neighbor, regiondest);
13016 apex(neighbor, regionapex);
13017 printf(" Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13018 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
13019 regionapex[0], regionapex[1]);
13020 }
13021
13022 infect(neighbor);
13023
13024 regiontri = (triangle **) poolalloc(&m->viri);
13025 *regiontri = neighbor.tri;
13026 }
13027 }
13028
13029
13030 infect(testtri);
13031 virusloop = (triangle **) traverse(&m->viri);
13032 }
13033
13034
13035 if (b->verbose > 1) {
13036 printf(" Unmarking marked triangles.\n");
13037 }
13038 traversalinit(&m->viri);
13039 virusloop = (triangle **) traverse(&m->viri);
13040 while (virusloop != (triangle **) NULL) {
13041 testtri.tri = *virusloop;
13042 uninfect(testtri);
13043 virusloop = (triangle **) traverse(&m->viri);
13044 }
13045
13046 poolrestart(&m->viri);
13047 }
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061 #ifdef ANSI_DECLARATORS
13062 void carveholes(struct mesh *m, struct behavior *b, REAL *holelist, int holes,
13063 REAL *regionlist, int regions)
13064 #else
13065 void carveholes(m, b, holelist, holes, regionlist, regions)
13066 struct mesh *m;
13067 struct behavior *b;
13068 REAL *holelist;
13069 int holes;
13070 REAL *regionlist;
13071 int regions;
13072 #endif
13073
13074 {
13075 struct otri searchtri;
13076 struct otri triangleloop;
13077 struct otri *regiontris;
13078 triangle **holetri;
13079 triangle **regiontri;
13080 vertex searchorg, searchdest;
13081 enum locateresult intersect;
13082 int i;
13083 triangle ptr;
13084
13085 if (!(b->quiet || (b->noholes && b->convex))) {
13086 printf("Removing unwanted triangles.\n");
13087 if (b->verbose && (holes > 0)) {
13088 printf(" Marking holes for elimination.\n");
13089 }
13090 }
13091
13092 if (regions > 0) {
13093
13094 regiontris = (struct otri *) trimalloc(regions *
13095 (int) sizeof(struct otri));
13096 } else {
13097 regiontris = (struct otri *) NULL;
13098 }
13099
13100 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13101
13102
13103 poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
13104 }
13105
13106 if (!b->convex) {
13107
13108
13109 infecthull(m, b);
13110 }
13111
13112 if ((holes > 0) && !b->noholes) {
13113
13114 for (i = 0; i < 2 * holes; i += 2) {
13115
13116 if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax)
13117 && (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax)) {
13118
13119 searchtri.tri = m->dummytri;
13120 searchtri.orient = 0;
13121 symself(searchtri);
13122
13123
13124
13125 org(searchtri, searchorg);
13126 dest(searchtri, searchdest);
13127 if (counterclockwise(m, b, searchorg, searchdest, &holelist[i]) >
13128 0.0) {
13129
13130 intersect = locate(m, b, &holelist[i], &searchtri);
13131 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13132
13133
13134 infect(searchtri);
13135 holetri = (triangle **) poolalloc(&m->viri);
13136 *holetri = searchtri.tri;
13137 }
13138 }
13139 }
13140 }
13141 }
13142
13143
13144
13145
13146
13147
13148
13149 if (regions > 0) {
13150
13151 for (i = 0; i < regions; i++) {
13152 regiontris[i].tri = m->dummytri;
13153
13154 if ((regionlist[4 * i] >= m->xmin) && (regionlist[4 * i] <= m->xmax) &&
13155 (regionlist[4 * i + 1] >= m->ymin) &&
13156 (regionlist[4 * i + 1] <= m->ymax)) {
13157
13158 searchtri.tri = m->dummytri;
13159 searchtri.orient = 0;
13160 symself(searchtri);
13161
13162
13163
13164 org(searchtri, searchorg);
13165 dest(searchtri, searchdest);
13166 if (counterclockwise(m, b, searchorg, searchdest, ®ionlist[4 * i]) >
13167 0.0) {
13168
13169 intersect = locate(m, b, ®ionlist[4 * i], &searchtri);
13170 if ((intersect != OUTSIDE) && (!infected(searchtri))) {
13171
13172
13173 otricopy(searchtri, regiontris[i]);
13174 }
13175 }
13176 }
13177 }
13178 }
13179
13180 if (m->viri.items > 0) {
13181
13182 plague(m, b);
13183 }
13184
13185
13186 if (regions > 0) {
13187 if (!b->quiet) {
13188 if (b->regionattrib) {
13189 if (b->vararea) {
13190 printf("Spreading regional attributes and area constraints.\n");
13191 } else {
13192 printf("Spreading regional attributes.\n");
13193 }
13194 } else {
13195 printf("Spreading regional area constraints.\n");
13196 }
13197 }
13198 if (b->regionattrib && !b->refine) {
13199
13200 traversalinit(&m->triangles);
13201 triangleloop.orient = 0;
13202 triangleloop.tri = triangletraverse(m);
13203 while (triangleloop.tri != (triangle *) NULL) {
13204 setelemattribute(triangleloop, m->eextras, 0.0);
13205 triangleloop.tri = triangletraverse(m);
13206 }
13207 }
13208 for (i = 0; i < regions; i++) {
13209 if (regiontris[i].tri != m->dummytri) {
13210
13211
13212 if (!deadtri(regiontris[i].tri)) {
13213
13214 infect(regiontris[i]);
13215 regiontri = (triangle **) poolalloc(&m->viri);
13216 *regiontri = regiontris[i].tri;
13217
13218 regionplague(m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
13219
13220 }
13221 }
13222 }
13223 if (b->regionattrib && !b->refine) {
13224
13225 m->eextras++;
13226 }
13227 }
13228
13229
13230 if (((holes > 0) && !b->noholes) || !b->convex || (regions > 0)) {
13231 pooldeinit(&m->viri);
13232 }
13233 if (regions > 0) {
13234 trifree((VOID *) regiontris);
13235 }
13236 }
13237
13240
13241
13242
13246
13247
13248
13249
13250
13251
13252
13253 #ifndef CDT_ONLY
13254
13255 #ifdef ANSI_DECLARATORS
13256 void tallyencs(struct mesh *m, struct behavior *b)
13257 #else
13258 void tallyencs(m, b)
13259 struct mesh *m;
13260 struct behavior *b;
13261 #endif
13262
13263 {
13264 struct osub subsegloop;
13265
13266
13267 traversalinit(&m->subsegs);
13268 subsegloop.ssorient = 0;
13269 subsegloop.ss = subsegtraverse(m);
13270 while (subsegloop.ss != (subseg *) NULL) {
13271
13272
13273 checkseg4encroach(m, b, &subsegloop);
13274 subsegloop.ss = subsegtraverse(m);
13275 }
13276 }
13277
13278 #endif
13279
13280
13281
13282
13283
13284
13285
13286 #ifndef CDT_ONLY
13287
13288 void precisionerror()
13289 {
13290 printf("Try increasing the area criterion and/or reducing the minimum\n");
13291 printf(" allowable angle so that tiny triangles are not created.\n");
13292 #ifdef SINGLE
13293 printf("Alternatively, try recompiling me with double precision\n");
13294 printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
13295 printf(" source file or \"-DSINGLE\" from the makefile).\n");
13296 #endif
13297 }
13298
13299 #endif
13300
13301
13302
13303
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314
13315 #ifndef CDT_ONLY
13316
13317 #ifdef ANSI_DECLARATORS
13318 void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
13319 #else
13320 void splitencsegs(m, b, triflaws)
13321 struct mesh *m;
13322 struct behavior *b;
13323 int triflaws;
13324 #endif
13325
13326 {
13327 struct otri enctri;
13328 struct otri testtri;
13329 struct osub testsh;
13330 struct osub currentenc;
13331 struct badsubseg *encloop;
13332 vertex eorg, edest, eapex;
13333 vertex newvertex;
13334 enum insertvertexresult success;
13335 REAL segmentlength, nearestpoweroftwo;
13336 REAL split;
13337 REAL multiplier, divisor;
13338 int acuteorg, acuteorg2, acutedest, acutedest2;
13339
13340 int i;
13341 triangle ptr;
13342 subseg sptr;
13343
13344
13345
13346 while ((m->badsubsegs.items > 0) && (m->steinerleft != 0)) {
13347 traversalinit(&m->badsubsegs);
13348 encloop = badsubsegtraverse(m);
13349 while ((encloop != (struct badsubseg *) NULL) && (m->steinerleft != 0)) {
13350 sdecode(encloop->encsubseg, currentenc);
13351 sorg(currentenc, eorg);
13352 sdest(currentenc, edest);
13353
13354
13355
13356
13357 if (!deadsubseg(currentenc.ss) &&
13358 (eorg == encloop->subsegorg) && (edest == encloop->subsegdest)) {
13359
13360
13361
13362
13363
13364
13365
13366
13367
13368
13369
13370
13371
13372
13373
13374
13375 stpivot(currentenc, enctri);
13376 lnext(enctri, testtri);
13377 tspivot(testtri, testsh);
13378 acuteorg = testsh.ss != m->dummysub;
13379
13380 lnextself(testtri);
13381 tspivot(testtri, testsh);
13382 acutedest = testsh.ss != m->dummysub;
13383
13384
13385
13386
13387 if (!b->conformdel && !acuteorg && !acutedest) {
13388 apex(enctri, eapex);
13389 while ((vertextype(eapex) == FREEVERTEX) &&
13390 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13391 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13392 deletevertex(m, b, &testtri);
13393 stpivot(currentenc, enctri);
13394 apex(enctri, eapex);
13395 lprev(enctri, testtri);
13396 }
13397 }
13398
13399
13400
13401 sym(enctri, testtri);
13402 if (testtri.tri != m->dummytri) {
13403
13404 lnextself(testtri);
13405 tspivot(testtri, testsh);
13406 acutedest2 = testsh.ss != m->dummysub;
13407 acutedest = acutedest || acutedest2;
13408
13409 lnextself(testtri);
13410 tspivot(testtri, testsh);
13411 acuteorg2 = testsh.ss != m->dummysub;
13412 acuteorg = acuteorg || acuteorg2;
13413
13414
13415 if (!b->conformdel && !acuteorg2 && !acutedest2) {
13416 org(testtri, eapex);
13417 while ((vertextype(eapex) == FREEVERTEX) &&
13418 ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
13419 (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) < 0.0)) {
13420 deletevertex(m, b, &testtri);
13421 sym(enctri, testtri);
13422 apex(testtri, eapex);
13423 lprevself(testtri);
13424 }
13425 }
13426 }
13427
13428
13429
13430 if (acuteorg || acutedest) {
13431 segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
13432 (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
13433
13434
13435 nearestpoweroftwo = 1.0;
13436 while (segmentlength > 3.0 * nearestpoweroftwo) {
13437 nearestpoweroftwo *= 2.0;
13438 }
13439 while (segmentlength < 1.5 * nearestpoweroftwo) {
13440 nearestpoweroftwo *= 0.5;
13441 }
13442
13443 split = nearestpoweroftwo / segmentlength;
13444 if (acutedest) {
13445 split = 1.0 - split;
13446 }
13447 } else {
13448
13449
13450 split = 0.5;
13451 }
13452
13453
13454 newvertex = (vertex) poolalloc(&m->vertices);
13455
13456 for (i = 0; i < 2 + m->nextras; i++) {
13457 newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
13458 }
13459
13460 if (!b->noexact) {
13461
13462
13463
13464 multiplier = counterclockwise(m, b, eorg, edest, newvertex);
13465 divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
13466 (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
13467 if ((multiplier != 0.0) && (divisor != 0.0)) {
13468 multiplier = multiplier / divisor;
13469
13470 if (multiplier == multiplier) {
13471 newvertex[0] += multiplier * (edest[1] - eorg[1]);
13472 newvertex[1] += multiplier * (eorg[0] - edest[0]);
13473 }
13474 }
13475 }
13476
13477 setvertexmark(newvertex, mark(currentenc));
13478 setvertextype(newvertex, SEGMENTVERTEX);
13479 if (b->verbose > 1) {
13480 printf(
13481 " Splitting subsegment (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
13482 eorg[0], eorg[1], edest[0], edest[1],
13483 newvertex[0], newvertex[1]);
13484 }
13485
13486 if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
13487 ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1]))) {
13488 printf("Error: Ran out of precision at (%.12g, %.12g).\n",
13489 newvertex[0], newvertex[1]);
13490 printf("I attempted to split a segment to a smaller size than\n");
13491 printf(" can be accommodated by the finite precision of\n");
13492 printf(" floating point arithmetic.\n");
13493 precisionerror();
13494 triexit(1);
13495 }
13496
13497 success = insertvertex(m, b, newvertex, &enctri, ¤tenc,
13498 1, triflaws);
13499 if ((success != SUCCESSFULVERTEX) && (success != ENCROACHINGVERTEX)) {
13500 printf("Internal error in splitencsegs():\n");
13501 printf(" Failure to split a segment.\n");
13502 internalerror();
13503 }
13504 if (m->steinerleft > 0) {
13505 m->steinerleft--;
13506 }
13507
13508
13509 checkseg4encroach(m, b, ¤tenc);
13510 snextself(currentenc);
13511
13512 checkseg4encroach(m, b, ¤tenc);
13513 }
13514
13515 badsubsegdealloc(m, encloop);
13516 encloop = badsubsegtraverse(m);
13517 }
13518 }
13519 }
13520
13521 #endif
13522
13523
13524
13525
13526
13527
13528
13529 #ifndef CDT_ONLY
13530
13531 #ifdef ANSI_DECLARATORS
13532 void tallyfaces(struct mesh *m, struct behavior *b)
13533 #else
13534 void tallyfaces(m, b)
13535 struct mesh *m;
13536 struct behavior *b;
13537 #endif
13538
13539 {
13540 struct otri triangleloop;
13541
13542 if (b->verbose) {
13543 printf(" Making a list of bad triangles.\n");
13544 }
13545 traversalinit(&m->triangles);
13546 triangleloop.orient = 0;
13547 triangleloop.tri = triangletraverse(m);
13548 while (triangleloop.tri != (triangle *) NULL) {
13549
13550 testtriangle(m, b, &triangleloop);
13551 triangleloop.tri = triangletraverse(m);
13552 }
13553 }
13554
13555 #endif
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565 #ifndef CDT_ONLY
13566
13567 #ifdef ANSI_DECLARATORS
13568 void splittriangle(struct mesh *m, struct behavior *b,
13569 struct badtriang *badtri)
13570 #else
13571 void splittriangle(m, b, badtri)
13572 struct mesh *m;
13573 struct behavior *b;
13574 struct badtriang *badtri;
13575 #endif
13576
13577 {
13578 struct otri badotri;
13579 vertex borg, bdest, bapex;
13580 vertex newvertex;
13581 REAL xi, eta;
13582 enum insertvertexresult success;
13583 int errorflag;
13584 int i;
13585
13586 decode(badtri->poortri, badotri);
13587 org(badotri, borg);
13588 dest(badotri, bdest);
13589 apex(badotri, bapex);
13590
13591
13592
13593 if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
13594 (bdest == badtri->triangdest) && (bapex == badtri->triangapex)) {
13595 if (b->verbose > 1) {
13596 printf(" Splitting this triangle at its circumcenter:\n");
13597 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
13598 borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13599 }
13600
13601 errorflag = 0;
13602
13603 newvertex = (vertex) poolalloc(&m->vertices);
13604 findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
13605
13606
13607 if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
13608 ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
13609 ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1]))) {
13610 if (!b->quiet) {
13611 printf(
13612 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13613 newvertex[0], newvertex[1]);
13614 errorflag = 1;
13615 }
13616 vertexdealloc(m, newvertex);
13617 } else {
13618 for (i = 2; i < 2 + m->nextras; i++) {
13619
13620 newvertex[i] = borg[i] + xi * (bdest[i] - borg[i])
13621 + eta * (bapex[i] - borg[i]);
13622 }
13623
13624
13625 setvertexmark(newvertex, 0);
13626 setvertextype(newvertex, FREEVERTEX);
13627
13628
13629
13630
13631
13632
13633
13634
13635 if (eta < xi) {
13636 lprevself(badotri);
13637 }
13638
13639
13640
13641 success = insertvertex(m, b, newvertex, &badotri, (struct osub *) NULL,
13642 1, 1);
13643 if (success == SUCCESSFULVERTEX) {
13644 if (m->steinerleft > 0) {
13645 m->steinerleft--;
13646 }
13647 } else if (success == ENCROACHINGVERTEX) {
13648
13649
13650 undovertex(m, b);
13651 if (b->verbose > 1) {
13652 printf(" Rejecting (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13653 }
13654 vertexdealloc(m, newvertex);
13655 } else if (success == VIOLATINGVERTEX) {
13656
13657
13658 vertexdealloc(m, newvertex);
13659 } else {
13660
13661 if (!b->quiet) {
13662 printf(
13663 "Warning: New vertex (%.12g, %.12g) falls on existing vertex.\n",
13664 newvertex[0], newvertex[1]);
13665 errorflag = 1;
13666 }
13667 vertexdealloc(m, newvertex);
13668 }
13669 }
13670 if (errorflag) {
13671 if (b->verbose) {
13672 printf(" The new vertex is at the circumcenter of triangle\n");
13673 printf(" (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
13674 borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
13675 }
13676 printf("This probably means that I am trying to refine triangles\n");
13677 printf(" to a smaller size than can be accommodated by the finite\n");
13678 printf(" precision of floating point arithmetic. (You can be\n");
13679 printf(" sure of this if I fail to terminate.)\n");
13680 precisionerror();
13681 }
13682 }
13683 }
13684
13685 #endif
13686
13687
13688
13689
13690
13691
13692
13693
13694 #ifndef CDT_ONLY
13695
13696 #ifdef ANSI_DECLARATORS
13697 void enforcequality(struct mesh *m, struct behavior *b)
13698 #else
13699 void enforcequality(m, b)
13700 struct mesh *m;
13701 struct behavior *b;
13702 #endif
13703
13704 {
13705 struct badtriang *badtri;
13706 int i;
13707
13708 if (!b->quiet) {
13709 printf("Adding Steiner points to enforce quality.\n");
13710 }
13711
13712 poolinit(&m->badsubsegs, sizeof(struct badsubseg), BADSUBSEGPERBLOCK,
13713 BADSUBSEGPERBLOCK, 0);
13714 if (b->verbose) {
13715 printf(" Looking for encroached subsegments.\n");
13716 }
13717
13718 tallyencs(m, b);
13719 if (b->verbose && (m->badsubsegs.items > 0)) {
13720 printf(" Splitting encroached subsegments.\n");
13721 }
13722
13723 splitencsegs(m, b, 0);
13724
13725
13726
13727
13728 if ((b->minangle > 0.0) || b->vararea || b->fixedarea || b->usertest) {
13729
13730 poolinit(&m->badtriangles, sizeof(struct badtriang), BADTRIPERBLOCK,
13731 BADTRIPERBLOCK, 0);
13732
13733 for (i = 0; i < 4096; i++) {
13734 m->queuefront[i] = (struct badtriang *) NULL;
13735 }
13736 m->firstnonemptyq = -1;
13737
13738 tallyfaces(m, b);
13739
13740 poolinit(&m->flipstackers, sizeof(struct flipstacker), FLIPSTACKERPERBLOCK,
13741 FLIPSTACKERPERBLOCK, 0);
13742 m->checkquality = 1;
13743 if (b->verbose) {
13744 printf(" Splitting bad triangles.\n");
13745 }
13746 while ((m->badtriangles.items > 0) && (m->steinerleft != 0)) {
13747
13748 badtri = dequeuebadtriang(m);
13749 splittriangle(m, b, badtri);
13750 if (m->badsubsegs.items > 0) {
13751
13752 enqueuebadtriang(m, b, badtri);
13753
13754
13755 splitencsegs(m, b, 1);
13756 } else {
13757
13758 pooldealloc(&m->badtriangles, (VOID *) badtri);
13759 }
13760 }
13761 }
13762
13763
13764
13765
13766
13767 if (!b->quiet && b->conformdel && (m->badsubsegs.items > 0) &&
13768 (m->steinerleft == 0)) {
13769 printf("\nWarning: I ran out of Steiner points, but the mesh has\n");
13770 if (m->badsubsegs.items == 1) {
13771 printf(" one encroached subsegment, and therefore might not be truly\n"
13772 );
13773 } else {
13774 printf(" %ld encroached subsegments, and therefore might not be truly\n"
13775 , m->badsubsegs.items);
13776 }
13777 printf(" Delaunay. If the Delaunay property is important to you,\n");
13778 printf(" try increasing the number of Steiner points (controlled by\n");
13779 printf(" the -S switch) slightly and try again.\n\n");
13780 }
13781 }
13782
13783 #endif
13784
13787
13788
13789
13790
13791
13792
13793
13794
13795 #ifdef ANSI_DECLARATORS
13796 void highorder(struct mesh *m, struct behavior *b)
13797 #else
13798 void highorder(m, b)
13799 struct mesh *m;
13800 struct behavior *b;
13801 #endif
13802
13803 {
13804 struct otri triangleloop, trisym;
13805 struct osub checkmark;
13806 vertex newvertex;
13807 vertex torg, tdest;
13808 int i;
13809 triangle ptr;
13810 subseg sptr;
13811
13812 if (!b->quiet) {
13813 printf("Adding vertices for second-order triangles.\n");
13814 }
13815
13816
13817
13818
13819
13820 m->vertices.deaditemstack = (VOID *) NULL;
13821
13822 traversalinit(&m->triangles);
13823 triangleloop.tri = triangletraverse(m);
13824
13825
13826
13827
13828
13829
13830 while (triangleloop.tri != (triangle *) NULL) {
13831 for (triangleloop.orient = 0; triangleloop.orient < 3;
13832 triangleloop.orient++) {
13833 sym(triangleloop, trisym);
13834 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
13835 org(triangleloop, torg);
13836 dest(triangleloop, tdest);
13837
13838
13839 newvertex = (vertex) poolalloc(&m->vertices);
13840 for (i = 0; i < 2 + m->nextras; i++) {
13841 newvertex[i] = 0.5 * (torg[i] + tdest[i]);
13842 }
13843
13844
13845 setvertexmark(newvertex, trisym.tri == m->dummytri);
13846 setvertextype(newvertex,
13847 trisym.tri == m->dummytri ? FREEVERTEX : SEGMENTVERTEX);
13848 if (b->usesegments) {
13849 tspivot(triangleloop, checkmark);
13850
13851 if (checkmark.ss != m->dummysub) {
13852 setvertexmark(newvertex, mark(checkmark));
13853 setvertextype(newvertex, SEGMENTVERTEX);
13854 }
13855 }
13856 if (b->verbose > 1) {
13857 printf(" Creating (%.12g, %.12g).\n", newvertex[0], newvertex[1]);
13858 }
13859
13860 triangleloop.tri[m->highorderindex + triangleloop.orient] =
13861 (triangle) newvertex;
13862 if (trisym.tri != m->dummytri) {
13863 trisym.tri[m->highorderindex + trisym.orient] = (triangle) newvertex;
13864 }
13865 }
13866 }
13867 triangleloop.tri = triangletraverse(m);
13868 }
13869 }
13870
13871
13875
13876
13877
13878
13879
13880
13881
13882
13883
13884 #ifndef TRILIBRARY
13885
13886 #ifdef ANSI_DECLARATORS
13887 char *readline(char *string, FILE *infile, char *infilename)
13888 #else
13889 char *readline(string, infile, infilename)
13890 char *string;
13891 FILE *infile;
13892 char *infilename;
13893 #endif
13894
13895 {
13896 char *result;
13897
13898
13899 do {
13900 result = fgets(string, INPUTLINESIZE, infile);
13901 if (result == (char *) NULL) {
13902 printf(" Error: Unexpected end of file in %s.\n", infilename);
13903 triexit(1);
13904 }
13905
13906
13907 while ((*result != '\0') && (*result != '#')
13908 && (*result != '.') && (*result != '+') && (*result != '-')
13909 && ((*result < '0') || (*result > '9'))) {
13910 result++;
13911 }
13912
13913 } while ((*result == '#') || (*result == '\0'));
13914 return result;
13915 }
13916
13917 #endif
13918
13919
13920
13921
13922
13923
13924
13925
13926
13927
13928 #ifndef TRILIBRARY
13929
13930 #ifdef ANSI_DECLARATORS
13931 char *findfield(char *string)
13932 #else
13933 char *findfield(string)
13934 char *string;
13935 #endif
13936
13937 {
13938 char *result;
13939
13940 result = string;
13941
13942 while ((*result != '\0') && (*result != '#')
13943 && (*result != ' ') && (*result != '\t')) {
13944 result++;
13945 }
13946
13947
13948 while ((*result != '\0') && (*result != '#')
13949 && (*result != '.') && (*result != '+') && (*result != '-')
13950 && ((*result < '0') || (*result > '9'))) {
13951 result++;
13952 }
13953
13954 if (*result == '#') {
13955 *result = '\0';
13956 }
13957 return result;
13958 }
13959
13960 #endif
13961
13962
13963
13964
13965
13966
13967
13968
13969 #ifndef TRILIBRARY
13970
13971 #ifdef ANSI_DECLARATORS
13972 void readnodes(struct mesh *m, struct behavior *b, char *nodefilename,
13973 char* polyfilename, FILE **polyfile)
13974 #else
13975 void readnodes(m, b, nodefilename, polyfilename, polyfile)
13976 struct mesh *m;
13977 struct behavior *b;
13978 char *nodefilename;
13979 char* polyfilename;
13980 FILE **polyfile;
13981 #endif
13982
13983 {
13984 FILE *infile;
13985 vertex vertexloop;
13986 char inputline[INPUTLINESIZE];
13987 char *stringptr;
13988 char *infilename;
13989 REAL x, y;
13990 int firstnode;
13991 int nodemarkers;
13992 int currentmarker;
13993 int i, j;
13994
13995 if (b->poly) {
13996
13997 if (!b->quiet) {
13998 printf("Opening %s.\n", polyfilename);
13999 }
14000 * polyfile = fopen(polyfilename, "r");
14001 if (*polyfile == (FILE *) NULL) {
14002 printf(" Error: Cannot access file %s.\n", polyfilename);
14003 triexit(1);
14004 }
14005
14006
14007 stringptr = readline(inputline,* polyfile, polyfilename);
14008 m->invertices = (int) strtol(stringptr, &stringptr, 0);
14009 stringptr = findfield(stringptr);
14010 if (*stringptr == '\0') {
14011 m->mesh_dim = 2;
14012 } else {
14013 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
14014 }
14015 stringptr = findfield(stringptr);
14016 if (*stringptr == '\0') {
14017 m->nextras = 0;
14018 } else {
14019 m->nextras = (int) strtol(stringptr, &stringptr, 0);
14020 }
14021 stringptr = findfield(stringptr);
14022 if (*stringptr == '\0') {
14023 nodemarkers = 0;
14024 } else {
14025 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
14026 }
14027 if (m->invertices > 0) {
14028 infile =* polyfile;
14029 infilename = polyfilename;
14030 m->readnodefile = 0;
14031 } else {
14032
14033
14034 m->readnodefile = 1;
14035 infilename = nodefilename;
14036 }
14037 } else {
14038 m->readnodefile = 1;
14039 infilename = nodefilename;
14040 * polyfile = (FILE *) NULL;
14041 }
14042
14043 if (m->readnodefile) {
14044
14045 if (!b->quiet) {
14046 printf("Opening %s.\n", nodefilename);
14047 }
14048 infile = fopen(nodefilename, "r");
14049 if (infile == (FILE *) NULL) {
14050 printf(" Error: Cannot access file %s.\n", nodefilename);
14051 triexit(1);
14052 }
14053
14054
14055 stringptr = readline(inputline, infile, nodefilename);
14056 m->invertices = (int) strtol(stringptr, &stringptr, 0);
14057 stringptr = findfield(stringptr);
14058 if (*stringptr == '\0') {
14059 m->mesh_dim = 2;
14060 } else {
14061 m->mesh_dim = (int) strtol(stringptr, &stringptr, 0);
14062 }
14063 stringptr = findfield(stringptr);
14064 if (*stringptr == '\0') {
14065 m->nextras = 0;
14066 } else {
14067 m->nextras = (int) strtol(stringptr, &stringptr, 0);
14068 }
14069 stringptr = findfield(stringptr);
14070 if (*stringptr == '\0') {
14071 nodemarkers = 0;
14072 } else {
14073 nodemarkers = (int) strtol(stringptr, &stringptr, 0);
14074 }
14075 }
14076
14077 if (m->invertices < 3) {
14078 printf("Error: Input must have at least three input vertices.\n");
14079 triexit(1);
14080 }
14081 if (m->mesh_dim != 2) {
14082 printf("Error: Triangle only works with two-dimensional meshes.\n");
14083 triexit(1);
14084 }
14085 if (m->nextras == 0) {
14086 b->weighted = 0;
14087 }
14088
14089 initializevertexpool(m, b);
14090
14091
14092 for (i = 0; i < m->invertices; i++) {
14093 vertexloop = (vertex) poolalloc(&m->vertices);
14094 stringptr = readline(inputline, infile, infilename);
14095 if (i == 0) {
14096 firstnode = (int) strtol(stringptr, &stringptr, 0);
14097 if ((firstnode == 0) || (firstnode == 1)) {
14098 b->firstnumber = firstnode;
14099 }
14100 }
14101 stringptr = findfield(stringptr);
14102 if (*stringptr == '\0') {
14103 printf("Error: Vertex %d has no x coordinate.\n", b->firstnumber + i);
14104 triexit(1);
14105 }
14106 x = (REAL) strtod(stringptr, &stringptr);
14107 stringptr = findfield(stringptr);
14108 if (*stringptr == '\0') {
14109 printf("Error: Vertex %d has no y coordinate.\n", b->firstnumber + i);
14110 triexit(1);
14111 }
14112 y = (REAL) strtod(stringptr, &stringptr);
14113 vertexloop[0] = x;
14114 vertexloop[1] = y;
14115
14116 for (j = 2; j < 2 + m->nextras; j++) {
14117 stringptr = findfield(stringptr);
14118 if (*stringptr == '\0') {
14119 vertexloop[j] = 0.0;
14120 } else {
14121 vertexloop[j] = (REAL) strtod(stringptr, &stringptr);
14122 }
14123 }
14124 if (nodemarkers) {
14125
14126 stringptr = findfield(stringptr);
14127 if (*stringptr == '\0') {
14128 setvertexmark(vertexloop, 0);
14129 } else {
14130 currentmarker = (int) strtol(stringptr, &stringptr, 0);
14131 setvertexmark(vertexloop, currentmarker);
14132 }
14133 } else {
14134
14135 setvertexmark(vertexloop, 0);
14136 }
14137 setvertextype(vertexloop, INPUTVERTEX);
14138
14139 if (i == 0) {
14140 m->xmin = m->xmax = x;
14141 m->ymin = m->ymax = y;
14142 } else {
14143 m->xmin = (x < m->xmin) ? x : m->xmin;
14144 m->xmax = (x > m->xmax) ? x : m->xmax;
14145 m->ymin = (y < m->ymin) ? y : m->ymin;
14146 m->ymax = (y > m->ymax) ? y : m->ymax;
14147 }
14148 }
14149 if (m->readnodefile) {
14150 fclose(infile);
14151 }
14152
14153
14154
14155 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14156 }
14157
14158 #endif
14159
14160
14161
14162
14163
14164
14165
14166 #ifdef TRILIBRARY
14167
14168 #ifdef ANSI_DECLARATORS
14169 void transfernodes(struct mesh *m, struct behavior *b, REAL* pointlist,
14170 REAL* pointattriblist, int* pointmarkerlist,
14171 int numberofpoints, int numberofpointattribs)
14172 #else
14173 void transfernodes(m, b, pointlist, pointattriblist, pointmarkerlist,
14174 numberofpoints, numberofpointattribs)
14175 struct mesh *m;
14176 struct behavior *b;
14177 REAL* pointlist;
14178 REAL* pointattriblist;
14179 int* pointmarkerlist;
14180 int numberofpoints;
14181 int numberofpointattribs;
14182 #endif
14183
14184 {
14185 vertex vertexloop;
14186 REAL x, y;
14187 int i, j;
14188 int coordindex;
14189 int attribindex;
14190
14191 m->invertices = numberofpoints;
14192 m->mesh_dim = 2;
14193 m->nextras = numberofpointattribs;
14194 m->readnodefile = 0;
14195 if (m->invertices < 3) {
14196 printf("Error: Input must have at least three input vertices.\n");
14197 triexit(1);
14198 }
14199 if (m->nextras == 0) {
14200 b->weighted = 0;
14201 }
14202
14203 initializevertexpool(m, b);
14204
14205
14206 coordindex = 0;
14207 attribindex = 0;
14208 for (i = 0; i < m->invertices; i++) {
14209 vertexloop = (vertex) poolalloc(&m->vertices);
14210
14211 x = vertexloop[0] = pointlist[coordindex++];
14212 y = vertexloop[1] = pointlist[coordindex++];
14213
14214 for (j = 0; j < numberofpointattribs; j++) {
14215 vertexloop[2 + j] = pointattriblist[attribindex++];
14216 }
14217 if (pointmarkerlist != (int *) NULL) {
14218
14219 setvertexmark(vertexloop, pointmarkerlist[i]);
14220 } else {
14221
14222 setvertexmark(vertexloop, 0);
14223 }
14224 setvertextype(vertexloop, INPUTVERTEX);
14225
14226 if (i == 0) {
14227 m->xmin = m->xmax = x;
14228 m->ymin = m->ymax = y;
14229 } else {
14230 m->xmin = (x < m->xmin) ? x : m->xmin;
14231 m->xmax = (x > m->xmax) ? x : m->xmax;
14232 m->ymin = (y < m->ymin) ? y : m->ymin;
14233 m->ymax = (y > m->ymax) ? y : m->ymax;
14234 }
14235 }
14236
14237
14238
14239 m->xminextreme = 10 * m->xmin - 9 * m->xmax;
14240 }
14241
14242 #endif
14243
14244
14245
14246
14247
14248
14249
14250
14251 #ifndef TRILIBRARY
14252
14253 #ifdef ANSI_DECLARATORS
14254 void readholes(struct mesh *m, struct behavior *b,
14255 FILE* polyfile, char* polyfilename, REAL **hlist, int *holes,
14256 REAL **rlist, int *regions)
14257 #else
14258 void readholes(m, b, polyfile, polyfilename, hlist, holes, rlist, regions)
14259 struct mesh *m;
14260 struct behavior *b;
14261 FILE* polyfile;
14262 char* polyfilename;
14263 REAL **hlist;
14264 int *holes;
14265 REAL **rlist;
14266 int *regions;
14267 #endif
14268
14269 {
14270 REAL *holelist;
14271 REAL *regionlist;
14272 char inputline[INPUTLINESIZE];
14273 char *stringptr;
14274 int index;
14275 int i;
14276
14277
14278 stringptr = readline(inputline, polyfile, polyfilename);
14279 *holes = (int) strtol(stringptr, &stringptr, 0);
14280 if (*holes > 0) {
14281 holelist = (REAL *) trimalloc(2 * *holes * (int) sizeof(REAL));
14282 *hlist = holelist;
14283 for (i = 0; i < 2 * *holes; i += 2) {
14284 stringptr = readline(inputline, polyfile, polyfilename);
14285 stringptr = findfield(stringptr);
14286 if (*stringptr == '\0') {
14287 printf("Error: Hole %d has no x coordinate.\n",
14288 b->firstnumber + (i >> 1));
14289 triexit(1);
14290 } else {
14291 holelist[i] = (REAL) strtod(stringptr, &stringptr);
14292 }
14293 stringptr = findfield(stringptr);
14294 if (*stringptr == '\0') {
14295 printf("Error: Hole %d has no y coordinate.\n",
14296 b->firstnumber + (i >> 1));
14297 triexit(1);
14298 } else {
14299 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
14300 }
14301 }
14302 } else {
14303 *hlist = (REAL *) NULL;
14304 }
14305
14306 #ifndef CDT_ONLY
14307 if ((b->regionattrib || b->vararea) && !b->refine) {
14308
14309 stringptr = readline(inputline, polyfile, polyfilename);
14310 *regions = (int) strtol(stringptr, &stringptr, 0);
14311 if (*regions > 0) {
14312 regionlist = (REAL *) trimalloc(4 * *regions * (int) sizeof(REAL));
14313 *rlist = regionlist;
14314 index = 0;
14315 for (i = 0; i < *regions; i++) {
14316 stringptr = readline(inputline, polyfile, polyfilename);
14317 stringptr = findfield(stringptr);
14318 if (*stringptr == '\0') {
14319 printf("Error: Region %d has no x coordinate.\n",
14320 b->firstnumber + i);
14321 triexit(1);
14322 } else {
14323 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14324 }
14325 stringptr = findfield(stringptr);
14326 if (*stringptr == '\0') {
14327 printf("Error: Region %d has no y coordinate.\n",
14328 b->firstnumber + i);
14329 triexit(1);
14330 } else {
14331 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14332 }
14333 stringptr = findfield(stringptr);
14334 if (*stringptr == '\0') {
14335 printf(
14336 "Error: Region %d has no region attribute or area constraint.\n",
14337 b->firstnumber + i);
14338 triexit(1);
14339 } else {
14340 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
14341 }
14342 stringptr = findfield(stringptr);
14343 if (*stringptr == '\0') {
14344 regionlist[index] = regionlist[index - 1];
14345 } else {
14346 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
14347 }
14348 index++;
14349 }
14350 }
14351 } else {
14352
14353 *regions = 0;
14354 *rlist = (REAL *) NULL;
14355 }
14356 #endif
14357
14358 fclose(polyfile);
14359 }
14360
14361 #endif
14362
14363
14364
14365
14366
14367
14368
14369
14370 #ifndef TRILIBRARY
14371
14372 #ifdef ANSI_DECLARATORS
14373 void finishfile(FILE *outfile, int argc, char **argv)
14374 #else
14375 void finishfile(outfile, argc, argv)
14376 FILE *outfile;
14377 int argc;
14378 char **argv;
14379 #endif
14380
14381 {
14382 int i;
14383
14384 fprintf(outfile, "# Generated by");
14385 for (i = 0; i < argc; i++) {
14386 fprintf(outfile, " ");
14387 fputs(argv[i], outfile);
14388 }
14389 fprintf(outfile, "\n");
14390 fclose(outfile);
14391 }
14392
14393 #endif
14394
14395
14396
14397
14398
14399
14400
14401
14402
14403
14404 #ifdef TRILIBRARY
14405
14406 #ifdef ANSI_DECLARATORS
14407 void writenodes(struct mesh *m, struct behavior *b, REAL **pointlist,
14408 REAL **pointattriblist, int **pointmarkerlist)
14409 #else
14410 void writenodes(m, b, pointlist, pointattriblist, pointmarkerlist)
14411 struct mesh *m;
14412 struct behavior *b;
14413 REAL **pointlist;
14414 REAL **pointattriblist;
14415 int **pointmarkerlist;
14416 #endif
14417
14418 #else
14419
14420 #ifdef ANSI_DECLARATORS
14421 void writenodes(struct mesh *m, struct behavior *b, char *nodefilename,
14422 int argc, char **argv)
14423 #else
14424 void writenodes(m, b, nodefilename, argc, argv)
14425 struct mesh *m;
14426 struct behavior *b;
14427 char *nodefilename;
14428 int argc;
14429 char **argv;
14430 #endif
14431
14432 #endif
14433
14434 {
14435 #ifdef TRILIBRARY
14436 REAL* plist;
14437 REAL* palist;
14438 int* pmlist;
14439 int coordindex;
14440 int attribindex;
14441 #else
14442 FILE *outfile;
14443 #endif
14444 vertex vertexloop;
14445 long outvertices;
14446 int vertexnumber;
14447 int i;
14448
14449 if (b->jettison) {
14450 outvertices = m->vertices.items - m->undeads;
14451 } else {
14452 outvertices = m->vertices.items;
14453 }
14454
14455 #ifdef TRILIBRARY
14456 if (!b->quiet) {
14457 printf("Writing vertices.\n");
14458 }
14459
14460 if (*pointlist == (REAL *) NULL) {
14461 * pointlist = (REAL *) trimalloc((int) (outvertices * 2 * sizeof(REAL)));
14462 }
14463
14464 if ((m->nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
14465 * pointattriblist = (REAL *) trimalloc((int) (outvertices * m->nextras *
14466 sizeof(REAL)));
14467 }
14468
14469 if (!b->nobound && (*pointmarkerlist == (int *) NULL)) {
14470 * pointmarkerlist = (int *) trimalloc((int) (outvertices * sizeof(int)));
14471 }
14472 plist =* pointlist;
14473 palist =* pointattriblist;
14474 pmlist =* pointmarkerlist;
14475 coordindex = 0;
14476 attribindex = 0;
14477 #else
14478 if (!b->quiet) {
14479 printf("Writing %s.\n", nodefilename);
14480 }
14481 outfile = fopen(nodefilename, "w");
14482 if (outfile == (FILE *) NULL) {
14483 printf(" Error: Cannot create file %s.\n", nodefilename);
14484 triexit(1);
14485 }
14486
14487
14488 fprintf(outfile, "%ld %d %d %d\n", outvertices, m->mesh_dim,
14489 m->nextras, 1 - b->nobound);
14490 #endif
14491
14492 traversalinit(&m->vertices);
14493 vertexnumber = b->firstnumber;
14494 vertexloop = vertextraverse(m);
14495 while (vertexloop != (vertex) NULL) {
14496 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14497 #ifdef TRILIBRARY
14498
14499 plist[coordindex++] = vertexloop[0];
14500 plist[coordindex++] = vertexloop[1];
14501
14502 for (i = 0; i < m->nextras; i++) {
14503 palist[attribindex++] = vertexloop[2 + i];
14504 }
14505 if (!b->nobound) {
14506
14507 pmlist[vertexnumber - b->firstnumber] = vertexmark(vertexloop);
14508 }
14509 #else
14510
14511 fprintf(outfile, "%4d %.17g %.17g", vertexnumber, vertexloop[0],
14512 vertexloop[1]);
14513 for (i = 0; i < m->nextras; i++) {
14514
14515 fprintf(outfile, " %.17g", vertexloop[i + 2]);
14516 }
14517 if (b->nobound) {
14518 fprintf(outfile, "\n");
14519 } else {
14520
14521 fprintf(outfile, " %d\n", vertexmark(vertexloop));
14522 }
14523 #endif
14524
14525 setvertexmark(vertexloop, vertexnumber);
14526 vertexnumber++;
14527 }
14528 vertexloop = vertextraverse(m);
14529 }
14530
14531 #ifndef TRILIBRARY
14532 finishfile(outfile, argc, argv);
14533 #endif
14534 }
14535
14536
14537
14538
14539
14540
14541
14542
14543
14544
14545
14546 #ifdef ANSI_DECLARATORS
14547 void numbernodes(struct mesh *m, struct behavior *b)
14548 #else
14549 void numbernodes(m, b)
14550 struct mesh *m;
14551 struct behavior *b;
14552 #endif
14553
14554 {
14555 vertex vertexloop;
14556 int vertexnumber;
14557
14558 traversalinit(&m->vertices);
14559 vertexnumber = b->firstnumber;
14560 vertexloop = vertextraverse(m);
14561 while (vertexloop != (vertex) NULL) {
14562 setvertexmark(vertexloop, vertexnumber);
14563 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
14564 vertexnumber++;
14565 }
14566 vertexloop = vertextraverse(m);
14567 }
14568 }
14569
14570
14571
14572
14573
14574
14575
14576 #ifdef TRILIBRARY
14577
14578 #ifdef ANSI_DECLARATORS
14579 void writeelements(struct mesh *m, struct behavior *b,
14580 int **trianglelist, REAL **triangleattriblist)
14581 #else
14582 void writeelements(m, b, trianglelist, triangleattriblist)
14583 struct mesh *m;
14584 struct behavior *b;
14585 int **trianglelist;
14586 REAL **triangleattriblist;
14587 #endif
14588
14589 #else
14590
14591 #ifdef ANSI_DECLARATORS
14592 void writeelements(struct mesh *m, struct behavior *b, char *elefilename,
14593 int argc, char **argv)
14594 #else
14595 void writeelements(m, b, elefilename, argc, argv)
14596 struct mesh *m;
14597 struct behavior *b;
14598 char *elefilename;
14599 int argc;
14600 char **argv;
14601 #endif
14602
14603 #endif
14604
14605 {
14606 #ifdef TRILIBRARY
14607 int *tlist;
14608 REAL *talist;
14609 int vertexindex;
14610 int attribindex;
14611 #else
14612 FILE *outfile;
14613 #endif
14614 struct otri triangleloop;
14615 vertex p1, p2, p3;
14616 vertex mid1, mid2, mid3;
14617 long elementnumber;
14618 int i;
14619
14620 #ifdef TRILIBRARY
14621 if (!b->quiet) {
14622 printf("Writing triangles.\n");
14623 }
14624
14625 if (*trianglelist == (int *) NULL) {
14626 *trianglelist = (int *) trimalloc((int) (m->triangles.items *
14627 ((b->order + 1) * (b->order + 2) /
14628 2) * sizeof(int)));
14629 }
14630
14631 if ((m->eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
14632 *triangleattriblist = (REAL *) trimalloc((int) (m->triangles.items *
14633 m->eextras *
14634 sizeof(REAL)));
14635 }
14636 tlist = *trianglelist;
14637 talist = *triangleattriblist;
14638 vertexindex = 0;
14639 attribindex = 0;
14640 #else
14641 if (!b->quiet) {
14642 printf("Writing %s.\n", elefilename);
14643 }
14644 outfile = fopen(elefilename, "w");
14645 if (outfile == (FILE *) NULL) {
14646 printf(" Error: Cannot create file %s.\n", elefilename);
14647 triexit(1);
14648 }
14649
14650 fprintf(outfile, "%ld %d %d\n", m->triangles.items,
14651 (b->order + 1) * (b->order + 2) / 2, m->eextras);
14652 #endif
14653
14654 traversalinit(&m->triangles);
14655 triangleloop.tri = triangletraverse(m);
14656 triangleloop.orient = 0;
14657 elementnumber = b->firstnumber;
14658 while (triangleloop.tri != (triangle *) NULL) {
14659 org(triangleloop, p1);
14660 dest(triangleloop, p2);
14661 apex(triangleloop, p3);
14662 if (b->order == 1) {
14663 #ifdef TRILIBRARY
14664 tlist[vertexindex++] = vertexmark(p1);
14665 tlist[vertexindex++] = vertexmark(p2);
14666 tlist[vertexindex++] = vertexmark(p3);
14667 #else
14668
14669 fprintf(outfile, "%4ld %4d %4d %4d", elementnumber,
14670 vertexmark(p1), vertexmark(p2), vertexmark(p3));
14671 #endif
14672 } else {
14673 mid1 = (vertex) triangleloop.tri[m->highorderindex + 1];
14674 mid2 = (vertex) triangleloop.tri[m->highorderindex + 2];
14675 mid3 = (vertex) triangleloop.tri[m->highorderindex];
14676 #ifdef TRILIBRARY
14677 tlist[vertexindex++] = vertexmark(p1);
14678 tlist[vertexindex++] = vertexmark(p2);
14679 tlist[vertexindex++] = vertexmark(p3);
14680 tlist[vertexindex++] = vertexmark(mid1);
14681 tlist[vertexindex++] = vertexmark(mid2);
14682 tlist[vertexindex++] = vertexmark(mid3);
14683 #else
14684
14685 fprintf(outfile, "%4ld %4d %4d %4d %4d %4d %4d", elementnumber,
14686 vertexmark(p1), vertexmark(p2), vertexmark(p3), vertexmark(mid1),
14687 vertexmark(mid2), vertexmark(mid3));
14688 #endif
14689 }
14690
14691 #ifdef TRILIBRARY
14692 for (i = 0; i < m->eextras; i++) {
14693 talist[attribindex++] = elemattribute(triangleloop, i);
14694 }
14695 #else
14696 for (i = 0; i < m->eextras; i++) {
14697 fprintf(outfile, " %.17g", elemattribute(triangleloop, i));
14698 }
14699 fprintf(outfile, "\n");
14700 #endif
14701
14702 triangleloop.tri = triangletraverse(m);
14703 elementnumber++;
14704 }
14705
14706 #ifndef TRILIBRARY
14707 finishfile(outfile, argc, argv);
14708 #endif
14709 }
14710
14711
14712
14713
14714
14715
14716
14717 #ifdef TRILIBRARY
14718
14719 #ifdef ANSI_DECLARATORS
14720 void writepoly(struct mesh *m, struct behavior *b,
14721 int **segmentlist, int **segmentmarkerlist)
14722 #else
14723 void writepoly(m, b, segmentlist, segmentmarkerlist)
14724 struct mesh *m;
14725 struct behavior *b;
14726 int **segmentlist;
14727 int **segmentmarkerlist;
14728 #endif
14729
14730 #else
14731
14732 #ifdef ANSI_DECLARATORS
14733 void writepoly(struct mesh *m, struct behavior *b, char* polyfilename,
14734 REAL *holelist, int holes, REAL *regionlist, int regions,
14735 int argc, char **argv)
14736 #else
14737 void writepoly(m, b, polyfilename, holelist, holes, regionlist, regions,
14738 argc, argv)
14739 struct mesh *m;
14740 struct behavior *b;
14741 char* polyfilename;
14742 REAL *holelist;
14743 int holes;
14744 REAL *regionlist;
14745 int regions;
14746 int argc;
14747 char **argv;
14748 #endif
14749
14750 #endif
14751
14752 {
14753 #ifdef TRILIBRARY
14754 int *slist;
14755 int *smlist;
14756 int index;
14757 #else
14758 FILE *outfile;
14759 long holenumber, regionnumber;
14760 #endif
14761 struct osub subsegloop;
14762 vertex endpoint1, endpoint2;
14763 long subsegnumber;
14764
14765 #ifdef TRILIBRARY
14766 if (!b->quiet) {
14767 printf("Writing segments.\n");
14768 }
14769
14770 if (*segmentlist == (int *) NULL) {
14771 *segmentlist = (int *) trimalloc((int) (m->subsegs.items * 2 *
14772 sizeof(int)));
14773 }
14774
14775 if (!b->nobound && (*segmentmarkerlist == (int *) NULL)) {
14776 *segmentmarkerlist = (int *) trimalloc((int) (m->subsegs.items *
14777 sizeof(int)));
14778 }
14779 slist = *segmentlist;
14780 smlist = *segmentmarkerlist;
14781 index = 0;
14782 #else
14783 if (!b->quiet) {
14784 printf("Writing %s.\n", polyfilename);
14785 }
14786 outfile = fopen(polyfilename, "w");
14787 if (outfile == (FILE *) NULL) {
14788 printf(" Error: Cannot create file %s.\n", polyfilename);
14789 triexit(1);
14790 }
14791
14792
14793
14794 fprintf(outfile, "%d %d %d %d\n", 0, m->mesh_dim, m->nextras,
14795 1 - b->nobound);
14796
14797 fprintf(outfile, "%ld %d\n", m->subsegs.items, 1 - b->nobound);
14798 #endif
14799
14800 traversalinit(&m->subsegs);
14801 subsegloop.ss = subsegtraverse(m);
14802 subsegloop.ssorient = 0;
14803 subsegnumber = b->firstnumber;
14804 while (subsegloop.ss != (subseg *) NULL) {
14805 sorg(subsegloop, endpoint1);
14806 sdest(subsegloop, endpoint2);
14807 #ifdef TRILIBRARY
14808
14809 slist[index++] = vertexmark(endpoint1);
14810 slist[index++] = vertexmark(endpoint2);
14811 if (!b->nobound) {
14812
14813 smlist[subsegnumber - b->firstnumber] = mark(subsegloop);
14814 }
14815 #else
14816
14817 if (b->nobound) {
14818 fprintf(outfile, "%4ld %4d %4d\n", subsegnumber,
14819 vertexmark(endpoint1), vertexmark(endpoint2));
14820 } else {
14821 fprintf(outfile, "%4ld %4d %4d %4d\n", subsegnumber,
14822 vertexmark(endpoint1), vertexmark(endpoint2), mark(subsegloop));
14823 }
14824 #endif
14825
14826 subsegloop.ss = subsegtraverse(m);
14827 subsegnumber++;
14828 }
14829
14830 #ifndef TRILIBRARY
14831 #ifndef CDT_ONLY
14832 fprintf(outfile, "%d\n", holes);
14833 if (holes > 0) {
14834 for (holenumber = 0; holenumber < holes; holenumber++) {
14835
14836 fprintf(outfile, "%4ld %.17g %.17g\n", b->firstnumber + holenumber,
14837 holelist[2 * holenumber], holelist[2 * holenumber + 1]);
14838 }
14839 }
14840 if (regions > 0) {
14841 fprintf(outfile, "%d\n", regions);
14842 for (regionnumber = 0; regionnumber < regions; regionnumber++) {
14843
14844 fprintf(outfile, "%4ld %.17g %.17g %.17g %.17g\n",
14845 b->firstnumber + regionnumber,
14846 regionlist[4 * regionnumber], regionlist[4 * regionnumber + 1],
14847 regionlist[4 * regionnumber + 2],
14848 regionlist[4 * regionnumber + 3]);
14849 }
14850 }
14851 #endif
14852
14853 finishfile(outfile, argc, argv);
14854 #endif
14855 }
14856
14857
14858
14859
14860
14861
14862
14863 #ifdef TRILIBRARY
14864
14865 #ifdef ANSI_DECLARATORS
14866 void writeedges(struct mesh *m, struct behavior *b,
14867 int **edgelist, int **edgemarkerlist)
14868 #else
14869 void writeedges(m, b, edgelist, edgemarkerlist)
14870 struct mesh *m;
14871 struct behavior *b;
14872 int **edgelist;
14873 int **edgemarkerlist;
14874 #endif
14875
14876 #else
14877
14878 #ifdef ANSI_DECLARATORS
14879 void writeedges(struct mesh *m, struct behavior *b, char *edgefilename,
14880 int argc, char **argv)
14881 #else
14882 void writeedges(m, b, edgefilename, argc, argv)
14883 struct mesh *m;
14884 struct behavior *b;
14885 char *edgefilename;
14886 int argc;
14887 char **argv;
14888 #endif
14889
14890 #endif
14891
14892 {
14893 #ifdef TRILIBRARY
14894 int *elist;
14895 int *emlist;
14896 int index;
14897 #else
14898 FILE *outfile;
14899 #endif
14900 struct otri triangleloop, trisym;
14901 struct osub checkmark;
14902 vertex p1, p2;
14903 long edgenumber;
14904 triangle ptr;
14905 subseg sptr;
14906
14907 #ifdef TRILIBRARY
14908 if (!b->quiet) {
14909 printf("Writing edges.\n");
14910 }
14911
14912 if (*edgelist == (int *) NULL) {
14913 *edgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
14914 }
14915
14916 if (!b->nobound && (*edgemarkerlist == (int *) NULL)) {
14917 *edgemarkerlist = (int *) trimalloc((int) (m->edges * sizeof(int)));
14918 }
14919 elist = *edgelist;
14920 emlist = *edgemarkerlist;
14921 index = 0;
14922 #else
14923 if (!b->quiet) {
14924 printf("Writing %s.\n", edgefilename);
14925 }
14926 outfile = fopen(edgefilename, "w");
14927 if (outfile == (FILE *) NULL) {
14928 printf(" Error: Cannot create file %s.\n", edgefilename);
14929 triexit(1);
14930 }
14931
14932 fprintf(outfile, "%ld %d\n", m->edges, 1 - b->nobound);
14933 #endif
14934
14935 traversalinit(&m->triangles);
14936 triangleloop.tri = triangletraverse(m);
14937 edgenumber = b->firstnumber;
14938
14939
14940
14941
14942
14943
14944 while (triangleloop.tri != (triangle *) NULL) {
14945 for (triangleloop.orient = 0; triangleloop.orient < 3;
14946 triangleloop.orient++) {
14947 sym(triangleloop, trisym);
14948 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
14949 org(triangleloop, p1);
14950 dest(triangleloop, p2);
14951 #ifdef TRILIBRARY
14952 elist[index++] = vertexmark(p1);
14953 elist[index++] = vertexmark(p2);
14954 #endif
14955 if (b->nobound) {
14956 #ifndef TRILIBRARY
14957
14958 fprintf(outfile, "%4ld %d %d\n", edgenumber,
14959 vertexmark(p1), vertexmark(p2));
14960 #endif
14961 } else {
14962
14963
14964 if (b->usesegments) {
14965 tspivot(triangleloop, checkmark);
14966 if (checkmark.ss == m->dummysub) {
14967 #ifdef TRILIBRARY
14968 emlist[edgenumber - b->firstnumber] = 0;
14969 #else
14970 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14971 vertexmark(p1), vertexmark(p2), 0);
14972 #endif
14973 } else {
14974 #ifdef TRILIBRARY
14975 emlist[edgenumber - b->firstnumber] = mark(checkmark);
14976 #else
14977 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14978 vertexmark(p1), vertexmark(p2), mark(checkmark));
14979 #endif
14980 }
14981 } else {
14982 #ifdef TRILIBRARY
14983 emlist[edgenumber - b->firstnumber] = trisym.tri == m->dummytri;
14984 #else
14985 fprintf(outfile, "%4ld %d %d %d\n", edgenumber,
14986 vertexmark(p1), vertexmark(p2), trisym.tri == m->dummytri);
14987 #endif
14988 }
14989 }
14990 edgenumber++;
14991 }
14992 }
14993 triangleloop.tri = triangletraverse(m);
14994 }
14995
14996 #ifndef TRILIBRARY
14997 finishfile(outfile, argc, argv);
14998 #endif
14999 }
15000
15001
15002
15003
15004
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017 #ifdef TRILIBRARY
15018
15019 #ifdef ANSI_DECLARATORS
15020 void writevoronoi(struct mesh *m, struct behavior *b, REAL **vpointlist,
15021 REAL **vpointattriblist, int **vpointmarkerlist,
15022 int **vedgelist, int **vedgemarkerlist, REAL **vnormlist)
15023 #else
15024 void writevoronoi(m, b, vpointlist, vpointattriblist, vpointmarkerlist,
15025 vedgelist, vedgemarkerlist, vnormlist)
15026 struct mesh *m;
15027 struct behavior *b;
15028 REAL **vpointlist;
15029 REAL **vpointattriblist;
15030 int **vpointmarkerlist;
15031 int **vedgelist;
15032 int **vedgemarkerlist;
15033 REAL **vnormlist;
15034 #endif
15035
15036 #else
15037
15038 #ifdef ANSI_DECLARATORS
15039 void writevoronoi(struct mesh *m, struct behavior *b, char *vnodefilename,
15040 char *vedgefilename, int argc, char **argv)
15041 #else
15042 void writevoronoi(m, b, vnodefilename, vedgefilename, argc, argv)
15043 struct mesh *m;
15044 struct behavior *b;
15045 char *vnodefilename;
15046 char *vedgefilename;
15047 int argc;
15048 char **argv;
15049 #endif
15050
15051 #endif
15052
15053 {
15054 #ifdef TRILIBRARY
15055 REAL* plist;
15056 REAL* palist;
15057 int *elist;
15058 REAL *normlist;
15059 int coordindex;
15060 int attribindex;
15061 #else
15062 FILE *outfile;
15063 #endif
15064 struct otri triangleloop, trisym;
15065 vertex torg, tdest, tapex;
15066 REAL circumcenter[2];
15067 REAL xi, eta;
15068 long vnodenumber, vedgenumber;
15069 int p1, p2;
15070 int i;
15071 triangle ptr;
15072
15073 #ifdef TRILIBRARY
15074 if (!b->quiet) {
15075 printf("Writing Voronoi vertices.\n");
15076 }
15077
15078 if (*vpointlist == (REAL *) NULL) {
15079 *vpointlist = (REAL *) trimalloc((int) (m->triangles.items * 2 *
15080 sizeof(REAL)));
15081 }
15082
15083 if (*vpointattriblist == (REAL *) NULL) {
15084 *vpointattriblist = (REAL *) trimalloc((int) (m->triangles.items *
15085 m->nextras * sizeof(REAL)));
15086 }
15087 *vpointmarkerlist = (int *) NULL;
15088 plist = *vpointlist;
15089 palist = *vpointattriblist;
15090 coordindex = 0;
15091 attribindex = 0;
15092 #else
15093 if (!b->quiet) {
15094 printf("Writing %s.\n", vnodefilename);
15095 }
15096 outfile = fopen(vnodefilename, "w");
15097 if (outfile == (FILE *) NULL) {
15098 printf(" Error: Cannot create file %s.\n", vnodefilename);
15099 triexit(1);
15100 }
15101
15102
15103 fprintf(outfile, "%ld %d %d %d\n", m->triangles.items, 2, m->nextras, 0);
15104 #endif
15105
15106 traversalinit(&m->triangles);
15107 triangleloop.tri = triangletraverse(m);
15108 triangleloop.orient = 0;
15109 vnodenumber = b->firstnumber;
15110 while (triangleloop.tri != (triangle *) NULL) {
15111 org(triangleloop, torg);
15112 dest(triangleloop, tdest);
15113 apex(triangleloop, tapex);
15114 findcircumcenter(m, b, torg, tdest, tapex, circumcenter, &xi, &eta, 0);
15115 #ifdef TRILIBRARY
15116
15117 plist[coordindex++] = circumcenter[0];
15118 plist[coordindex++] = circumcenter[1];
15119 for (i = 2; i < 2 + m->nextras; i++) {
15120
15121 palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
15122 + eta * (tapex[i] - torg[i]);
15123 }
15124 #else
15125
15126 fprintf(outfile, "%4ld %.17g %.17g", vnodenumber, circumcenter[0],
15127 circumcenter[1]);
15128 for (i = 2; i < 2 + m->nextras; i++) {
15129
15130 fprintf(outfile, " %.17g", torg[i] + xi * (tdest[i] - torg[i])
15131 + eta * (tapex[i] - torg[i]));
15132 }
15133 fprintf(outfile, "\n");
15134 #endif
15135
15136 * (int *) (triangleloop.tri + 6) = (int) vnodenumber;
15137 triangleloop.tri = triangletraverse(m);
15138 vnodenumber++;
15139 }
15140
15141 #ifndef TRILIBRARY
15142 finishfile(outfile, argc, argv);
15143 #endif
15144
15145 #ifdef TRILIBRARY
15146 if (!b->quiet) {
15147 printf("Writing Voronoi edges.\n");
15148 }
15149
15150 if (*vedgelist == (int *) NULL) {
15151 *vedgelist = (int *) trimalloc((int) (m->edges * 2 * sizeof(int)));
15152 }
15153 *vedgemarkerlist = (int *) NULL;
15154
15155 if (*vnormlist == (REAL *) NULL) {
15156 *vnormlist = (REAL *) trimalloc((int) (m->edges * 2 * sizeof(REAL)));
15157 }
15158 elist = *vedgelist;
15159 normlist = *vnormlist;
15160 coordindex = 0;
15161 #else
15162 if (!b->quiet) {
15163 printf("Writing %s.\n", vedgefilename);
15164 }
15165 outfile = fopen(vedgefilename, "w");
15166 if (outfile == (FILE *) NULL) {
15167 printf(" Error: Cannot create file %s.\n", vedgefilename);
15168 triexit(1);
15169 }
15170
15171 fprintf(outfile, "%ld %d\n", m->edges, 0);
15172 #endif
15173
15174 traversalinit(&m->triangles);
15175 triangleloop.tri = triangletraverse(m);
15176 vedgenumber = b->firstnumber;
15177
15178
15179
15180
15181
15182
15183 while (triangleloop.tri != (triangle *) NULL) {
15184 for (triangleloop.orient = 0; triangleloop.orient < 3;
15185 triangleloop.orient++) {
15186 sym(triangleloop, trisym);
15187 if ((triangleloop.tri < trisym.tri) || (trisym.tri == m->dummytri)) {
15188
15189 p1 = * (int *) (triangleloop.tri + 6);
15190 if (trisym.tri == m->dummytri) {
15191 org(triangleloop, torg);
15192 dest(triangleloop, tdest);
15193 #ifdef TRILIBRARY
15194
15195 elist[coordindex] = p1;
15196 normlist[coordindex++] = tdest[1] - torg[1];
15197 elist[coordindex] = -1;
15198 normlist[coordindex++] = torg[0] - tdest[0];
15199 #else
15200
15201
15202
15203 fprintf(outfile, "%4ld %d %d %.17g %.17g\n", vedgenumber,
15204 p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
15205 #endif
15206 } else {
15207
15208 p2 = * (int *) (trisym.tri + 6);
15209
15210 #ifdef TRILIBRARY
15211 elist[coordindex] = p1;
15212 normlist[coordindex++] = 0.0;
15213 elist[coordindex] = p2;
15214 normlist[coordindex++] = 0.0;
15215 #else
15216 fprintf(outfile, "%4ld %d %d\n", vedgenumber, p1, p2);
15217 #endif
15218 }
15219 vedgenumber++;
15220 }
15221 }
15222 triangleloop.tri = triangletraverse(m);
15223 }
15224
15225 #ifndef TRILIBRARY
15226 finishfile(outfile, argc, argv);
15227 #endif
15228 }
15229
15230 #ifdef TRILIBRARY
15231
15232 #ifdef ANSI_DECLARATORS
15233 void writeneighbors(struct mesh *m, struct behavior *b, int **neighborlist)
15234 #else
15235 void writeneighbors(m, b, neighborlist)
15236 struct mesh *m;
15237 struct behavior *b;
15238 int **neighborlist;
15239 #endif
15240
15241 #else
15242
15243 #ifdef ANSI_DECLARATORS
15244 void writeneighbors(struct mesh *m, struct behavior *b, char *neighborfilename,
15245 int argc, char **argv)
15246 #else
15247 void writeneighbors(m, b, neighborfilename, argc, argv)
15248 struct mesh *m;
15249 struct behavior *b;
15250 char *neighborfilename;
15251 int argc;
15252 char **argv;
15253 #endif
15254
15255 #endif
15256
15257 {
15258 #ifdef TRILIBRARY
15259 int *nlist;
15260 int index;
15261 #else
15262 FILE *outfile;
15263 #endif
15264 struct otri triangleloop, trisym;
15265 long elementnumber;
15266 int neighbor1, neighbor2, neighbor3;
15267 triangle ptr;
15268
15269 #ifdef TRILIBRARY
15270 if (!b->quiet) {
15271 printf("Writing neighbors.\n");
15272 }
15273
15274 if (*neighborlist == (int *) NULL) {
15275 *neighborlist = (int *) trimalloc((int) (m->triangles.items * 3 *
15276 sizeof(int)));
15277 }
15278 nlist = *neighborlist;
15279 index = 0;
15280 #else
15281 if (!b->quiet) {
15282 printf("Writing %s.\n", neighborfilename);
15283 }
15284 outfile = fopen(neighborfilename, "w");
15285 if (outfile == (FILE *) NULL) {
15286 printf(" Error: Cannot create file %s.\n", neighborfilename);
15287 triexit(1);
15288 }
15289
15290 fprintf(outfile, "%ld %d\n", m->triangles.items, 3);
15291 #endif
15292
15293 traversalinit(&m->triangles);
15294 triangleloop.tri = triangletraverse(m);
15295 triangleloop.orient = 0;
15296 elementnumber = b->firstnumber;
15297 while (triangleloop.tri != (triangle *) NULL) {
15298 * (int *) (triangleloop.tri + 6) = (int) elementnumber;
15299 triangleloop.tri = triangletraverse(m);
15300 elementnumber++;
15301 }
15302 * (int *) (m->dummytri + 6) = -1;
15303
15304 traversalinit(&m->triangles);
15305 triangleloop.tri = triangletraverse(m);
15306 elementnumber = b->firstnumber;
15307 while (triangleloop.tri != (triangle *) NULL) {
15308 triangleloop.orient = 1;
15309 sym(triangleloop, trisym);
15310 neighbor1 = * (int *) (trisym.tri + 6);
15311 triangleloop.orient = 2;
15312 sym(triangleloop, trisym);
15313 neighbor2 = * (int *) (trisym.tri + 6);
15314 triangleloop.orient = 0;
15315 sym(triangleloop, trisym);
15316 neighbor3 = * (int *) (trisym.tri + 6);
15317 #ifdef TRILIBRARY
15318 nlist[index++] = neighbor1;
15319 nlist[index++] = neighbor2;
15320 nlist[index++] = neighbor3;
15321 #else
15322
15323 fprintf(outfile, "%4ld %d %d %d\n", elementnumber,
15324 neighbor1, neighbor2, neighbor3);
15325 #endif
15326
15327 triangleloop.tri = triangletraverse(m);
15328 elementnumber++;
15329 }
15330
15331 #ifndef TRILIBRARY
15332 finishfile(outfile, argc, argv);
15333 #endif
15334 }
15335
15336
15337
15338
15339
15340
15341
15342
15343
15344
15345 #ifndef TRILIBRARY
15346
15347 #ifdef ANSI_DECLARATORS
15348 void writeoff(struct mesh *m, struct behavior *b, char *offfilename,
15349 int argc, char **argv)
15350 #else
15351 void writeoff(m, b, offfilename, argc, argv)
15352 struct mesh *m;
15353 struct behavior *b;
15354 char *offfilename;
15355 int argc;
15356 char **argv;
15357 #endif
15358
15359 {
15360 FILE *outfile;
15361 struct otri triangleloop;
15362 vertex vertexloop;
15363 vertex p1, p2, p3;
15364 long outvertices;
15365
15366 if (!b->quiet) {
15367 printf("Writing %s.\n", offfilename);
15368 }
15369
15370 if (b->jettison) {
15371 outvertices = m->vertices.items - m->undeads;
15372 } else {
15373 outvertices = m->vertices.items;
15374 }
15375
15376 outfile = fopen(offfilename, "w");
15377 if (outfile == (FILE *) NULL) {
15378 printf(" Error: Cannot create file %s.\n", offfilename);
15379 triexit(1);
15380 }
15381
15382 fprintf(outfile, "OFF\n%ld %ld %ld\n", outvertices, m->triangles.items,
15383 m->edges);
15384
15385
15386 traversalinit(&m->vertices);
15387 vertexloop = vertextraverse(m);
15388 while (vertexloop != (vertex) NULL) {
15389 if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX)) {
15390
15391 fprintf(outfile, " %.17g %.17g %.17g\n", vertexloop[0], vertexloop[1],
15392 0.0);
15393 }
15394 vertexloop = vertextraverse(m);
15395 }
15396
15397
15398 traversalinit(&m->triangles);
15399 triangleloop.tri = triangletraverse(m);
15400 triangleloop.orient = 0;
15401 while (triangleloop.tri != (triangle *) NULL) {
15402 org(triangleloop, p1);
15403 dest(triangleloop, p2);
15404 apex(triangleloop, p3);
15405
15406 fprintf(outfile, " 3 %4d %4d %4d\n", vertexmark(p1) - b->firstnumber,
15407 vertexmark(p2) - b->firstnumber, vertexmark(p3) - b->firstnumber);
15408 triangleloop.tri = triangletraverse(m);
15409 }
15410 finishfile(outfile, argc, argv);
15411 }
15412
15413 #endif
15414
15417
15418
15419
15420
15421
15422
15423
15424
15425 #ifdef ANSI_DECLARATORS
15426 void quality_statistics(struct mesh *m, struct behavior *b)
15427 #else
15428 void quality_statistics(m, b)
15429 struct mesh *m;
15430 struct behavior *b;
15431 #endif
15432
15433 {
15434 struct otri triangleloop;
15435 vertex p[3];
15436 REAL cossquaretable[8];
15437 REAL ratiotable[16];
15438 REAL dx[3], dy[3];
15439 REAL edgelength[3];
15440 REAL dotproduct;
15441 REAL cossquare;
15442 REAL triarea;
15443 REAL shortest, longest;
15444 REAL trilongest2;
15445 REAL smallestarea, biggestarea;
15446 REAL triminaltitude2;
15447 REAL minaltitude;
15448 REAL triaspect2;
15449 REAL worstaspect;
15450 REAL smallestangle, biggestangle;
15451 REAL radconst, degconst;
15452 int angletable[18];
15453 int aspecttable[16];
15454 int aspectindex;
15455 int tendegree;
15456 int acutebiggest;
15457 int i, ii, j, k;
15458
15459 printf("Mesh quality statistics:\n\n");
15460 radconst = PI / 18.0;
15461 degconst = 180.0 / PI;
15462 for (i = 0; i < 8; i++) {
15463 cossquaretable[i] = cos(radconst * (REAL) (i + 1));
15464 cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
15465 }
15466 for (i = 0; i < 18; i++) {
15467 angletable[i] = 0;
15468 }
15469
15470 ratiotable[0] = 1.5; ratiotable[1] = 2.0;
15471 ratiotable[2] = 2.5; ratiotable[3] = 3.0;
15472 ratiotable[4] = 4.0; ratiotable[5] = 6.0;
15473 ratiotable[6] = 10.0; ratiotable[7] = 15.0;
15474 ratiotable[8] = 25.0; ratiotable[9] = 50.0;
15475 ratiotable[10] = 100.0; ratiotable[11] = 300.0;
15476 ratiotable[12] = 1000.0; ratiotable[13] = 10000.0;
15477 ratiotable[14] = 100000.0; ratiotable[15] = 0.0;
15478 for (i = 0; i < 16; i++) {
15479 aspecttable[i] = 0;
15480 }
15481
15482 worstaspect = 0.0;
15483 minaltitude = m->xmax - m->xmin + m->ymax - m->ymin;
15484 minaltitude = minaltitude * minaltitude;
15485 shortest = minaltitude;
15486 longest = 0.0;
15487 smallestarea = minaltitude;
15488 biggestarea = 0.0;
15489 worstaspect = 0.0;
15490 smallestangle = 0.0;
15491 biggestangle = 2.0;
15492 acutebiggest = 1;
15493
15494 traversalinit(&m->triangles);
15495 triangleloop.tri = triangletraverse(m);
15496 triangleloop.orient = 0;
15497 while (triangleloop.tri != (triangle *) NULL) {
15498 org(triangleloop, p[0]);
15499 dest(triangleloop, p[1]);
15500 apex(triangleloop, p[2]);
15501 trilongest2 = 0.0;
15502
15503 for (i = 0; i < 3; i++) {
15504 j = plus1mod3[i];
15505 k = minus1mod3[i];
15506 dx[i] = p[j][0] - p[k][0];
15507 dy[i] = p[j][1] - p[k][1];
15508 edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
15509 if (edgelength[i] > trilongest2) {
15510 trilongest2 = edgelength[i];
15511 }
15512 if (edgelength[i] > longest) {
15513 longest = edgelength[i];
15514 }
15515 if (edgelength[i] < shortest) {
15516 shortest = edgelength[i];
15517 }
15518 }
15519
15520 triarea = counterclockwise(m, b, p[0], p[1], p[2]);
15521 if (triarea < smallestarea) {
15522 smallestarea = triarea;
15523 }
15524 if (triarea > biggestarea) {
15525 biggestarea = triarea;
15526 }
15527 triminaltitude2 = triarea * triarea / trilongest2;
15528 if (triminaltitude2 < minaltitude) {
15529 minaltitude = triminaltitude2;
15530 }
15531 triaspect2 = trilongest2 / triminaltitude2;
15532 if (triaspect2 > worstaspect) {
15533 worstaspect = triaspect2;
15534 }
15535 aspectindex = 0;
15536 while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
15537 && (aspectindex < 15)) {
15538 aspectindex++;
15539 }
15540 aspecttable[aspectindex]++;
15541
15542 for (i = 0; i < 3; i++) {
15543 j = plus1mod3[i];
15544 k = minus1mod3[i];
15545 dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
15546 cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
15547 tendegree = 8;
15548 for (ii = 7; ii >= 0; ii--) {
15549 if (cossquare > cossquaretable[ii]) {
15550 tendegree = ii;
15551 }
15552 }
15553 if (dotproduct <= 0.0) {
15554 angletable[tendegree]++;
15555 if (cossquare > smallestangle) {
15556 smallestangle = cossquare;
15557 }
15558 if (acutebiggest && (cossquare < biggestangle)) {
15559 biggestangle = cossquare;
15560 }
15561 } else {
15562 angletable[17 - tendegree]++;
15563 if (acutebiggest || (cossquare > biggestangle)) {
15564 biggestangle = cossquare;
15565 acutebiggest = 0;
15566 }
15567 }
15568 }
15569 triangleloop.tri = triangletraverse(m);
15570 }
15571
15572 shortest = sqrt(shortest);
15573 longest = sqrt(longest);
15574 minaltitude = sqrt(minaltitude);
15575 worstaspect = sqrt(worstaspect);
15576 smallestarea *= 0.5;
15577 biggestarea *= 0.5;
15578 if (smallestangle >= 1.0) {
15579 smallestangle = 0.0;
15580 } else {
15581 smallestangle = degconst * acos(sqrt(smallestangle));
15582 }
15583 if (biggestangle >= 1.0) {
15584 biggestangle = 180.0;
15585 } else {
15586 if (acutebiggest) {
15587 biggestangle = degconst * acos(sqrt(biggestangle));
15588 } else {
15589 biggestangle = 180.0 - degconst * acos(sqrt(biggestangle));
15590 }
15591 }
15592
15593 printf(" Smallest area: %16.5g | Largest area: %16.5g\n",
15594 smallestarea, biggestarea);
15595 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
15596 shortest, longest);
15597 printf(" Shortest altitude: %12.5g | Largest aspect ratio: %8.5g\n\n",
15598 minaltitude, worstaspect);
15599
15600 printf(" Triangle aspect ratio histogram:\n");
15601 printf(" 1.1547 - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15602 ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
15603 aspecttable[8]);
15604 for (i = 1; i < 7; i++) {
15605 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
15606 ratiotable[i - 1], ratiotable[i], aspecttable[i],
15607 ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
15608 }
15609 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
15610 ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
15611 aspecttable[15]);
15612 printf(" (Aspect ratio is longest edge divided by shortest altitude)\n\n");
15613
15614 printf(" Smallest angle: %15.5g | Largest angle: %15.5g\n\n",
15615 smallestangle, biggestangle);
15616
15617 printf(" Angle histogram:\n");
15618 for (i = 0; i < 9; i++) {
15619 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
15620 i * 10, i * 10 + 10, angletable[i],
15621 i * 10 + 90, i * 10 + 100, angletable[i + 9]);
15622 }
15623 printf("\n");
15624 }
15625
15626
15627
15628
15629
15630
15631
15632 #ifdef ANSI_DECLARATORS
15633 void statistics(struct mesh *m, struct behavior *b)
15634 #else
15635 void statistics(m, b)
15636 struct mesh *m;
15637 struct behavior *b;
15638 #endif
15639
15640 {
15641 printf("\nStatistics:\n\n");
15642 printf(" Input vertices: %d\n", m->invertices);
15643 if (b->refine) {
15644 printf(" Input triangles: %d\n", m->inelements);
15645 }
15646 if (b->poly) {
15647 printf(" Input segments: %d\n", m->insegments);
15648 if (!b->refine) {
15649 printf(" Input holes: %d\n", m->holes);
15650 }
15651 }
15652
15653 printf("\n Mesh vertices: %ld\n", m->vertices.items - m->undeads);
15654 printf(" Mesh triangles: %ld\n", m->triangles.items);
15655 printf(" Mesh edges: %ld\n", m->edges);
15656 printf(" Mesh exterior boundary edges: %ld\n", m->hullsize);
15657 if (b->poly || b->refine) {
15658 printf(" Mesh interior boundary edges: %ld\n",
15659 m->subsegs.items - m->hullsize);
15660 printf(" Mesh subsegments (constrained edges): %ld\n",
15661 m->subsegs.items);
15662 }
15663 printf("\n");
15664
15665 if (b->verbose) {
15666 quality_statistics(m, b);
15667 printf("Memory allocation statistics:\n\n");
15668 printf(" Maximum number of vertices: %ld\n", m->vertices.maxitems);
15669 printf(" Maximum number of triangles: %ld\n", m->triangles.maxitems);
15670 if (m->subsegs.maxitems > 0) {
15671 printf(" Maximum number of subsegments: %ld\n", m->subsegs.maxitems);
15672 }
15673 if (m->viri.maxitems > 0) {
15674 printf(" Maximum number of viri: %ld\n", m->viri.maxitems);
15675 }
15676 if (m->badsubsegs.maxitems > 0) {
15677 printf(" Maximum number of encroached subsegments: %ld\n",
15678 m->badsubsegs.maxitems);
15679 }
15680 if (m->badtriangles.maxitems > 0) {
15681 printf(" Maximum number of bad triangles: %ld\n",
15682 m->badtriangles.maxitems);
15683 }
15684 if (m->flipstackers.maxitems > 0) {
15685 printf(" Maximum number of stacked triangle flips: %ld\n",
15686 m->flipstackers.maxitems);
15687 }
15688 if (m->splaynodes.maxitems > 0) {
15689 printf(" Maximum number of splay tree nodes: %ld\n",
15690 m->splaynodes.maxitems);
15691 }
15692 printf(" Approximate heap memory use (bytes): %ld\n\n",
15693 m->vertices.maxitems * m->vertices.itembytes +
15694 m->triangles.maxitems * m->triangles.itembytes +
15695 m->subsegs.maxitems * m->subsegs.itembytes +
15696 m->viri.maxitems * m->viri.itembytes +
15697 m->badsubsegs.maxitems * m->badsubsegs.itembytes +
15698 m->badtriangles.maxitems * m->badtriangles.itembytes +
15699 m->flipstackers.maxitems * m->flipstackers.itembytes +
15700 m->splaynodes.maxitems * m->splaynodes.itembytes);
15701
15702 printf("Algorithmic statistics:\n\n");
15703 if (!b->weighted) {
15704 printf(" Number of incircle tests: %ld\n", m->incirclecount);
15705 } else {
15706 printf(" Number of 3D orientation tests: %ld\n", m->orient3dcount);
15707 }
15708 printf(" Number of 2D orientation tests: %ld\n", m->counterclockcount);
15709 if (m->hyperbolacount > 0) {
15710 printf(" Number of right-of-hyperbola tests: %ld\n",
15711 m->hyperbolacount);
15712 }
15713 if (m->circletopcount > 0) {
15714 printf(" Number of circle top computations: %ld\n",
15715 m->circletopcount);
15716 }
15717 if (m->circumcentercount > 0) {
15718 printf(" Number of triangle circumcenter computations: %ld\n",
15719 m->circumcentercount);
15720 }
15721 printf("\n");
15722 }
15723 }
15724
15725
15726
15727
15728
15729
15730
15731
15732
15733
15734
15735
15736
15737
15738
15739
15740
15741
15742
15743
15744
15745
15746
15747
15748
15749
15750 #ifdef TRILIBRARY
15751
15752 #ifdef ANSI_DECLARATORS
15753 void triangulate(char *triswitches, struct triangulateio *in,
15754 struct triangulateio *out, struct triangulateio *vorout)
15755 #else
15756 void triangulate(triswitches, in, out, vorout)
15757 char *triswitches;
15758 struct triangulateio *in;
15759 struct triangulateio *out;
15760 struct triangulateio *vorout;
15761 #endif
15762
15763 #else
15764
15765 #ifdef ANSI_DECLARATORS
15766 int main(int argc, char **argv)
15767 #else
15768 int main(argc, argv)
15769 int argc;
15770 char **argv;
15771 #endif
15772
15773 #endif
15774
15775 {
15776 struct mesh m;
15777 struct behavior b;
15778 REAL *holearray;
15779 REAL *regionarray;
15780 #ifndef TRILIBRARY
15781 FILE* polyfile;
15782 #endif
15783 #ifndef NO_TIMER
15784
15785
15786 struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
15787 struct timezone tz;
15788 #endif
15789
15790 #ifndef NO_TIMER
15791 gettimeofday(&tv0, &tz);
15792 #endif
15793
15794 triangleinit(&m);
15795 #ifdef TRILIBRARY
15796 parsecommandline(1, &triswitches, &b);
15797 #else
15798 parsecommandline(argc, argv, &b);
15799 #endif
15800 m.steinerleft = b.steiner;
15801
15802 #ifdef TRILIBRARY
15803 transfernodes(&m, &b, in->pointlist, in->pointattributelist,
15804 in->pointmarkerlist, in->numberofpoints,
15805 in->numberofpointattributes);
15806 #else
15807 readnodes(&m, &b, b.innodefilename, b.inpolyfilename, &polyfile);
15808 #endif
15809
15810 #ifndef NO_TIMER
15811 if (!b.quiet) {
15812 gettimeofday(&tv1, &tz);
15813 }
15814 #endif
15815
15816 #ifdef CDT_ONLY
15817 m.hullsize = delaunay(&m, &b);
15818 #else
15819 if (b.refine) {
15820
15821 #ifdef TRILIBRARY
15822 m.hullsize = reconstruct(&m, &b, in->trianglelist,
15823 in->triangleattributelist, in->trianglearealist,
15824 in->numberoftriangles, in->numberofcorners,
15825 in->numberoftriangleattributes,
15826 in->segmentlist, in->segmentmarkerlist,
15827 in->numberofsegments);
15828 #else
15829 m.hullsize = reconstruct(&m, &b, b.inelefilename, b.areafilename,
15830 b.inpolyfilename, polyfile);
15831 #endif
15832 } else {
15833 m.hullsize = delaunay(&m, &b);
15834 }
15835 #endif
15836
15837 #ifndef NO_TIMER
15838 if (!b.quiet) {
15839 gettimeofday(&tv2, &tz);
15840 if (b.refine) {
15841 printf("Mesh reconstruction");
15842 } else {
15843 printf("Delaunay");
15844 }
15845 printf(" milliseconds: %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec) +
15846 (tv2.tv_usec - tv1.tv_usec) / 1000l);
15847 }
15848 #endif
15849
15850
15851
15852 m.infvertex1 = (vertex) NULL;
15853 m.infvertex2 = (vertex) NULL;
15854 m.infvertex3 = (vertex) NULL;
15855
15856 if (b.usesegments) {
15857 m.checksegments = 1;
15858 if (!b.refine) {
15859
15860 #ifdef TRILIBRARY
15861 formskeleton(&m, &b, in->segmentlist,
15862 in->segmentmarkerlist, in->numberofsegments);
15863 #else
15864 formskeleton(&m, &b, polyfile, b.inpolyfilename);
15865 #endif
15866 }
15867 }
15868
15869 #ifndef NO_TIMER
15870 if (!b.quiet) {
15871 gettimeofday(&tv3, &tz);
15872 if (b.usesegments && !b.refine) {
15873 printf("Segment milliseconds: %ld\n",
15874 1000l * (tv3.tv_sec - tv2.tv_sec) +
15875 (tv3.tv_usec - tv2.tv_usec) / 1000l);
15876 }
15877 }
15878 #endif
15879
15880 if (b.poly && (m.triangles.items > 0)) {
15881 #ifdef TRILIBRARY
15882 holearray = in->holelist;
15883 m.holes = in->numberofholes;
15884 regionarray = in->regionlist;
15885 m.regions = in->numberofregions;
15886 #else
15887 readholes(&m, &b, polyfile, b.inpolyfilename, &holearray, &m.holes,
15888 ®ionarray, &m.regions);
15889 #endif
15890 if (!b.refine) {
15891
15892 carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
15893 }
15894 } else {
15895
15896
15897
15898 m.holes = 0;
15899 m.regions = 0;
15900 }
15901
15902 #ifndef NO_TIMER
15903 if (!b.quiet) {
15904 gettimeofday(&tv4, &tz);
15905 if (b.poly && !b.refine) {
15906 printf("Hole milliseconds: %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec) +
15907 (tv4.tv_usec - tv3.tv_usec) / 1000l);
15908 }
15909 }
15910 #endif
15911
15912 #ifndef CDT_ONLY
15913 if (b.quality && (m.triangles.items > 0)) {
15914 enforcequality(&m, &b);
15915 }
15916 #endif
15917
15918 #ifndef NO_TIMER
15919 if (!b.quiet) {
15920 gettimeofday(&tv5, &tz);
15921 #ifndef CDT_ONLY
15922 if (b.quality) {
15923 printf("Quality milliseconds: %ld\n",
15924 1000l * (tv5.tv_sec - tv4.tv_sec) +
15925 (tv5.tv_usec - tv4.tv_usec) / 1000l);
15926 }
15927 #endif
15928 }
15929 #endif
15930
15931
15932 m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
15933
15934 if (b.order > 1) {
15935 highorder(&m, &b);
15936 }
15937 if (!b.quiet) {
15938 printf("\n");
15939 }
15940
15941 #ifdef TRILIBRARY
15942 if (b.jettison) {
15943 out->numberofpoints = m.vertices.items - m.undeads;
15944 } else {
15945 out->numberofpoints = m.vertices.items;
15946 }
15947 out->numberofpointattributes = m.nextras;
15948 out->numberoftriangles = m.triangles.items;
15949 out->numberofcorners = (b.order + 1) * (b.order + 2) / 2;
15950 out->numberoftriangleattributes = m.eextras;
15951 out->numberofedges = m.edges;
15952 if (b.usesegments) {
15953 out->numberofsegments = m.subsegs.items;
15954 } else {
15955 out->numberofsegments = m.hullsize;
15956 }
15957 if (vorout != (struct triangulateio *) NULL) {
15958 vorout->numberofpoints = m.triangles.items;
15959 vorout->numberofpointattributes = m.nextras;
15960 vorout->numberofedges = m.edges;
15961 }
15962 #endif
15963
15964
15965 if (b.nonodewritten || (b.noiterationnum && m.readnodefile)) {
15966 if (!b.quiet) {
15967 #ifdef TRILIBRARY
15968 printf("NOT writing vertices.\n");
15969 #else
15970 printf("NOT writing a .node file.\n");
15971 #endif
15972 }
15973 numbernodes(&m, &b);
15974 } else {
15975
15976 #ifdef TRILIBRARY
15977 writenodes(&m, &b, &out->pointlist, &out->pointattributelist,
15978 &out->pointmarkerlist);
15979 #else
15980 writenodes(&m, &b, b.outnodefilename, argc, argv);
15981 #endif
15982 }
15983 if (b.noelewritten) {
15984 if (!b.quiet) {
15985 #ifdef TRILIBRARY
15986 printf("NOT writing triangles.\n");
15987 #else
15988 printf("NOT writing an .ele file.\n");
15989 #endif
15990 }
15991 } else {
15992 #ifdef TRILIBRARY
15993 writeelements(&m, &b, &out->trianglelist, &out->triangleattributelist);
15994 #else
15995 writeelements(&m, &b, b.outelefilename, argc, argv);
15996 #endif
15997 }
15998
15999
16000 if (b.poly || b.convex) {
16001
16002 if (b.nopolywritten || b.noiterationnum) {
16003 if (!b.quiet) {
16004 #ifdef TRILIBRARY
16005 printf("NOT writing segments.\n");
16006 #else
16007 printf("NOT writing a .poly file.\n");
16008 #endif
16009 }
16010 } else {
16011 #ifdef TRILIBRARY
16012 writepoly(&m, &b, &out->segmentlist, &out->segmentmarkerlist);
16013 out->numberofholes = m.holes;
16014 out->numberofregions = m.regions;
16015 if (b.poly) {
16016 out->holelist = in->holelist;
16017 out->regionlist = in->regionlist;
16018 } else {
16019 out->holelist = (REAL *) NULL;
16020 out->regionlist = (REAL *) NULL;
16021 }
16022 #else
16023 writepoly(&m, &b, b.outpolyfilename, holearray, m.holes, regionarray,
16024 m.regions, argc, argv);
16025 #endif
16026 }
16027 }
16028 #ifndef TRILIBRARY
16029 #ifndef CDT_ONLY
16030 if (m.regions > 0) {
16031 trifree((VOID *) regionarray);
16032 }
16033 #endif
16034 if (m.holes > 0) {
16035 trifree((VOID *) holearray);
16036 }
16037 if (b.geomview) {
16038 writeoff(&m, &b, b.offfilename, argc, argv);
16039 }
16040 #endif
16041 if (b.edgesout) {
16042 #ifdef TRILIBRARY
16043 writeedges(&m, &b, &out->edgelist, &out->edgemarkerlist);
16044 #else
16045 writeedges(&m, &b, b.edgefilename, argc, argv);
16046 #endif
16047 }
16048 if (b.voronoi) {
16049 #ifdef TRILIBRARY
16050 writevoronoi(&m, &b, &vorout->pointlist, &vorout->pointattributelist,
16051 &vorout->pointmarkerlist, &vorout->edgelist,
16052 &vorout->edgemarkerlist, &vorout->normlist);
16053 #else
16054 writevoronoi(&m, &b, b.vnodefilename, b.vedgefilename, argc, argv);
16055 #endif
16056 }
16057 if (b.neighbors) {
16058 #ifdef TRILIBRARY
16059 writeneighbors(&m, &b, &out->neighborlist);
16060 #else
16061 writeneighbors(&m, &b, b.neighborfilename, argc, argv);
16062 #endif
16063 }
16064
16065 if (!b.quiet) {
16066 #ifndef NO_TIMER
16067 gettimeofday(&tv6, &tz);
16068 printf("\nOutput milliseconds: %ld\n",
16069 1000l * (tv6.tv_sec - tv5.tv_sec) +
16070 (tv6.tv_usec - tv5.tv_usec) / 1000l);
16071 printf("Total running milliseconds: %ld\n",
16072 1000l * (tv6.tv_sec - tv0.tv_sec) +
16073 (tv6.tv_usec - tv0.tv_usec) / 1000l);
16074 #endif
16075
16076 statistics(&m, &b);
16077 }
16078
16079 #ifndef REDUCED
16080 if (b.docheck) {
16081 checkmesh(&m, &b);
16082 checkdelaunay(&m, &b);
16083 }
16084 #endif
16085
16086 triangledeinit(&m, &b);
16087 #ifndef TRILIBRARY
16088 return 0;
16089 #endif
16090 }