00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "triangulator.h"
00016 #include "randomizer.h"
00017
00018
00019
00020
00021
00022
00023 Triangulator::
00024 Triangulator() {
00025 }
00026
00027
00028
00029
00030
00031
00032
00033 void Triangulator::
00034 clear() {
00035 _vertices.clear();
00036 clear_polygon();
00037 }
00038
00039
00040
00041
00042
00043
00044
00045 int Triangulator::
00046 add_vertex(const LPoint2d &point) {
00047 int index = (int)_vertices.size();
00048 _vertices.push_back(point);
00049 return index;
00050 }
00051
00052
00053
00054
00055
00056
00057
00058 void Triangulator::
00059 clear_polygon() {
00060 _polygon.clear();
00061 _holes.clear();
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 void Triangulator::
00077 add_polygon_vertex(int index) {
00078 _polygon.push_back(index);
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 void Triangulator::
00088 begin_hole() {
00089 _holes.push_back(vector_int());
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 void Triangulator::
00104 add_hole_vertex(int index) {
00105 nassertv(!_holes.empty());
00106 _holes.back().push_back(index);
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 void Triangulator::
00118 triangulate() {
00119 _result.clear();
00120
00121
00122 cleanup_polygon_indices(_polygon);
00123 Holes::iterator hi;
00124 for (hi = _holes.begin(); hi != _holes.end(); ++hi) {
00125 cleanup_polygon_indices(*hi);
00126 }
00127
00128 if (_polygon.size() < 3) {
00129
00130 return;
00131 }
00132
00133
00134 seg.clear();
00135 seg.push_back(segment_t());
00136 make_segment(_polygon, true);
00137
00138 for (hi = _holes.begin(); hi != _holes.end(); ++hi) {
00139 if ((*hi).size() >= 3) {
00140 make_segment(*hi, false);
00141 }
00142 }
00143
00144
00145 int num_segments = (int)seg.size() - 1;
00146 permute.reserve(num_segments);
00147 int i;
00148 for (i = 0; i < num_segments; ++i) {
00149 permute.push_back(i + 1);
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 choose_idx = 0;
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 while (construct_trapezoids(num_segments) != 0) {
00178
00179 Randomizer randomizer;
00180 for (i = 0; i < num_segments; ++i) {
00181 int j = randomizer.random_int(num_segments);
00182 nassertv(j >= 0 && j < num_segments);
00183 int t = permute[i];
00184 permute[i] = permute[j];
00185 permute[j] = t;
00186 }
00187 choose_idx = 0;
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 int nmonpoly = monotonate_trapezoids(num_segments);
00211
00212
00213
00214 triangulate_monotone_polygons(num_segments, nmonpoly);
00215
00216
00217
00218
00219
00220
00221
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 int Triangulator::
00231 get_num_triangles() const {
00232 return _result.size();
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 int Triangulator::
00245 get_triangle_v0(int n) const {
00246 nassertr(n >= 0 && n < (int)_result.size(), -1);
00247 return _result[n]._v0;
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 int Triangulator::
00260 get_triangle_v1(int n) const {
00261 nassertr(n >= 0 && n < (int)_result.size(), -1);
00262 return _result[n]._v1;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 int Triangulator::
00275 get_triangle_v2(int n) const {
00276 nassertr(n >= 0 && n < (int)_result.size(), -1);
00277 return _result[n]._v2;
00278 }
00279
00280
00281
00282
00283
00284
00285 void Triangulator::
00286 cleanup_polygon_indices(vector_int &polygon) {
00287
00288 size_t pi = 0;
00289 while (pi < polygon.size()) {
00290 if (polygon[pi] >= 0 && polygon[pi] < _vertices.size()) {
00291
00292 ++pi;
00293 } else {
00294
00295 polygon.erase(_polygon.begin() + pi);
00296 }
00297 }
00298
00299
00300 pi = 1;
00301 while (pi < polygon.size()) {
00302 if (_vertices[polygon[pi]] != _vertices[polygon[pi - 1]]) {
00303
00304 ++pi;
00305 } else {
00306
00307 polygon.erase(_polygon.begin() + pi);
00308 }
00309 }
00310
00311 if (polygon.size() > 1 && _vertices[polygon.back()] == _vertices[_polygon.front()]) {
00312
00313 polygon.pop_back();
00314 }
00315 }
00316
00317
00318
00319
00320
00321 #define T_X 1
00322 #define T_Y 2
00323 #define T_SINK 3
00324
00325
00326 #define FIRSTPT 1
00327 #define LASTPT 2
00328
00329
00330 #define REALLY_BIG 1<<30
00331 #define C_EPS 1.0e-7
00332
00333
00334
00335
00336
00337
00338 #define S_LEFT 1
00339 #define S_RIGHT 2
00340
00341
00342 #define ST_VALID 1
00343 #define ST_INVALID 2
00344
00345
00346 #define SP_SIMPLE_LRUP 1
00347 #define SP_SIMPLE_LRDN 2
00348 #define SP_2UP_2DN 3
00349 #define SP_2UP_LEFT 4
00350 #define SP_2UP_RIGHT 5
00351 #define SP_2DN_LEFT 6
00352 #define SP_2DN_RIGHT 7
00353 #define SP_NOSPLIT -1
00354
00355 #define TR_FROM_UP 1
00356 #define TR_FROM_DN 2
00357
00358 #define TRI_LHS 1
00359 #define TRI_RHS 2
00360
00361
00362 #define CROSS(v0, v1, v2) (((v1).x - (v0).x)*((v2).y - (v0).y) - \
00363 ((v1).y - (v0).y)*((v2).x - (v0).x))
00364
00365 #define DOT(v0, v1) ((v0).x * (v1).x + (v0).y * (v1).y)
00366
00367 #define FP_EQUAL(s, t) (fabs(s - t) <= C_EPS)
00368
00369
00370 #define CROSS_SINE(v0, v1) ((v0).x * (v1).y - (v1).x * (v0).y)
00371 #define LENGTH(v0) (sqrt((v0).x * (v0).x + (v0).y * (v0).y))
00372
00373
00374
00375
00376
00377
00378
00379
00380 bool Triangulator::
00381 check_left_winding(const vector_int &range) const {
00382
00383
00384
00385 double area = 0.0;
00386 size_t j = range.size() - 1;
00387 for (size_t i = 0; i < range.size(); ++i) {
00388 const LPoint2d &p0 = _vertices[range[j]];
00389 const LPoint2d &p1 = _vertices[range[i]];
00390 area += p0[0] * p1[1] - p0[1] * p1[0];
00391 j = i;
00392 }
00393
00394 return area >= 0.0;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 void Triangulator::
00406 make_segment(const vector_int &range, bool want_left_winding) {
00407 int num_points = (int)range.size();
00408 nassertv(num_points >= 2);
00409
00410 int first = (int)seg.size();
00411 int last = first + num_points - 1;
00412
00413 if (want_left_winding == check_left_winding(range)) {
00414
00415 int first = (int)seg.size();
00416 int last = first + num_points - 1;
00417
00418 seg.push_back(segment_t(this, range[0], range[1],
00419 last, first + 1));
00420
00421 for (int i = 1; i < num_points - 1; ++i) {
00422 seg.push_back(segment_t(this, range[i], range[i + 1],
00423 first + i - 1, first + i + 1));
00424 }
00425
00426 seg.push_back(segment_t(this, range[num_points - 1], range[0],
00427 last - 1, first));
00428
00429 } else {
00430
00431 seg.push_back(segment_t(this, range[0], range[num_points - 1],
00432 last, first + 1));
00433
00434 for (int i = 1; i < num_points - 1; ++i) {
00435 seg.push_back(segment_t(this, range[num_points - i], range[num_points - i - 1],
00436 first + i - 1, first + i + 1));
00437 }
00438
00439 seg.push_back(segment_t(this, range[1], range[0],
00440 last - 1, first));
00441
00442 }
00443 }
00444
00445
00446
00447 int Triangulator::
00448 choose_segment() {
00449 nassertr(choose_idx < (int)permute.size(), 0);
00450
00451
00452 return permute[choose_idx++];
00453 }
00454
00455 double Triangulator::
00456 math_log2(double v) {
00457 static const double log2 = log(2.0);
00458 return log(v) / log2;
00459 }
00460
00461
00462 int Triangulator::
00463 math_logstar_n(int n) {
00464 int i;
00465 double v;
00466
00467 for (i = 0, v = (double) n; v >= 1; i++)
00468 v = math_log2(v);
00469
00470 return (i - 1);
00471 }
00472
00473
00474 int Triangulator::
00475 math_N(int n, int h) {
00476 int i;
00477 double v;
00478
00479 for (i = 0, v = (int) n; i < h; i++)
00480 v = math_log2(v);
00481
00482 return (int) ceil((double) 1.0*n/v);
00483 }
00484
00485
00486
00487 int Triangulator::newnode() {
00488 int index = (int)qs.size();
00489 qs.push_back(node_t());
00490
00491 return index;
00492 }
00493
00494
00495 int Triangulator::newtrap() {
00496 int tr_idx = (int)tr.size();
00497 tr.push_back(trap_t());
00498 tr[tr_idx].lseg = -1;
00499 tr[tr_idx].rseg = -1;
00500 tr[tr_idx].state = ST_VALID;
00501
00502 return tr_idx;
00503 }
00504
00505
00506
00507 int Triangulator::_max(point_t *yval, point_t *v0, point_t *v1) {
00508 if (v0->y > v1->y + C_EPS)
00509 *yval = *v0;
00510 else if (FP_EQUAL(v0->y, v1->y))
00511 {
00512 if (v0->x > v1->x + C_EPS)
00513 *yval = *v0;
00514 else
00515 *yval = *v1;
00516 }
00517 else
00518 *yval = *v1;
00519
00520 return 0;
00521 }
00522
00523
00524
00525 int Triangulator::_min(point_t *yval, point_t *v0, point_t *v1) {
00526 if (v0->y < v1->y - C_EPS)
00527 *yval = *v0;
00528 else if (FP_EQUAL(v0->y, v1->y))
00529 {
00530 if (v0->x < v1->x)
00531 *yval = *v0;
00532 else
00533 *yval = *v1;
00534 }
00535 else
00536 *yval = *v1;
00537
00538 return 0;
00539 }
00540
00541
00542 int Triangulator::
00543 _greater_than(point_t *v0, point_t *v1) {
00544 if (v0->y > v1->y + C_EPS)
00545 return true;
00546 else if (v0->y < v1->y - C_EPS)
00547 return false;
00548 else
00549 return (v0->x > v1->x);
00550 }
00551
00552
00553 int Triangulator::
00554 _equal_to(point_t *v0, point_t *v1) {
00555 return (FP_EQUAL(v0->y, v1->y) && FP_EQUAL(v0->x, v1->x));
00556 }
00557
00558 int Triangulator::
00559 _greater_than_equal_to(point_t *v0, point_t *v1) {
00560 if (v0->y > v1->y + C_EPS)
00561 return true;
00562 else if (v0->y < v1->y - C_EPS)
00563 return false;
00564 else
00565 return (v0->x >= v1->x);
00566 }
00567
00568 int Triangulator::
00569 _less_than(point_t *v0, point_t *v1) {
00570 if (v0->y < v1->y - C_EPS)
00571 return true;
00572 else if (v0->y > v1->y + C_EPS)
00573 return false;
00574 else
00575 return (v0->x < v1->x);
00576 }
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592 int Triangulator::
00593 init_query_structure(int segnum) {
00594 int i1, i2, i3, i4, i5, i6, i7, root;
00595 int t1, t2, t3, t4;
00596 segment_t *s = &seg[segnum];
00597
00598 tr.clear();
00599 qs.clear();
00600
00601
00602 tr.push_back(trap_t());
00603 qs.push_back(node_t());
00604
00605 i1 = newnode();
00606 qs[i1].nodetype = T_Y;
00607 _max(&qs[i1].yval, &s->v0, &s->v1);
00608 root = i1;
00609
00610 i2 = newnode();
00611 qs[i1].right = i2;
00612 qs[i2].nodetype = T_SINK;
00613 qs[i2].parent = i1;
00614
00615 i3 = newnode();
00616 qs[i1].left = i3;
00617
00618 qs[i3].nodetype = T_Y;
00619 _min(&qs[i3].yval, &s->v0, &s->v1);
00620 qs[i3].parent = i1;
00621
00622 i4 = newnode();
00623 qs[i3].left = i4;
00624 qs[i4].nodetype = T_SINK;
00625 qs[i4].parent = i3;
00626
00627 i5 = newnode();
00628 qs[i3].right = i5;
00629 qs[i5].nodetype = T_X;
00630 qs[i5].segnum = segnum;
00631 qs[i5].parent = i3;
00632
00633 i6 = newnode();
00634 qs[i5].left = i6;
00635 qs[i6].nodetype = T_SINK;
00636 qs[i6].parent = i5;
00637
00638 i7 = newnode();
00639 qs[i5].right = i7;
00640 qs[i7].nodetype = T_SINK;
00641 qs[i7].parent = i5;
00642
00643 t1 = newtrap();
00644 t2 = newtrap();
00645 t3 = newtrap();
00646 t4 = newtrap();
00647
00648 tr[t4].lo = qs[i1].yval;
00649 tr[t2].hi = qs[i1].yval;
00650 tr[t1].hi = qs[i1].yval;
00651 tr[t3].hi = qs[i3].yval;
00652 tr[t2].lo = qs[i3].yval;
00653 tr[t1].lo = qs[i3].yval;
00654 tr[t4].hi.y = (double) (REALLY_BIG);
00655 tr[t4].hi.x = (double) (REALLY_BIG);
00656 tr[t3].lo.y = (double) -1* (REALLY_BIG);
00657 tr[t3].lo.x = (double) -1* (REALLY_BIG);
00658 tr[t2].lseg = segnum;
00659 tr[t1].rseg = segnum;
00660 tr[t2].u0 = t4;
00661 tr[t1].u0 = t4;
00662 tr[t2].d0 = t3;
00663 tr[t1].d0 = t3;
00664 tr[t3].u0 = t1;
00665 tr[t4].d0 = t1;
00666 tr[t3].u1 = t2;
00667 tr[t4].d1 = t2;
00668
00669 tr[t1].sink = i6;
00670 tr[t2].sink = i7;
00671 tr[t3].sink = i4;
00672 tr[t4].sink = i2;
00673
00674 tr[t2].state = ST_VALID;
00675 tr[t1].state = ST_VALID;
00676 tr[t4].state = ST_VALID;
00677 tr[t3].state = ST_VALID;
00678
00679 qs[i2].trnum = t4;
00680 qs[i4].trnum = t3;
00681 qs[i6].trnum = t1;
00682 qs[i7].trnum = t2;
00683
00684 s->is_inserted = true;
00685 return root;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694 int Triangulator::
00695 is_left_of(int segnum, point_t *v) {
00696 segment_t *s = &seg[segnum];
00697 double area;
00698
00699 if (_greater_than(&s->v1, &s->v0))
00700 {
00701 if (FP_EQUAL(s->v1.y, v->y))
00702 {
00703 if (v->x < s->v1.x)
00704 area = 1.0;
00705 else
00706 area = -1.0;
00707 }
00708 else if (FP_EQUAL(s->v0.y, v->y))
00709 {
00710 if (v->x < s->v0.x)
00711 area = 1.0;
00712 else
00713 area = -1.0;
00714 }
00715 else
00716 area = CROSS(s->v0, s->v1, (*v));
00717 }
00718 else
00719 {
00720 if (FP_EQUAL(s->v1.y, v->y))
00721 {
00722 if (v->x < s->v1.x)
00723 area = 1.0;
00724 else
00725 area = -1.0;
00726 }
00727 else if (FP_EQUAL(s->v0.y, v->y))
00728 {
00729 if (v->x < s->v0.x)
00730 area = 1.0;
00731 else
00732 area = -1.0;
00733 }
00734 else
00735 area = CROSS(s->v1, s->v0, (*v));
00736 }
00737
00738 if (area > 0.0)
00739 return true;
00740 else
00741 return false;
00742 }
00743
00744
00745
00746
00747
00748
00749
00750 int Triangulator::
00751 inserted(int segnum, int whichpt) {
00752 if (whichpt == FIRSTPT)
00753 return seg[seg[segnum].prev].is_inserted;
00754 else
00755 return seg[seg[segnum].next].is_inserted;
00756 }
00757
00758
00759
00760
00761
00762 int Triangulator::
00763 locate_endpoint(point_t *v, point_t *vo, int r) {
00764
00765 node_t *rptr = &qs[r];
00766
00767 switch (rptr->nodetype)
00768 {
00769 case T_SINK:
00770 return rptr->trnum;
00771
00772 case T_Y:
00773 if (_greater_than(v, &rptr->yval))
00774 return locate_endpoint(v, vo, rptr->right);
00775 else if (_equal_to(v, &rptr->yval))
00776 {
00777 if (_greater_than(vo, &rptr->yval))
00778 return locate_endpoint(v, vo, rptr->right);
00779 else
00780 return locate_endpoint(v, vo, rptr->left);
00781 }
00782 else
00783 return locate_endpoint(v, vo, rptr->left);
00784
00785 case T_X:
00786 if (_equal_to(v, &seg[rptr->segnum].v0) ||
00787 _equal_to(v, &seg[rptr->segnum].v1))
00788 {
00789 if (FP_EQUAL(v->y, vo->y))
00790 {
00791 if (vo->x < v->x)
00792 return locate_endpoint(v, vo, rptr->left);
00793 else
00794 return locate_endpoint(v, vo, rptr->right);
00795 }
00796
00797 else if (is_left_of(rptr->segnum, vo))
00798 return locate_endpoint(v, vo, rptr->left);
00799 else
00800 return locate_endpoint(v, vo, rptr->right);
00801 }
00802 else if (is_left_of(rptr->segnum, v))
00803 return locate_endpoint(v, vo, rptr->left);
00804 else
00805 return locate_endpoint(v, vo, rptr->right);
00806
00807 default:
00808 fprintf(stderr, "Haggu !!!!!\n");
00809 nassertr(false, -1);
00810 return -1;
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822 int Triangulator::
00823 merge_trapezoids(int segnum, int tfirst, int tlast, int side) {
00824 int t, tnext, cond;
00825 int ptnext;
00826
00827
00828
00829
00830 t = tfirst;
00831 while ((t > 0) && _greater_than_equal_to(&tr[t].lo, &tr[tlast].lo))
00832 {
00833 if (side == S_LEFT)
00834 cond = ((((tnext = tr[t].d0) > 0) && (tr[tnext].rseg == segnum)) ||
00835 (((tnext = tr[t].d1) > 0) && (tr[tnext].rseg == segnum)));
00836 else
00837 cond = ((((tnext = tr[t].d0) > 0) && (tr[tnext].lseg == segnum)) ||
00838 (((tnext = tr[t].d1) > 0) && (tr[tnext].lseg == segnum)));
00839
00840 if (cond)
00841 {
00842 if ((tr[t].lseg == tr[tnext].lseg) &&
00843 (tr[t].rseg == tr[tnext].rseg))
00844 {
00845
00846
00847 ptnext = qs[tr[tnext].sink].parent;
00848
00849 if (qs[ptnext].left == tr[tnext].sink)
00850 qs[ptnext].left = tr[t].sink;
00851 else
00852 qs[ptnext].right = tr[t].sink;
00853
00854
00855
00856
00857 if ((tr[t].d0 = tr[tnext].d0) > 0)
00858 if (tr[tr[t].d0].u0 == tnext)
00859 tr[tr[t].d0].u0 = t;
00860 else if (tr[tr[t].d0].u1 == tnext)
00861 tr[tr[t].d0].u1 = t;
00862
00863 if ((tr[t].d1 = tr[tnext].d1) > 0)
00864 if (tr[tr[t].d1].u0 == tnext)
00865 tr[tr[t].d1].u0 = t;
00866 else if (tr[tr[t].d1].u1 == tnext)
00867 tr[tr[t].d1].u1 = t;
00868
00869 tr[t].lo = tr[tnext].lo;
00870 tr[tnext].state = ST_INVALID;
00871
00872 }
00873 else
00874 t = tnext;
00875 }
00876 else
00877 t = tnext;
00878
00879 }
00880
00881 return 0;
00882 }
00883
00884
00885
00886
00887
00888
00889
00890
00891 int Triangulator::
00892 add_segment(int segnum) {
00893
00894
00895 segment_t s;
00896
00897 int tu, tl, sk, tfirst, tlast;
00898 int tfirstr = 0, tlastr = 0, tfirstl = 0, tlastl = 0;
00899 int i1, i2, t, tn;
00900 point_t tpt;
00901 int tritop = 0, tribot = 0, is_swapped = 0;
00902 int tmptriseg;
00903
00904 s = seg[segnum];
00905 if (_greater_than(&s.v1, &s.v0))
00906 {
00907 int tmp;
00908 tpt = s.v0;
00909 s.v0 = s.v1;
00910 s.v1 = tpt;
00911 tmp = s.root0;
00912 s.root0 = s.root1;
00913 s.root1 = tmp;
00914 is_swapped = true;
00915 }
00916
00917 if ((is_swapped) ? !inserted(segnum, LASTPT) :
00918 !inserted(segnum, FIRSTPT))
00919 {
00920 int tmp_d;
00921
00922 tu = locate_endpoint(&s.v0, &s.v1, s.root0);
00923 tl = newtrap();
00924 tr[tl].state = ST_VALID;
00925 tr[tl] = tr[tu];
00926 tr[tl].hi.y = s.v0.y;
00927 tr[tu].lo.y = s.v0.y;
00928 tr[tl].hi.x = s.v0.x;
00929 tr[tu].lo.x = s.v0.x;
00930 tr[tu].d0 = tl;
00931 tr[tu].d1 = 0;
00932 tr[tl].u0 = tu;
00933 tr[tl].u1 = 0;
00934
00935 if (((tmp_d = tr[tl].d0) > 0) && (tr[tmp_d].u0 == tu))
00936 tr[tmp_d].u0 = tl;
00937 if (((tmp_d = tr[tl].d0) > 0) && (tr[tmp_d].u1 == tu))
00938 tr[tmp_d].u1 = tl;
00939
00940 if (((tmp_d = tr[tl].d1) > 0) && (tr[tmp_d].u0 == tu))
00941 tr[tmp_d].u0 = tl;
00942 if (((tmp_d = tr[tl].d1) > 0) && (tr[tmp_d].u1 == tu))
00943 tr[tmp_d].u1 = tl;
00944
00945
00946
00947
00948 i1 = newnode();
00949 i2 = newnode();
00950 sk = tr[tu].sink;
00951
00952 qs[sk].nodetype = T_Y;
00953 qs[sk].yval = s.v0;
00954 qs[sk].segnum = segnum;
00955 qs[sk].left = i2;
00956 qs[sk].right = i1;
00957
00958 qs[i1].nodetype = T_SINK;
00959 qs[i1].trnum = tu;
00960 qs[i1].parent = sk;
00961
00962 qs[i2].nodetype = T_SINK;
00963 qs[i2].trnum = tl;
00964 qs[i2].parent = sk;
00965
00966 tr[tu].sink = i1;
00967 tr[tl].sink = i2;
00968 tfirst = tl;
00969 }
00970 else
00971 {
00972 tfirst = locate_endpoint(&s.v0, &s.v1, s.root0);
00973 tritop = 1;
00974 }
00975
00976
00977 if ((is_swapped) ? !inserted(segnum, FIRSTPT) :
00978 !inserted(segnum, LASTPT))
00979 {
00980 int tmp_d;
00981
00982 tu = locate_endpoint(&s.v1, &s.v0, s.root1);
00983
00984 tl = newtrap();
00985 tr[tl].state = ST_VALID;
00986 tr[tl] = tr[tu];
00987 tr[tl].hi.y = s.v1.y;
00988 tr[tu].lo.y = s.v1.y;
00989 tr[tl].hi.x = s.v1.x;
00990 tr[tu].lo.x = s.v1.x;
00991 tr[tu].d0 = tl;
00992 tr[tu].d1 = 0;
00993 tr[tl].u0 = tu;
00994 tr[tl].u1 = 0;
00995
00996 if (((tmp_d = tr[tl].d0) > 0) && (tr[tmp_d].u0 == tu))
00997 tr[tmp_d].u0 = tl;
00998 if (((tmp_d = tr[tl].d0) > 0) && (tr[tmp_d].u1 == tu))
00999 tr[tmp_d].u1 = tl;
01000
01001 if (((tmp_d = tr[tl].d1) > 0) && (tr[tmp_d].u0 == tu))
01002 tr[tmp_d].u0 = tl;
01003 if (((tmp_d = tr[tl].d1) > 0) && (tr[tmp_d].u1 == tu))
01004 tr[tmp_d].u1 = tl;
01005
01006
01007
01008
01009 i1 = newnode();
01010 i2 = newnode();
01011 sk = tr[tu].sink;
01012
01013 qs[sk].nodetype = T_Y;
01014 qs[sk].yval = s.v1;
01015 qs[sk].segnum = segnum;
01016 qs[sk].left = i2;
01017 qs[sk].right = i1;
01018
01019 qs[i1].nodetype = T_SINK;
01020 qs[i1].trnum = tu;
01021 qs[i1].parent = sk;
01022
01023 qs[i2].nodetype = T_SINK;
01024 qs[i2].trnum = tl;
01025 qs[i2].parent = sk;
01026
01027 tr[tu].sink = i1;
01028 tr[tl].sink = i2;
01029 tlast = tu;
01030 }
01031 else
01032 {
01033 tlast = locate_endpoint(&s.v1, &s.v0, s.root1);
01034 tribot = 1;
01035 }
01036
01037
01038
01039
01040
01041 t = tfirst;
01042
01043 while ((t > 0) &&
01044 _greater_than_equal_to(&tr[t].lo, &tr[tlast].lo))
01045
01046 {
01047 int t_sav, tn_sav;
01048 sk = tr[t].sink;
01049 i1 = newnode();
01050 i2 = newnode();
01051
01052 qs[sk].nodetype = T_X;
01053 qs[sk].segnum = segnum;
01054 qs[sk].left = i1;
01055 qs[sk].right = i2;
01056
01057 qs[i1].nodetype = T_SINK;
01058 qs[i1].trnum = t;
01059 qs[i1].parent = sk;
01060
01061 qs[i2].nodetype = T_SINK;
01062 tn = newtrap();
01063 qs[i2].trnum = tn;
01064 tr[tn].state = ST_VALID;
01065 qs[i2].parent = sk;
01066
01067 if (t == tfirst)
01068 tfirstr = tn;
01069 if (_equal_to(&tr[t].lo, &tr[tlast].lo))
01070 tlastr = tn;
01071
01072 tr[tn] = tr[t];
01073 tr[t].sink = i1;
01074 tr[tn].sink = i2;
01075 t_sav = t;
01076 tn_sav = tn;
01077
01078
01079
01080 if ((tr[t].d0 <= 0) && (tr[t].d1 <= 0))
01081 {
01082
01083 fprintf(stderr, "add_segment: error\n");
01084 return 1;
01085 }
01086
01087
01088
01089
01090
01091 else if ((tr[t].d0 > 0) && (tr[t].d1 <= 0))
01092 {
01093 if ((tr[t].u0 > 0) && (tr[t].u1 > 0))
01094 {
01095 if (tr[t].usave > 0)
01096 {
01097 if (tr[t].uside == S_LEFT)
01098 {
01099 tr[tn].u0 = tr[t].u1;
01100 tr[t].u1 = -1;
01101 tr[tn].u1 = tr[t].usave;
01102
01103 tr[tr[t].u0].d0 = t;
01104 tr[tr[tn].u0].d0 = tn;
01105 tr[tr[tn].u1].d0 = tn;
01106 }
01107 else
01108 {
01109 tr[tn].u1 = -1;
01110 tr[tn].u0 = tr[t].u1;
01111 tr[t].u1 = tr[t].u0;
01112 tr[t].u0 = tr[t].usave;
01113
01114 tr[tr[t].u0].d0 = t;
01115 tr[tr[t].u1].d0 = t;
01116 tr[tr[tn].u0].d0 = tn;
01117 }
01118 tr[tn].usave = 0;
01119 tr[t].usave = 0;
01120 }
01121 else
01122 {
01123 tr[tn].u0 = tr[t].u1;
01124 tr[tn].u1 = -1;
01125 tr[t].u1 = -1;
01126 tr[tr[tn].u0].d0 = tn;
01127 }
01128 }
01129 else
01130 {
01131 int tmp_u = tr[t].u0;
01132 int td0, td1;
01133 if (((td0 = tr[tmp_u].d0) > 0) &&
01134 ((td1 = tr[tmp_u].d1) > 0))
01135 {
01136 if ((tr[td0].rseg > 0) &&
01137 !is_left_of(tr[td0].rseg, &s.v1))
01138 {
01139 tr[tn].u1 = -1;
01140 tr[t].u1 = -1;
01141 tr[t].u0 = -1;
01142 tr[tr[tn].u0].d1 = tn;
01143 }
01144 else
01145 {
01146 tr[t].u1 = -1;
01147 tr[tn].u1 = -1;
01148 tr[tn].u0 = -1;
01149 tr[tr[t].u0].d0 = t;
01150 }
01151 }
01152 else
01153 {
01154 tr[tr[t].u0].d0 = t;
01155 tr[tr[t].u0].d1 = tn;
01156 }
01157 }
01158
01159 if (FP_EQUAL(tr[t].lo.y, tr[tlast].lo.y) &&
01160 FP_EQUAL(tr[t].lo.x, tr[tlast].lo.x) && tribot)
01161 {
01162
01163 if (is_swapped)
01164 tmptriseg = seg[segnum].prev;
01165 else
01166 tmptriseg = seg[segnum].next;
01167
01168 if ((tmptriseg > 0) && is_left_of(tmptriseg, &s.v0))
01169 {
01170
01171 tr[tr[t].d0].u0 = t;
01172 tr[tn].d1 = -1;
01173 tr[tn].d0 = -1;
01174 }
01175 else
01176 {
01177
01178 tr[tr[tn].d0].u1 = tn;
01179 tr[t].d1 = -1;
01180 tr[t].d0 = -1;
01181 }
01182 }
01183 else
01184 {
01185 if ((tr[tr[t].d0].u0 > 0) && (tr[tr[t].d0].u1 > 0))
01186 {
01187 if (tr[tr[t].d0].u0 == t)
01188 {
01189 tr[tr[t].d0].usave = tr[tr[t].d0].u1;
01190 tr[tr[t].d0].uside = S_LEFT;
01191 }
01192 else
01193 {
01194 tr[tr[t].d0].usave = tr[tr[t].d0].u0;
01195 tr[tr[t].d0].uside = S_RIGHT;
01196 }
01197 }
01198 tr[tr[t].d0].u0 = t;
01199 tr[tr[t].d0].u1 = tn;
01200 }
01201
01202 t = tr[t].d0;
01203 }
01204
01205
01206 else if ((tr[t].d0 <= 0) && (tr[t].d1 > 0))
01207 {
01208 if ((tr[t].u0 > 0) && (tr[t].u1 > 0))
01209 {
01210 if (tr[t].usave > 0)
01211 {
01212 if (tr[t].uside == S_LEFT)
01213 {
01214 tr[tn].u0 = tr[t].u1;
01215 tr[t].u1 = -1;
01216 tr[tn].u1 = tr[t].usave;
01217
01218 tr[tr[t].u0].d0 = t;
01219 tr[tr[tn].u0].d0 = tn;
01220 tr[tr[tn].u1].d0 = tn;
01221 }
01222 else
01223 {
01224 tr[tn].u1 = -1;
01225 tr[tn].u0 = tr[t].u1;
01226 tr[t].u1 = tr[t].u0;
01227 tr[t].u0 = tr[t].usave;
01228
01229 tr[tr[t].u0].d0 = t;
01230 tr[tr[t].u1].d0 = t;
01231 tr[tr[tn].u0].d0 = tn;
01232 }
01233
01234 tr[tn].usave = 0;
01235 tr[t].usave = 0;
01236 }
01237 else
01238 {
01239 tr[tn].u0 = tr[t].u1;
01240 tr[tn].u1 = -1;
01241 tr[t].u1 = -1;
01242 tr[tr[tn].u0].d0 = tn;
01243 }
01244 }
01245 else
01246 {
01247 int tmp_u = tr[t].u0;
01248 int td0, td1;
01249 if (((td0 = tr[tmp_u].d0) > 0) &&
01250 ((td1 = tr[tmp_u].d1) > 0))
01251 {
01252 if ((tr[td0].rseg > 0) &&
01253 !is_left_of(tr[td0].rseg, &s.v1))
01254 {
01255 tr[tn].u1 = -1;
01256 tr[t].u1 = -1;
01257 tr[t].u0 = -1;
01258 tr[tr[tn].u0].d1 = tn;
01259 }
01260 else
01261 {
01262 tr[t].u1 = -1;
01263 tr[tn].u1 = -1;
01264 tr[tn].u0 = -1;
01265 tr[tr[t].u0].d0 = t;
01266 }
01267 }
01268 else
01269 {
01270 tr[tr[t].u0].d0 = t;
01271 tr[tr[t].u0].d1 = tn;
01272 }
01273 }
01274
01275 if (FP_EQUAL(tr[t].lo.y, tr[tlast].lo.y) &&
01276 FP_EQUAL(tr[t].lo.x, tr[tlast].lo.x) && tribot)
01277 {
01278 if (is_swapped)
01279 tmptriseg = seg[segnum].prev;
01280 else
01281 tmptriseg = seg[segnum].next;
01282
01283 if ((tmptriseg > 0) && is_left_of(tmptriseg, &s.v0))
01284 {
01285
01286 tr[tr[t].d1].u0 = t;
01287 tr[tn].d1 = -1;
01288 tr[tn].d0 = -1;
01289 }
01290 else
01291 {
01292
01293 tr[tr[tn].d1].u1 = tn;
01294 tr[t].d1 = -1;
01295 tr[t].d0 = -1;
01296 }
01297 }
01298 else
01299 {
01300 if ((tr[tr[t].d1].u0 > 0) && (tr[tr[t].d1].u1 > 0))
01301 {
01302 if (tr[tr[t].d1].u0 == t)
01303 {
01304 tr[tr[t].d1].usave = tr[tr[t].d1].u1;
01305 tr[tr[t].d1].uside = S_LEFT;
01306 }
01307 else
01308 {
01309 tr[tr[t].d1].usave = tr[tr[t].d1].u0;
01310 tr[tr[t].d1].uside = S_RIGHT;
01311 }
01312 }
01313 tr[tr[t].d1].u0 = t;
01314 tr[tr[t].d1].u1 = tn;
01315 }
01316
01317 t = tr[t].d1;
01318 }
01319
01320
01321
01322
01323 else
01324 {
01325
01326 double y0, yt;
01327 point_t tmppt;
01328 int tnext, i_d0, i_d1;
01329
01330 i_d1 = false;
01331 i_d0 = false;
01332 if (FP_EQUAL(tr[t].lo.y, s.v0.y))
01333 {
01334 if (tr[t].lo.x > s.v0.x)
01335 i_d0 = true;
01336 else
01337 i_d1 = true;
01338 }
01339 else
01340 {
01341 y0 = tr[t].lo.y;
01342 tmppt.y = y0;
01343 yt = (y0 - s.v0.y)/(s.v1.y - s.v0.y);
01344 tmppt.x = s.v0.x + yt * (s.v1.x - s.v0.x);
01345
01346 if (_less_than(&tmppt, &tr[t].lo))
01347 i_d0 = true;
01348 else
01349 i_d1 = true;
01350 }
01351
01352
01353
01354
01355 if ((tr[t].u0 > 0) && (tr[t].u1 > 0))
01356 {
01357 if (tr[t].usave > 0)
01358 {
01359 if (tr[t].uside == S_LEFT)
01360 {
01361 tr[tn].u0 = tr[t].u1;
01362 tr[t].u1 = -1;
01363 tr[tn].u1 = tr[t].usave;
01364
01365 tr[tr[t].u0].d0 = t;
01366 tr[tr[tn].u0].d0 = tn;
01367 tr[tr[tn].u1].d0 = tn;
01368 }
01369 else
01370 {
01371 tr[tn].u1 = -1;
01372 tr[tn].u0 = tr[t].u1;
01373 tr[t].u1 = tr[t].u0;
01374 tr[t].u0 = tr[t].usave;
01375
01376 tr[tr[t].u0].d0 = t;
01377 tr[tr[t].u1].d0 = t;
01378 tr[tr[tn].u0].d0 = tn;
01379 }
01380
01381 tr[tn].usave = 0;
01382 tr[t].usave = 0;
01383 }
01384 else
01385 {
01386 tr[tn].u0 = tr[t].u1;
01387 tr[tn].u1 = -1;
01388 tr[t].u1 = -1;
01389 tr[tr[tn].u0].d0 = tn;
01390 }
01391 }
01392 else
01393 {
01394 int tmp_u = tr[t].u0;
01395 int td0, td1;
01396 if (((td0 = tr[tmp_u].d0) > 0) &&
01397 ((td1 = tr[tmp_u].d1) > 0))
01398 {
01399 if ((tr[td0].rseg > 0) &&
01400 !is_left_of(tr[td0].rseg, &s.v1))
01401 {
01402 tr[tn].u1 = -1;
01403 tr[t].u1 = -1;
01404 tr[t].u0 = -1;
01405 tr[tr[tn].u0].d1 = tn;
01406 }
01407 else
01408 {
01409 tr[t].u1 = -1;
01410 tr[tn].u1 = -1;
01411 tr[tn].u0 = -1;
01412 tr[tr[t].u0].d0 = t;
01413 }
01414 }
01415 else
01416 {
01417 tr[tr[t].u0].d0 = t;
01418 tr[tr[t].u0].d1 = tn;
01419 }
01420 }
01421
01422 if (FP_EQUAL(tr[t].lo.y, tr[tlast].lo.y) &&
01423 FP_EQUAL(tr[t].lo.x, tr[tlast].lo.x) && tribot)
01424 {
01425
01426
01427
01428
01429 tr[tr[t].d0].u0 = t;
01430 tr[tr[t].d0].u1 = -1;
01431 tr[tr[t].d1].u0 = tn;
01432 tr[tr[t].d1].u1 = -1;
01433
01434 tr[tn].d0 = tr[t].d1;
01435 tr[tn].d1 = -1;
01436 tr[t].d1 = -1;
01437
01438 tnext = tr[t].d1;
01439 }
01440 else if (i_d0)
01441
01442 {
01443 tr[tr[t].d0].u0 = t;
01444 tr[tr[t].d0].u1 = tn;
01445 tr[tr[t].d1].u0 = tn;
01446 tr[tr[t].d1].u1 = -1;
01447
01448
01449
01450
01451 tr[t].d1 = -1;
01452
01453 tnext = tr[t].d0;
01454 }
01455 else
01456 {
01457 tr[tr[t].d0].u0 = t;
01458 tr[tr[t].d0].u1 = -1;
01459 tr[tr[t].d1].u0 = t;
01460 tr[tr[t].d1].u1 = tn;
01461
01462
01463
01464
01465 tr[tn].d0 = tr[t].d1;
01466 tr[tn].d1 = -1;
01467
01468 tnext = tr[t].d1;
01469 }
01470
01471 t = tnext;
01472 }
01473
01474 tr[tn_sav].lseg = segnum;
01475 tr[t_sav].rseg = segnum;
01476 }
01477
01478
01479
01480
01481
01482
01483 tfirstl = tfirst;
01484 tlastl = tlast;
01485 merge_trapezoids(segnum, tfirstl, tlastl, S_LEFT);
01486 merge_trapezoids(segnum, tfirstr, tlastr, S_RIGHT);
01487
01488 seg[segnum].is_inserted = true;
01489 return 0;
01490 }
01491
01492
01493
01494
01495
01496
01497 int Triangulator::
01498 find_new_roots(int segnum) {
01499
01500 segment_t *s = &seg[segnum];
01501
01502 if (s->is_inserted)
01503 return 0;
01504
01505 s->root0 = locate_endpoint(&s->v0, &s->v1, s->root0);
01506 s->root0 = tr[s->root0].sink;
01507
01508 s->root1 = locate_endpoint(&s->v1, &s->v0, s->root1);
01509 s->root1 = tr[s->root1].sink;
01510 return 0;
01511 }
01512
01513
01514
01515 int Triangulator::
01516 construct_trapezoids(int nseg) {
01517
01518 int i;
01519 int root, h;
01520
01521
01522
01523
01524 root = init_query_structure(choose_segment());
01525
01526 for (i = 1; i <= nseg; i++) {
01527 seg[i].root1 = root;
01528 seg[i].root0 = root;
01529 }
01530
01531 for (h = 1; h <= math_logstar_n(nseg); h++)
01532 {
01533 for (i = math_N(nseg, h -1) + 1; i <= math_N(nseg, h); i++) {
01534 if (add_segment(choose_segment()) != 0) {
01535
01536 return 1;
01537 }
01538 }
01539
01540
01541 for (i = 1; i <= nseg; i++)
01542 find_new_roots(i);
01543 }
01544
01545 for (i = math_N(nseg, math_logstar_n(nseg)) + 1; i <= nseg; i++)
01546 add_segment(choose_segment());
01547
01548 return 0;
01549 }
01550
01551
01552
01553
01554 int Triangulator::
01555 inside_polygon(trap_t *t) {
01556 int rseg = t->rseg;
01557
01558 if (t->state == ST_INVALID)
01559 return 0;
01560
01561 if ((t->lseg <= 0) || (t->rseg <= 0))
01562 return 0;
01563
01564 if (((t->u0 <= 0) && (t->u1 <= 0)) ||
01565 ((t->d0 <= 0) && (t->d1 <= 0)))
01566 return (_greater_than(&seg[rseg].v1, &seg[rseg].v0));
01567
01568 return 0;
01569 }
01570
01571
01572
01573 int Triangulator::
01574 newmon() {
01575 int index = (int)mon.size();
01576 mon.push_back(0);
01577
01578 return index;
01579 }
01580
01581
01582
01583 int Triangulator::
01584 new_chain_element() {
01585 int index = (int)mchain.size();
01586 mchain.push_back(monchain_t());
01587
01588 return index;
01589 }
01590
01591
01592 double Triangulator::
01593 get_angle(point_t *vp0, point_t *vpnext, point_t *vp1) {
01594 point_t v0, v1;
01595
01596 v0.x = vpnext->x - vp0->x;
01597 v0.y = vpnext->y - vp0->y;
01598
01599 v1.x = vp1->x - vp0->x;
01600 v1.y = vp1->y - vp0->y;
01601
01602 if (CROSS_SINE(v0, v1) >= 0)
01603 return DOT(v0, v1)/LENGTH(v0)/LENGTH(v1);
01604 else
01605 return (-1.0 * DOT(v0, v1)/LENGTH(v0)/LENGTH(v1) - 2);
01606 }
01607
01608
01609
01610
01611 int Triangulator::
01612 get_vertex_positions(int v0, int v1, int *ip, int *iq) {
01613 vertexchain_t *vp0, *vp1;
01614 int i;
01615 double angle, temp;
01616 int tp = 0, tq = 0;
01617
01618 vp0 = &vert[v0];
01619 vp1 = &vert[v1];
01620
01621
01622
01623
01624
01625 angle = -4.0;
01626 for (i = 0; i < 4; i++)
01627 {
01628 if (vp0->vnext[i] <= 0)
01629 continue;
01630 if ((temp = get_angle(&vp0->pt, &(vert[vp0->vnext[i]].pt),
01631 &vp1->pt)) > angle)
01632 {
01633 angle = temp;
01634 tp = i;
01635 }
01636 }
01637
01638 *ip = tp;
01639
01640
01641
01642 angle = -4.0;
01643 for (i = 0; i < 4; i++)
01644 {
01645 if (vp1->vnext[i] <= 0)
01646 continue;
01647 if ((temp = get_angle(&vp1->pt, &(vert[vp1->vnext[i]].pt),
01648 &vp0->pt)) > angle)
01649 {
01650 angle = temp;
01651 tq = i;
01652 }
01653 }
01654
01655 *iq = tq;
01656
01657 return 0;
01658 }
01659
01660
01661
01662
01663
01664
01665 int Triangulator::
01666 make_new_monotone_poly(int mcur, int v0, int v1) {
01667 int p, q, ip, iq;
01668 int mnew = newmon();
01669 int i, j, nf0, nf1;
01670 vertexchain_t *vp0, *vp1;
01671
01672 if (v0 <= 0 || v1 <= 0) {
01673 return -1;
01674 }
01675
01676 vp0 = &vert[v0];
01677 vp1 = &vert[v1];
01678
01679 get_vertex_positions(v0, v1, &ip, &iq);
01680
01681 p = vp0->vpos[ip];
01682 q = vp1->vpos[iq];
01683
01684
01685
01686
01687 i = new_chain_element();
01688 j = new_chain_element();
01689
01690 mchain[i].vnum = v0;
01691 mchain[j].vnum = v1;
01692
01693 mchain[i].next = mchain[p].next;
01694 mchain[mchain[p].next].prev = i;
01695 mchain[i].prev = j;
01696 mchain[j].next = i;
01697 mchain[j].prev = mchain[q].prev;
01698 mchain[mchain[q].prev].next = j;
01699
01700 mchain[p].next = q;
01701 mchain[q].prev = p;
01702
01703 nf0 = vp0->nextfree;
01704 nf1 = vp1->nextfree;
01705
01706 vp0->vnext[ip] = v1;
01707
01708 vp0->vpos[nf0] = i;
01709 vp0->vnext[nf0] = mchain[mchain[i].next].vnum;
01710 vp1->vpos[nf1] = j;
01711 vp1->vnext[nf1] = v0;
01712
01713 vp0->nextfree++;
01714 vp1->nextfree++;
01715
01716 #ifdef DEBUG
01717 fprintf(stderr, "make_poly: mcur = %d, (v0, v1) = (%d, %d)\n",
01718 mcur, v0, v1);
01719 fprintf(stderr, "next posns = (p, q) = (%d, %d)\n", p, q);
01720 #endif
01721
01722 mon[mcur] = p;
01723 mon[mnew] = i;
01724 return mnew;
01725 }
01726
01727
01728
01729
01730
01731 int Triangulator::
01732 monotonate_trapezoids(int n) {
01733 int i;
01734 int tr_start;
01735
01736 vert.clear();
01737 visited.clear();
01738 mchain.clear();
01739 mon.clear();
01740
01741 vert.insert(vert.begin(), n + 1, vertexchain_t());
01742 mchain.insert(mchain.begin(), n + 1, monchain_t());
01743
01744 visited.insert(visited.begin(), tr.size(), 0);
01745
01746
01747
01748 for (i = 1; i < (int)tr.size(); i++)
01749 if (inside_polygon(&tr[i]))
01750 break;
01751 if (i >= (int)tr.size()) {
01752
01753 return 0;
01754 }
01755
01756 tr_start = i;
01757
01758
01759
01760
01761 #if 0
01762 for (i = 1; i <= n; i++)
01763 {
01764 mchain[i].prev = i - 1;
01765 mchain[i].next = i + 1;
01766 mchain[i].vnum = i;
01767 vert[i].pt = seg[i].v0;
01768 vert[i].vnext[0] = i + 1;
01769 vert[i].vpos[0] = i;
01770 vert[i].nextfree = 1;
01771 vert[i].user_i = seg[i].v0_i;
01772 }
01773 mchain[1].prev = n;
01774 mchain[n].next = 1;
01775 vert[n].vnext[0] = 1;
01776 vert[n].vpos[0] = n;
01777 mon.push_back(1);
01778
01779
01780 #else
01781
01782 for (i = 1; i <= n; i++)
01783 {
01784 mchain[i].prev = seg[i].prev;
01785 mchain[i].next = seg[i].next;
01786 mchain[i].vnum = i;
01787 vert[i].pt = seg[i].v0;
01788 vert[i].vnext[0] = seg[i].next;
01789 vert[i].vpos[0] = i;
01790 vert[i].nextfree = 1;
01791 vert[i].user_i = seg[i].v0_i;
01792 }
01793
01794 mon.push_back(1);
01795
01796
01797 #endif
01798
01799
01800 if (tr[tr_start].u0 > 0)
01801 traverse_polygon(0, tr_start, tr[tr_start].u0, TR_FROM_UP);
01802 else if (tr[tr_start].d0 > 0)
01803 traverse_polygon(0, tr_start, tr[tr_start].d0, TR_FROM_DN);
01804
01805
01806 return newmon();
01807 }
01808
01809
01810
01811 int Triangulator::
01812 traverse_polygon(int mcur, int trnum, int from, int dir) {
01813
01814
01815 if (mcur < 0 || trnum <= 0)
01816 return 0;
01817
01818 if (visited[trnum])
01819 return 0;
01820
01821 trap_t *t = &tr[trnum];
01822
01823 int mnew;
01824 int v0, v1;
01825 int retval = 0;
01826 int do_switch = false;
01827
01828
01829
01830 visited[trnum] = true;
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842 if ((t->u0 <= 0) && (t->u1 <= 0))
01843 {
01844 if ((t->d0 > 0) && (t->d1 > 0))
01845 {
01846 v0 = tr[t->d1].lseg;
01847 v1 = t->lseg;
01848 if (from == t->d1)
01849 {
01850 do_switch = true;
01851 mnew = make_new_monotone_poly(mcur, v1, v0);
01852 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01853 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
01854 }
01855 else
01856 {
01857 mnew = make_new_monotone_poly(mcur, v0, v1);
01858 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01859 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
01860 }
01861 }
01862 else
01863 {
01864 retval = SP_NOSPLIT;
01865 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01866 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01867 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01868 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01869 }
01870 }
01871
01872 else if ((t->d0 <= 0) && (t->d1 <= 0))
01873 {
01874 if ((t->u0 > 0) && (t->u1 > 0))
01875 {
01876 v0 = t->rseg;
01877 v1 = tr[t->u0].rseg;
01878 if (from == t->u1)
01879 {
01880 do_switch = true;
01881 mnew = make_new_monotone_poly(mcur, v1, v0);
01882 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01883 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
01884 }
01885 else
01886 {
01887 mnew = make_new_monotone_poly(mcur, v0, v1);
01888 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01889 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
01890 }
01891 }
01892 else
01893 {
01894 retval = SP_NOSPLIT;
01895 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01896 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01897 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01898 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01899 }
01900 }
01901
01902 else if ((t->u0 > 0) && (t->u1 > 0))
01903 {
01904 if ((t->d0 > 0) && (t->d1 > 0))
01905 {
01906 v0 = tr[t->d1].lseg;
01907 v1 = tr[t->u0].rseg;
01908 retval = SP_2UP_2DN;
01909 if (((dir == TR_FROM_DN) && (t->d1 == from)) ||
01910 ((dir == TR_FROM_UP) && (t->u1 == from)))
01911 {
01912 do_switch = true;
01913 mnew = make_new_monotone_poly(mcur, v1, v0);
01914 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01915 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01916 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
01917 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
01918 }
01919 else
01920 {
01921 mnew = make_new_monotone_poly(mcur, v0, v1);
01922 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01923 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01924 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
01925 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
01926 }
01927 }
01928 else
01929 {
01930 if (_equal_to(&t->lo, &seg[t->lseg].v1))
01931 {
01932 v0 = tr[t->u0].rseg;
01933 v1 = seg[t->lseg].next;
01934
01935 retval = SP_2UP_LEFT;
01936 if ((dir == TR_FROM_UP) && (t->u0 == from))
01937 {
01938 do_switch = true;
01939 mnew = make_new_monotone_poly(mcur, v1, v0);
01940 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01941 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
01942 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
01943 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
01944 }
01945 else
01946 {
01947 mnew = make_new_monotone_poly(mcur, v0, v1);
01948 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01949 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01950 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01951 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
01952 }
01953 }
01954 else
01955 {
01956 v0 = t->rseg;
01957 v1 = tr[t->u0].rseg;
01958 retval = SP_2UP_RIGHT;
01959 if ((dir == TR_FROM_UP) && (t->u1 == from))
01960 {
01961 do_switch = true;
01962 mnew = make_new_monotone_poly(mcur, v1, v0);
01963 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01964 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
01965 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
01966 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
01967 }
01968 else
01969 {
01970 mnew = make_new_monotone_poly(mcur, v0, v1);
01971 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01972 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
01973 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01974 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
01975 }
01976 }
01977 }
01978 }
01979 else if ((t->u0 > 0) || (t->u1 > 0))
01980 {
01981 if ((t->d0 > 0) && (t->d1 > 0))
01982 {
01983 if (_equal_to(&t->hi, &seg[t->lseg].v0))
01984 {
01985 v0 = tr[t->d1].lseg;
01986 v1 = t->lseg;
01987 retval = SP_2DN_LEFT;
01988 if (!((dir == TR_FROM_DN) && (t->d0 == from)))
01989 {
01990 do_switch = true;
01991 mnew = make_new_monotone_poly(mcur, v1, v0);
01992 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
01993 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
01994 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
01995 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
01996 }
01997 else
01998 {
01999 mnew = make_new_monotone_poly(mcur, v0, v1);
02000 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
02001 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
02002 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
02003 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
02004 }
02005 }
02006 else
02007 {
02008 v0 = tr[t->d1].lseg;
02009 v1 = seg[t->rseg].next;
02010
02011 retval = SP_2DN_RIGHT;
02012 if ((dir == TR_FROM_DN) && (t->d1 == from))
02013 {
02014 do_switch = true;
02015 mnew = make_new_monotone_poly(mcur, v1, v0);
02016 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
02017 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
02018 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
02019 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
02020 }
02021 else
02022 {
02023 mnew = make_new_monotone_poly(mcur, v0, v1);
02024 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
02025 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
02026 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
02027 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
02028 }
02029 }
02030 }
02031 else
02032 {
02033 if (_equal_to(&t->hi, &seg[t->lseg].v0) &&
02034 _equal_to(&t->lo, &seg[t->rseg].v0))
02035 {
02036 v0 = t->rseg;
02037 v1 = t->lseg;
02038 retval = SP_SIMPLE_LRDN;
02039 if (dir == TR_FROM_UP)
02040 {
02041 do_switch = true;
02042 mnew = make_new_monotone_poly(mcur, v1, v0);
02043 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
02044 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
02045 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
02046 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
02047 }
02048 else
02049 {
02050 mnew = make_new_monotone_poly(mcur, v0, v1);
02051 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
02052 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
02053 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
02054 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
02055 }
02056 }
02057 else if (_equal_to(&t->hi, &seg[t->rseg].v1) &&
02058 _equal_to(&t->lo, &seg[t->lseg].v1))
02059 {
02060 v0 = seg[t->rseg].next;
02061 v1 = seg[t->lseg].next;
02062
02063 retval = SP_SIMPLE_LRUP;
02064 if (dir == TR_FROM_UP)
02065 {
02066 do_switch = true;
02067 mnew = make_new_monotone_poly(mcur, v1, v0);
02068 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
02069 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
02070 traverse_polygon(mnew, t->d1, trnum, TR_FROM_UP);
02071 traverse_polygon(mnew, t->d0, trnum, TR_FROM_UP);
02072 }
02073 else
02074 {
02075 mnew = make_new_monotone_poly(mcur, v0, v1);
02076 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
02077 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
02078 traverse_polygon(mnew, t->u0, trnum, TR_FROM_DN);
02079 traverse_polygon(mnew, t->u1, trnum, TR_FROM_DN);
02080 }
02081 }
02082 else
02083 {
02084 retval = SP_NOSPLIT;
02085 traverse_polygon(mcur, t->u0, trnum, TR_FROM_DN);
02086 traverse_polygon(mcur, t->d0, trnum, TR_FROM_UP);
02087 traverse_polygon(mcur, t->u1, trnum, TR_FROM_DN);
02088 traverse_polygon(mcur, t->d1, trnum, TR_FROM_UP);
02089 }
02090 }
02091 }
02092
02093 return retval;
02094 }
02095
02096
02097
02098
02099
02100
02101
02102 void Triangulator::
02103 triangulate_monotone_polygons(int nvert, int nmonpoly) {
02104 int i;
02105 point_t ymax, ymin;
02106 int p, vfirst, posmax, posmin, v;
02107 int vcount, processed;
02108
02109 #ifdef DEBUG
02110 for (i = 0; i < nmonpoly; i++)
02111 {
02112 fprintf(stderr, "\n\nPolygon %d: ", i);
02113 vfirst = mchain[mon[i]].vnum;
02114 p = mchain[mon[i]].next;
02115 fprintf (stderr, "%d ", mchain[mon[i]].vnum);
02116 while (mchain[p].vnum != vfirst)
02117 {
02118 fprintf(stderr, "%d ", mchain[p].vnum);
02119 if (mchain[p].vnum == -1) {
02120 fprintf(stderr, " xx");
02121 break;
02122 }
02123 p = mchain[p].next;
02124 }
02125 }
02126 fprintf(stderr, "\n");
02127 #endif
02128
02129 for (i = 0; i < nmonpoly; i++)
02130 {
02131 vcount = 1;
02132 processed = false;
02133 vfirst = mchain[mon[i]].vnum;
02134 if (vfirst <= 0) {
02135 return;
02136 }
02137 ymin = vert[vfirst].pt;
02138 ymax = ymin;
02139 posmin = mon[i];
02140 posmax = posmin;
02141 mchain[mon[i]].marked = true;
02142 p = mchain[mon[i]].next;
02143 while ((v = mchain[p].vnum) != vfirst)
02144 {
02145 if (v <= 0) {
02146 return;
02147 }
02148 if (mchain[p].marked)
02149 {
02150 processed = true;
02151 break;
02152 }
02153 else
02154 mchain[p].marked = true;
02155
02156 if (_greater_than(&vert[v].pt, &ymax))
02157 {
02158 ymax = vert[v].pt;
02159 posmax = p;
02160 }
02161 if (_less_than(&vert[v].pt, &ymin))
02162 {
02163 ymin = vert[v].pt;
02164 posmin = p;
02165 }
02166 p = mchain[p].next;
02167 vcount++;
02168 }
02169
02170 if (processed)
02171 continue;
02172
02173 if (vcount == 3)
02174 {
02175 _result.push_back(Triangle(this, mchain[p].vnum,
02176 mchain[mchain[p].next].vnum,
02177 mchain[mchain[p].prev].vnum));
02178 }
02179 else
02180 {
02181 v = mchain[mchain[posmax].next].vnum;
02182 if (_equal_to(&vert[v].pt, &ymin))
02183 {
02184 triangulate_single_polygon(nvert, posmax, TRI_LHS);
02185 }
02186 else
02187 triangulate_single_polygon(nvert, posmax, TRI_RHS);
02188 }
02189 }
02190 }
02191
02192
02193
02194
02195
02196
02197 void Triangulator::
02198 triangulate_single_polygon(int nvert, int posmax, int side) {
02199 int v;
02200 vector_int rc;
02201 int ri;
02202 int endv, tmp, vpos;
02203
02204
02205
02206 if (side == TRI_RHS)
02207 {
02208 rc.push_back(mchain[posmax].vnum);
02209 tmp = mchain[posmax].next;
02210 rc.push_back(mchain[tmp].vnum);
02211 ri = 1;
02212
02213 vpos = mchain[tmp].next;
02214 v = mchain[vpos].vnum;
02215
02216 if ((endv = mchain[mchain[posmax].prev].vnum) == 0)
02217 endv = nvert;
02218 }
02219 else
02220 {
02221 tmp = mchain[posmax].next;
02222 rc.push_back(mchain[tmp].vnum);
02223 tmp = mchain[tmp].next;
02224 rc.push_back(mchain[tmp].vnum);
02225 ri = 1;
02226
02227 vpos = mchain[tmp].next;
02228 v = mchain[vpos].vnum;
02229
02230 endv = mchain[posmax].vnum;
02231 }
02232
02233 while ((v != endv) || (ri > 1))
02234 {
02235
02236 if (v <= 0) {
02237
02238 return;
02239 }
02240 if (ri > 0)
02241 {
02242 PN_stdfloat crossResult = CROSS(vert[v].pt, vert[rc[ri - 1]].pt,
02243 vert[rc[ri]].pt);
02244 if ( crossResult >= 0 )
02245 {
02246 if ( crossResult > 0)
02247 _result.push_back(Triangle(this, rc[ri - 1], rc[ri], v));
02248
02249 ri--;
02250 rc.pop_back();
02251 nassertv(ri + 1 == (int)rc.size());
02252 }
02253 else
02254 {
02255 ri++;
02256 rc.push_back(v);
02257 nassertv(ri + 1 == (int)rc.size());
02258 vpos = mchain[vpos].next;
02259 v = mchain[vpos].vnum;
02260 }
02261 }
02262 else
02263 {
02264 ri++;
02265 rc.push_back(v);
02266 nassertv(ri + 1 == (int)rc.size());
02267 vpos = mchain[vpos].next;
02268 v = mchain[vpos].vnum;
02269 }
02270 }
02271
02272
02273 _result.push_back(Triangle(this, rc[ri - 1], rc[ri], v));
02274 ri--;
02275 }
02276
02277