00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdmisc.h"
00027
00028 #include "nel/misc/polygon.h"
00029 #include "nel/misc/plane.h"
00030 #include "nel/misc/triangle.h"
00031
00032
00033 using namespace std;
00034 using namespace NLMISC;
00035
00036
00037 namespace NLMISC
00038 {
00039
00040
00041
00042
00043
00044
00045
00046 CPolygon::CPolygon(const CVector &a, const CVector &b, const CVector &c)
00047 {
00048 Vertices.reserve(3);
00049 Vertices.push_back(a);
00050 Vertices.push_back(b);
00051 Vertices.push_back(c);
00052 }
00053
00054
00055
00056 void CPolygon::clip(const CPlane *planes, uint nPlanes)
00057 {
00058 if(nPlanes==0 || getNumVertices()==0)
00059 return;
00060
00061
00062
00063 static vector<CVector> tab0, tab1;
00064 tab0.resize(getNumVertices()+nPlanes);
00065 tab1.resize(getNumVertices()+nPlanes);
00066
00067 copy(Vertices.begin(), Vertices.end(), tab0.begin());
00068 CVector *in=&(*tab0.begin()), *out= &(*tab1.begin());
00069 sint nin= getNumVertices(), nout;
00070 for(sint i=0;i<(sint)nPlanes;i++)
00071 {
00072 nout= planes[i].clipPolygonBack(in, out, nin);
00073 swap(in, out);
00074 nin= nout;
00075 if(nin==0)
00076 break;
00077 }
00078
00079
00080 Vertices.resize(nin);
00081 if(nin>0)
00082 {
00083 memcpy(&(*Vertices.begin()), in, nin*sizeof(CVector));
00084 }
00085 }
00086
00087
00088
00089 void CPolygon::clip(const std::vector<CPlane> &planes)
00090 {
00091 if(planes.size()==0)
00092 return;
00093 clip(&(*planes.begin()), planes.size());
00094 }
00095
00096
00097
00098
00099 void CPolygon::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00100 {
00101 f.serialVersion(0);
00102 f.serialCont(Vertices);
00103 }
00104
00105
00106 void CPolygon::getBestTriplet(uint &index0,uint &index1,uint &index2)
00107 {
00108 nlassert(Vertices.size() >= 3);
00109 uint i, j, k;
00110 float bestArea = 0.f;
00111 const uint numVerts = Vertices.size();
00112 for (i = 0; i < numVerts; ++i)
00113 {
00114 for (j = 0; j < numVerts; ++j)
00115 {
00116 if (i != j)
00117 {
00118 for (k = 0; k < numVerts; ++k)
00119 {
00120 if (k != i && k != j)
00121 {
00122 CVector v0 = Vertices[j] - Vertices[i];
00123 CVector v1 = Vertices[k] - Vertices[i];
00124 float area = (v0 ^ v1).norm();
00125 if (area > bestArea)
00126 {
00127 bestArea = area;
00128 index0 = i;
00129 index1 = j;
00130 index2 = k;
00131 }
00132 }
00133 }
00134 }
00135 }
00136 }
00137
00138 }
00139
00140
00141 void CPolygon::buildBasis(CMatrix &dest)
00142 {
00143 nlassert(Vertices.size() > 3);
00144 uint i1, i2, i3;
00145 getBestTriplet(i1, i2, i3);
00146 CVector v1 = (Vertices[i2] - Vertices[i1]).normed();
00147 CVector v2 = (Vertices[i3] - Vertices[i1]).normed();
00148 CVector K = v2 ^ v1;
00149 CVector I = v1 - (v1 * K) * v1;
00150 CVector J = K ^ I;
00151 dest.setRot(I, J, K);
00152 dest.setPos(Vertices[i1]);
00153 }
00154
00155
00156
00157 class CConcavePolygonsVertexDesc
00158 {
00159 public:
00160
00161 CConcavePolygonsVertexDesc (float length, uint index)
00162 {
00163 Length = length;
00164 Index = index;
00165 }
00166
00167
00168 float Length;
00169
00170
00171 uint Index;
00172 };
00173 typedef std::map<float, CConcavePolygonsVertexDesc> TCConcavePolygonsVertexMap;
00174
00175
00176
00177 bool CPolygon::toConvexPolygonsEdgeIntersect (const CVector2f& a0, const CVector2f& a1, const CVector2f& b0, const CVector2f& b1)
00178 {
00179 float Aa = (a0.y - a1.y) / (a0.x - a1.x);
00180 float Ba = a0.y - a0.x * Aa;
00181 float Ab = (b0.y - b1.y) / (b0.x - b1.x);
00182 float Bb = b0.y - b0.x * Ab;
00183
00184
00185 CVector2f intersection;
00186 intersection.x = (Bb - Ba) / (Aa - Ab);
00187 intersection.y = Aa * intersection.x + Ba;
00188
00189
00190 return ( ( (a0-intersection)*(a1-intersection) < 0 ) && ( (b0-intersection)*(b1-intersection) < 0 ) );
00191 }
00192
00193
00194
00195 class CBSPNode2v
00196 {
00197 public:
00198 CBSPNode2v ()
00199 {
00200 Back = NULL;
00201 Front = NULL;
00202 }
00203 CBSPNode2v ( const CPlane &plane, CVector p0, CVector p1, uint v0, uint v1 ) : Plane (plane), P0 (p0), P1 (p1)
00204 {
00205 Back = NULL;
00206 Front = NULL;
00207 Parent = NULL;
00208 V0 = v0;
00209 V1 = v1;
00210 }
00211 ~CBSPNode2v ()
00212 {
00213 if (Front)
00214 delete Front;
00215 if (Back)
00216 delete Back;
00217 }
00218
00219 void insert (CBSPNode2v *node)
00220 {
00221
00222 bool p0Front = (Plane * node->P0) > 0;
00223 bool p1Front = (Plane * node->P1) > 0;
00224 if (p0Front && p1Front)
00225 {
00226
00227 if (Front)
00228 Front->insert (node);
00229 else
00230 {
00231
00232 Front = node;
00233 node->Parent = this;
00234 }
00235 }
00236 else if ((!p0Front) && (!p1Front))
00237 {
00238
00239 if (Back)
00240 Back->insert (node);
00241 else
00242 {
00243
00244 Back = node;
00245 node->Parent = this;
00246 }
00247 }
00248 else
00249 {
00250
00251 CVector newVertex = Plane.intersect (node->P0, node->P1);
00252
00253
00254 CBSPNode2v *newNode = new CBSPNode2v (node->Plane, node->P0, newVertex, node->V0, node->V1);
00255
00256
00257 node->P0 = newVertex;
00258
00259
00260 CBSPNode2v **p0Parent;
00261 CBSPNode2v **p1Parent;
00262
00263
00264 if (p0Front)
00265 {
00266 p0Parent = &Front;
00267 p1Parent = &Back;
00268 }
00269 else
00270 {
00271 p0Parent = &Back;
00272 p1Parent = &Front;
00273 }
00274
00275
00276 if (*p0Parent)
00277 {
00278 (*p0Parent)->insert (newNode);
00279 }
00280 else
00281 {
00282 *p0Parent = newNode;
00283 newNode->Parent = this;
00284 }
00285
00286
00287 if (*p1Parent)
00288 {
00289 (*p1Parent)->insert (node);
00290 }
00291 else
00292 {
00293 *p1Parent = node;
00294 node->Parent = this;
00295 }
00296 }
00297 }
00298
00299 bool intersect (const CVector &p0, const CVector &p1, uint v0, uint v1) const
00300 {
00301
00302 bool p0Front = (Plane * p0) > 0;
00303 bool p1Front = (Plane * p1) > 0;
00304
00305 if (p0Front != p1Front)
00306 if ( (v0 != V0) && (v0 != V1) && (v1 != V0) && (v1 != V1) )
00307 if (CPolygon::toConvexPolygonsEdgeIntersect ((CVector2f) P0, (CVector2f) P1, (CVector2f) p0, (CVector2f) p1))
00308 return true;
00309
00310 if (p0Front || p1Front)
00311 {
00312 if (Front)
00313 if (Front->intersect (p0, p1, v0, v1))
00314 return true;
00315 }
00316
00317 if ((!p0Front) || (!p1Front))
00318 {
00319 if (Back)
00320 if (Back->intersect (p0, p1, v0, v1))
00321 return true;
00322 }
00323
00324 return false;
00325 }
00326
00327 CBSPNode2v *Back, *Front, *Parent;
00328 CPlane Plane;
00329 CVector P0;
00330 CVector P1;
00331 uint V0;
00332 uint V1;
00333 };
00334
00335
00336
00337 bool CPolygon::toConvexPolygonsLeft (const std::vector<CVector> &vertex, uint a, uint b, uint c)
00338 {
00339 return ( (vertex[b].x - vertex[a].x) * (vertex[c].y - vertex[a].y) - (vertex[c].x - vertex[a].x) * (vertex[b].y - vertex[a].y) ) < 0;
00340 }
00341
00342
00343
00344 bool CPolygon::toConvexPolygonsLeftOn (const std::vector<CVector> &vertex, uint a, uint b, uint c)
00345 {
00346 return ( (vertex[b].x - vertex[a].x) * (vertex[c].y - vertex[a].y) - (vertex[c].x - vertex[a].x) * (vertex[b].y - vertex[a].y) ) <= 0;
00347 }
00348
00349
00350
00351 bool CPolygon::toConvexPolygonsInCone (const std::vector<CVector> &vertex, uint a, uint b)
00352 {
00353
00354 uint a0 = a+1;
00355 if (a0==vertex.size())
00356 a0=0;
00357 uint a1;
00358 if (a==0)
00359 a1=vertex.size()-1;
00360 else
00361 a1= a-1;
00362
00363 if (toConvexPolygonsLeftOn (vertex, a, a1, a0) )
00364 {
00365 return toConvexPolygonsLeft ( vertex, a, b, a0) && toConvexPolygonsLeft ( vertex, b, a, a1);
00366 }
00367 else
00368 {
00369 return !( toConvexPolygonsLeft ( vertex, a, b, a1) && toConvexPolygonsLeft ( vertex, b, a, a0) );
00370 }
00371 }
00372
00373
00374
00375 bool CPolygon::toConvexPolygonsDiagonal (const std::vector<CVector> &vertex, const CBSPNode2v &bsp, uint a, uint b)
00376 {
00377
00378 if ( ( (b - a) == 1) || ( (a - b) == 1) || ( (a==0) && (b ==(vertex.size()-1))) || ( (b==0) && (a ==(vertex.size()-1))) )
00379 return true;
00380
00381
00382 if (toConvexPolygonsInCone (vertex, a, b) && toConvexPolygonsInCone (vertex, b, a))
00383 {
00384
00385 return !bsp.intersect (vertex[a], vertex[b], a, b);
00386 }
00387 return false;
00388 }
00389
00390
00391
00392 void CPolygon::toConvexPolygonsLocalAndBSP (std::vector<CVector> &localVertices, CBSPNode2v &root, const CMatrix &basis) const
00393 {
00394
00395 CMatrix invert = basis;
00396 invert.invert ();
00397
00398
00399 uint vertexCount = Vertices.size();
00400 TCConcavePolygonsVertexMap vertexMap;
00401 localVertices.resize (vertexCount);
00402 uint i, j;
00403
00404
00405 for (i=0; i<vertexCount; i++)
00406 {
00407 CVector local = invert*Vertices[i];
00408 localVertices[i] = CVector (local.x, local.y, 0);
00409 }
00410
00411
00412 i=0;
00413 j=Vertices.size()-1;
00414 CVector normal = localVertices[i] - localVertices[j];
00415 normal = normal ^ CVector::K;
00416 CPlane clipPlane;
00417 clipPlane.make(normal, localVertices[i]);
00418
00419
00420 root = CBSPNode2v (clipPlane, localVertices[i], localVertices[j], i, j);
00421
00422
00423 j=i++;
00424 for (; i<Vertices.size(); i++)
00425 {
00426
00427 normal = localVertices[i] - localVertices[j];
00428 normal = normal ^ CVector::K;
00429 clipPlane.make(normal, localVertices[i]);
00430
00431
00432 root.insert ( new CBSPNode2v (clipPlane, localVertices[i], localVertices[j], i, j) );
00433
00434 j=i;
00435 }
00436 }
00437
00438
00439
00440 bool CPolygon::toConvexPolygons (std::list<CPolygon>& outputPolygons, const CMatrix& basis) const
00441 {
00442
00443 if (Vertices.size()>2)
00444 {
00445
00446 std::vector<CVector> localVertices;
00447
00448
00449 CBSPNode2v root;
00450
00451
00452 toConvexPolygonsLocalAndBSP (localVertices, root, basis);
00453
00454
00455 std::list<uint> vertexList;
00456 uint i;
00457 for (i=0; i<Vertices.size(); i++)
00458 vertexList.push_back (i);
00459
00460
00461 std::list<uint>::iterator current=vertexList.begin();
00462 std::list<uint>::iterator begin=vertexList.begin();
00463 do
00464 {
00465 again:;
00466
00467 bool found = false;
00468
00469
00470 std::list<uint>::iterator first = current;
00471 std::list<uint>::iterator lastPreviousPrevious=current;
00472 std::list<uint>::iterator lastPrevious=current;
00473 lastPrevious++;
00474 if (lastPrevious==vertexList.end())
00475 lastPrevious = vertexList.begin();
00476 std::list<uint>::iterator currentNext = lastPrevious;
00477 std::list<uint>::iterator last = lastPrevious;
00478 last++;
00479 if (last==vertexList.end())
00480 last = vertexList.begin();
00481 while (last != current)
00482 {
00483
00484 if (
00485 (toConvexPolygonsDiagonal (localVertices, root, *lastPreviousPrevious, *last)) &&
00486 (toConvexPolygonsDiagonal (localVertices, root, *currentNext, *last)) &&
00487 (toConvexPolygonsDiagonal (localVertices, root, *last, *current))
00488 )
00489 {
00490
00491 found = true;
00492 }
00493 else
00494 {
00495
00496 last = lastPrevious;
00497 lastPrevious = lastPreviousPrevious;
00498 break;
00499 }
00500
00501
00502 lastPreviousPrevious = lastPrevious;
00503 lastPrevious = last++;
00504 if (last==vertexList.end())
00505 last = vertexList.begin();
00506 }
00507
00508
00509 if (last==current)
00510 {
00511
00512 outputPolygons.push_back (CPolygon());
00513 CPolygon &back = outputPolygons.back ();
00514 back.Vertices.reserve (vertexList.size());
00515
00516
00517 current=vertexList.begin();
00518 while (current!=vertexList.end())
00519 {
00520 back.Vertices.push_back (Vertices[*current]);
00521 current++;
00522 }
00523
00524
00525 return true;
00526 }
00527 else
00528 {
00529 std::list<uint>::iterator firstNext = current;
00530 std::list<uint>::iterator firstNextNext = currentNext;
00531 if (first != vertexList.begin())
00532 first--;
00533 else
00534 {
00535 first = vertexList.end();
00536 first--;
00537 }
00538
00539 while (current != first)
00540 {
00541
00542 if (
00543 (toConvexPolygonsDiagonal (localVertices, root, *firstNextNext, *first)) &&
00544 (toConvexPolygonsDiagonal (localVertices, root, *lastPrevious, *first)) &&
00545 (toConvexPolygonsDiagonal (localVertices, root, *last, *first))
00546 )
00547 {
00548
00549 found = true;
00550 }
00551 else
00552 {
00553
00554 first = firstNext;
00555 break;
00556 }
00557
00558
00559 firstNextNext = firstNext;
00560 firstNext = first;
00561 if (first==vertexList.begin())
00562 {
00563 first = vertexList.end();
00564 first--;
00565 }
00566 else
00567 first--;
00568 }
00569 }
00570
00571
00572 if (found)
00573 {
00574
00575 outputPolygons.push_back (CPolygon());
00576 CPolygon &back = outputPolygons.back ();
00577
00578
00579 uint vertexCount = 1;
00580 current = first;
00581 while (current != last)
00582 {
00583 vertexCount++;
00584 current++;
00585 if (current == vertexList.end())
00586 current = vertexList.begin();
00587 }
00588
00589
00590 back.Vertices.reserve (vertexCount);
00591
00592
00593 back.Vertices.push_back (Vertices[*first]);
00594 first++;
00595 if (first == vertexList.end())
00596 first = vertexList.begin();
00597 while (first != last)
00598 {
00599 back.Vertices.push_back (Vertices[*first]);
00600
00601
00602 first = vertexList.erase (first);
00603 if (first == vertexList.end())
00604 first = vertexList.begin();
00605 nlassert (first != vertexList.end());
00606 }
00607 back.Vertices.push_back (Vertices[*first]);
00608 current = begin = last;
00609 goto again;
00610 }
00611
00612
00613 current++;
00614 if (current == vertexList.end())
00615 current = vertexList.begin ();
00616 }
00617 while (current != begin);
00618 }
00619 return false;
00620 }
00621
00622
00623
00624 bool CPolygon::chain (const std::vector<CPolygon> &other, const CMatrix& basis)
00625 {
00626
00627 std::vector<CVector> localVertices;
00628
00629
00630 CBSPNode2v root;
00631
00632
00633 toConvexPolygonsLocalAndBSP (localVertices, root, basis);
00634
00635
00636 std::vector<std::vector<CVector> > localVerticesOther (other.size());
00637
00638
00639 std::vector<CBSPNode2v> rootOther (other.size());
00640
00641
00642 std::vector<CPolygon> copy = other;
00643
00644
00645 CPolygon mainCopy = *this;
00646
00647
00648 uint o;
00649 for (o=0; o<other.size(); o++)
00650 {
00651
00652 other[o].toConvexPolygonsLocalAndBSP (localVerticesOther[o], rootOther[o], basis);
00653 }
00654
00655
00656 uint thisCount = Vertices.size();
00657 uint i, j;
00658 for (o=0; o<other.size(); o++)
00659 {
00660 uint otherCount = other[o].Vertices.size();
00661
00662
00663 for (i=0; i<thisCount; i++)
00664 {
00665 for (j=0; j<otherCount; j++)
00666 {
00667
00668 if (!root.intersect (localVertices[i], localVerticesOther[o][j], i, 0xffffffff))
00669 {
00670
00671 uint otherO;
00672 for (otherO=0; otherO<other.size(); otherO++)
00673 {
00674
00675 if (rootOther[otherO].intersect (localVertices[i], localVerticesOther[o][j], 0xffffffff, (otherO == o)?j:0xffffffff))
00676 break;
00677 }
00678
00679
00680 if (otherO==other.size())
00681 {
00682
00683 mainCopy.Vertices.insert (mainCopy.Vertices.begin()+i, 2+otherCount, CVector());
00684
00685
00686 mainCopy.Vertices[i] = mainCopy.Vertices[i+otherCount+2];
00687
00688
00689 uint k;
00690 for (k=0; k<otherCount; k++)
00691 {
00692 uint index = j+k;
00693 if (index>=otherCount)
00694 index -= otherCount;
00695 mainCopy.Vertices[i+k+1] = copy[o].Vertices[index];
00696 }
00697
00698
00699 mainCopy.Vertices[i+otherCount+1] = copy[o].Vertices[j];
00700 break;
00701 }
00702 }
00703 }
00704 if (j!=otherCount)
00705 break;
00706 }
00707
00708
00709 if (i==thisCount)
00710 {
00711
00712 uint otherToCheck;
00713 for (otherToCheck=o+1; otherToCheck<other.size(); otherToCheck++)
00714 {
00715 uint otherToCheckCount = other[otherToCheck].Vertices.size();
00716 for (i=0; i<otherToCheckCount; i++)
00717 {
00718 for (j=0; j<otherCount; j++)
00719 {
00720
00721 if (!rootOther[otherToCheck].intersect (localVerticesOther[otherToCheck][i], localVerticesOther[o][j], i, 0xffffffff))
00722 {
00723
00724 uint otherO;
00725 for (otherO=0; otherO<other.size(); otherO++)
00726 {
00727
00728 if (rootOther[otherO].intersect (localVerticesOther[otherToCheck][i], localVerticesOther[o][j], (otherToCheck == otherO)?i:0xffffffff, (otherO == o)?j:0xffffffff))
00729 break;
00730 }
00731
00732
00733 if (otherO==other.size())
00734 {
00735
00736 copy[otherToCheck].Vertices.insert (copy[otherToCheck].Vertices.begin()+i, 2+otherCount, CVector());
00737
00738
00739 copy[otherToCheck].Vertices[i] = copy[otherToCheck].Vertices[i+otherCount+2];
00740
00741
00742 uint k;
00743 for (k=0; k<otherCount; k++)
00744 {
00745 uint index = j+k;
00746 if (index>=otherCount)
00747 index -= otherCount;
00748 copy[otherToCheck].Vertices[i+k+1] = copy[otherO].Vertices[index];
00749 }
00750
00751
00752 copy[otherToCheck].Vertices[i+otherCount+1] = copy[otherO].Vertices[j];
00753 break;
00754 }
00755 }
00756 }
00757 if (j!=otherCount)
00758 break;
00759 }
00760 if (i!=otherToCheckCount)
00761 break;
00762 }
00763 if (otherToCheck==other.size())
00764 {
00765
00766 return false;
00767 }
00768 }
00769 }
00770
00771
00772 *this = mainCopy;
00773 return true;
00774 }
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 CPolygon2D::CPolygon2D(const CPolygon &src, const CMatrix &projMat)
00786 {
00787 uint size = src.Vertices.size();
00788 Vertices.resize(size);
00789 for (uint k = 0; k < size; ++k)
00790 {
00791 CVector proj = projMat * src.Vertices[k];
00792 Vertices[k].set(proj.x, proj.y);
00793 }
00794 }
00795
00796
00797
00798 bool CPolygon2D::isConvex()
00799 {
00800 bool Front = true, Back = false;
00801
00802
00803 uint numVerts = Vertices.size();
00804 if (numVerts < 3) return true;
00805 CVector segStart, segEnd;
00806 CPlane clipPlane;
00807 for (TVec2fVect::const_iterator it = Vertices.begin(); it != Vertices.end(); ++it)
00808 {
00809 segStart.set(it->x, it->y, 0);
00810 segEnd.set((it + 1)->x, (it + 1)->y, 0);
00811 float n = (segStart - segEnd).norm();
00812 if (n != 0)
00813 {
00814 clipPlane.make(segStart, segEnd, (n > 10 ? n : 10) * CVector::K + segStart);
00815
00816 for (TVec2fVect::const_iterator it2 = Vertices.begin(); it2 != Vertices.end(); ++it2)
00817 {
00818 if (it2 != it && it2 != (it + 1))
00819 {
00820
00821 float dist = clipPlane * CVector(it2->x, it2-> y, 0);
00822 if (dist != 0)
00823 {
00824 if (dist > 0) Front = true; else Back = true;
00825 if (Front && Back) return false;
00826 }
00827 }
00828 }
00829 }
00830 }
00831 return true;
00832 }
00833
00834
00835
00836 void CPolygon2D::buildConvexHull(CPolygon2D &dest) const
00837 {
00838 nlassert(&dest != this);
00839
00840 if (this->Vertices.size() == 3)
00841 {
00842 dest = *this;
00843 return;
00844 }
00845 uint k, l;
00846 uint numVerts = Vertices.size();
00847 CVector2f p, curr, prev;
00848 uint pIndex, p1Index, p2Index, pCurr, pPrev;
00849
00850 nlassert(numVerts >= 3);
00851 dest.Vertices.clear();
00852
00853 typedef std::set<uint> TIndexSet;
00854 TIndexSet leftIndex;
00855 for (k = 0; k < Vertices.size(); ++k)
00856 {
00857 leftIndex.insert(k);
00858 }
00859
00860
00861
00862 pIndex = 0;
00863 p = Vertices[0];
00864 for (k = 1; k < numVerts; ++k)
00865 {
00866 if (Vertices[k].y < p.y)
00867 {
00868 pIndex = k;
00869 p = Vertices[k];
00870 }
00871 }
00872
00873 leftIndex.erase(pIndex);
00874
00875
00876 float bestCP = 1.1f;
00877 p1Index = p2Index = pIndex;
00878
00879 for (k = 0; k < numVerts; ++k)
00880 {
00881 if (k != pIndex)
00882 {
00883 for (l = 0; l < numVerts; ++l)
00884 {
00885 if (l != pIndex && l != k)
00886 {
00887 CVector2f seg1 = (Vertices[l] - p).normed();
00888 CVector2f seg2 = (Vertices[k] - p).normed();
00889
00890
00891
00892 float n = seg1 * seg2;
00893 if (n < bestCP)
00894 {
00895 p1Index = l;
00896 p2Index = k;
00897 bestCP = n;
00898 }
00899 }
00900 }
00901 }
00902 }
00903
00904
00905 leftIndex.erase(p2Index);
00906
00907
00908
00909
00910 pCurr = p2Index;
00911 pPrev = pIndex;
00912
00913 curr = Vertices[pCurr];
00914 prev = Vertices[pPrev];
00915
00916
00917 dest.Vertices.push_back(Vertices[p1Index]);
00918 dest.Vertices.push_back(prev);
00919 dest.Vertices.push_back(curr);
00920
00921 uint step = 0;
00922
00923 for(;;)
00924 {
00925 bestCP = 1.1f;
00926 CVector2f seg2 = (prev - curr).normed();
00927 TIndexSet::const_iterator bestIt = leftIndex.end();
00928 for (TIndexSet::const_iterator it = leftIndex.begin(); it != leftIndex.end(); ++it)
00929 {
00930 if (step == 0 && *it == p1Index) continue;
00931 CVector2f seg1 = (Vertices[*it] - curr).normed();
00932 float n = seg1 * seg2;
00933 if (n < bestCP)
00934 {
00935 bestCP = n;
00936 bestIt = it;
00937 }
00938 }
00939
00940 nlassert(bestIt != leftIndex.end());
00941 if (*bestIt == p1Index)
00942 {
00943 return;
00944 }
00945 prev = curr;
00946 curr = Vertices[*bestIt];
00947 pPrev = pCurr;
00948 pCurr = *bestIt;
00949
00950 dest.Vertices.push_back(curr);
00951 ++step;
00952 leftIndex.erase(bestIt);
00953 }
00954 }
00955
00956
00957
00958
00959 void CPolygon2D::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00960 {
00961 (void)f.serialVersion(0);
00962 f.serialCont(Vertices);
00963 }
00964
00965
00967
00968 {
00969 nlassert(Vertices.size() >= 3);
00970 uint i, j, k;
00971 float bestArea = 0.f;
00972 const uint numVerts = Vertices.size();
00973 for (i = 0; i < numVerts; ++i)
00974 {
00975 for (j = 0; j < numVerts; ++j)
00976 {
00977 if (i != j)
00978 {
00979 for (k = 0; k < numVerts; ++k)
00980 {
00981 if (k != i && k != j)
00982 {
00983 CVector2f v0 = Vertices[j] - Vertices[i];
00984 CVector2f v1 = Vertices[k] - Vertices[i];
00985 float area = fabsf((CVector(v0.x, v0.y, 0) ^ CVector(v1.x, v1.y, 0)).norm());
00986 if (area > bestArea)
00987 {
00988 bestArea = area;
00989 index0 = i;
00990 index1 = j;
00991 index2 = k;
00992 }
00993 }
00994 }
00995 }
00996 }
00997 }
00998 }
00999
01000
01002
01003 static void ScanEdge(CPolygon2D::TRasterVect &outputVect, sint topY, const CVector2f &v1, const CVector2f &v2, bool rightEdge = true)
01004 {
01005 const uint rol16 = 65536;
01006 sint ceilY1 = (sint) ceilf(v1.y);
01007 sint height;
01008 float deltaX, deltaY;
01009 float fInverseSlope;
01010 sint iInverseSlope, iPosX;
01011
01012
01013 height = (sint) (ceilf(v2.y) - ceilY1);
01014 if (height <= 0) return;
01015
01016
01017 deltaY = v2.y - v1.y;
01018 deltaX = v2.x - v1.x;
01019 fInverseSlope = deltaX / deltaY;
01020
01021
01022 CPolygon2D::TRasterVect::iterator outputIt = outputVect.begin() + (ceilY1 - topY);
01023
01024
01025 iInverseSlope = (sint) (rol16 * fInverseSlope);
01026
01027
01028 iPosX = (int) (rol16 * (v1.x + fInverseSlope * (ceilY1 - v1.y)));
01029
01030 const CPolygon2D::TRasterVect::iterator endIt = outputIt + height;
01031 if (rightEdge)
01032 {
01033 do
01034 {
01035 outputIt->second = iPosX >> 16;
01036 iPosX += iInverseSlope;
01037 ++outputIt;
01038 }
01039 while (outputIt != endIt);
01040 }
01041 else
01042 {
01043 iPosX += (rol16 - 1);
01044 do
01045 {
01046 outputIt->first = iPosX >> 16;
01047 iPosX += iInverseSlope;
01048 ++outputIt;
01049 }
01050 while (outputIt != endIt);
01051 }
01052 }
01053
01054
01055
01056
01057 static inline CPolygon2D::TVec2fVect::const_iterator Next(const CPolygon2D::TVec2fVect::const_iterator &it, const CPolygon2D::TVec2fVect &cont)
01058 {
01059 nlassert(cont.size() != 0);
01060 if ((it + 1) == cont.end()) return cont.begin();
01061 return (it + 1);
01062 }
01063
01064
01065
01066
01067 static inline CPolygon2D::TVec2fVect::const_iterator Prev(const CPolygon2D::TVec2fVect::const_iterator &it, const CPolygon2D::TVec2fVect &cont)
01068 {
01069 nlassert(cont.size() != 0);
01070 if (it == cont.begin()) return cont.end() - 1;
01071 return (it - 1);
01072 }
01073
01074
01075 void CPolygon2D::computeBorders(TRasterVect &borders, sint &highestY)
01076 {
01077
01078 const TVec2fVect &V = Vertices;
01079 if (Vertices.size() < 3)
01080 {
01081 borders.clear();
01082 return;
01083 }
01084 bool ccw;
01085
01086
01087 float fHighest = V[0].y;
01088 float fLowest = fHighest;
01089
01090
01091 TVec2fVect::const_iterator pLowest = V.begin(), pHighest = V.begin();
01092 TVec2fVect::const_iterator it = V.begin() ;
01093 const TVec2fVect::const_iterator endIt = V.end();
01094 do
01095 {
01096 if (it->y > fLowest)
01097 {
01098 fLowest = it->y;
01099 pLowest = it;
01100 }
01101 else
01102 if (it->y < fHighest)
01103 {
01104 fHighest = it->y;
01105 pHighest = it;
01106 }
01107 ++it;
01108 }
01109 while (it != endIt);
01110
01111
01112 sint iHighest = (sint) ceilf(fHighest) ;
01113 sint iLowest = (sint) ceilf(fLowest) ;
01114
01115 highestY = iHighest;
01116
01117
01119 uint polyHeight = iLowest - iHighest;
01120 if (polyHeight <= 0)
01121 {
01122 borders.clear();
01123 return;
01124 }
01125
01126 borders.resize(polyHeight);
01127
01128
01129 TVec2fVect::const_iterator pHighestRight = pHighest;
01130
01131 while (Next(pHighestRight, V)->y == fHighest)
01132 {
01133 pHighestRight = Next(pHighestRight, V);
01134 }
01135
01136
01137 TVec2fVect::const_iterator pHighestLeft = Next(pHighestRight, V);
01138
01139 while (pHighestLeft->y != fHighest)
01140 {
01141 pHighestLeft = Next(pHighestLeft, V);
01142 }
01143
01144 TVec2fVect::const_iterator pPrevHighestLeft = Prev(pHighestLeft, V);
01145
01146
01147
01148
01149
01150 if (pHighestLeft->x != pHighestRight->x)
01151 {
01152
01153 if (pHighestLeft->x> pHighestRight->x)
01154 {
01155 ccw = true;
01156 std::swap(pHighestLeft, pHighestRight);
01157 }
01158 else
01159 {
01160 ccw = false;
01161 }
01162 }
01163 else
01164 {
01165
01166
01167
01168 const float deltaXN = Next(pHighestRight, V)->x - pHighestRight->x;
01169 const float deltaYN = Next(pHighestRight, V)->y - pHighestRight->y;
01170 const float deltaXP = pPrevHighestLeft->x - pHighestLeft->x;
01171 const float deltaYP = pPrevHighestLeft->y - pHighestLeft->y;
01172 if ((deltaXN * deltaYP - deltaYN * deltaXP) < 0)
01173 {
01174 ccw = true;
01175 std::swap(pHighestLeft, pHighestRight);
01176 }
01177 else
01178 {
01179 ccw = false;
01180 }
01181 }
01182
01183
01184
01185 TVec2fVect::const_iterator currV, nextV;
01186 if (!ccw)
01187 {
01188 currV = pHighestRight ;
01189
01190 do
01191 {
01192 nextV = Next(currV, V);
01193 ScanEdge(borders, iHighest, *currV, *nextV, true);
01194 currV = nextV;
01195 }
01196 while (currV != pLowest);
01197
01198
01199 do
01200 {
01201 nextV = Next(currV, V);
01202 ScanEdge(borders, iHighest, *nextV, *currV, false);
01203 currV = nextV;
01204 }
01205 while (currV != pHighestLeft);
01206 }
01207 else
01208 {
01209 currV = pHighestLeft;
01210
01211 do
01212 {
01213 nextV = Next(currV, V);
01214 ScanEdge(borders, iHighest, *currV, *nextV, false) ;
01215 currV = nextV;
01216 }
01217 while (currV != pLowest) ;
01218
01219
01220 do
01221 {
01222 nextV = Next(currV, V);
01223 ScanEdge(borders, iHighest, *nextV, *currV, true);
01224 currV = nextV;
01225 }
01226 while (currV != pHighestRight) ;
01227 }
01228 }
01229
01230
01232
01233 {
01234 float sum = 0.f;
01235 for (uint k = 0; k < Vertices.size(); ++k)
01236 {
01237 const CVector2f &p = Vertices[k];
01238 sum += a * p.x + b * p.y + c;
01239 }
01240 return sum;
01241 }
01242
01243
01244
01245 bool CPolygon2D::getNonNullSeg(uint &index) const
01246 {
01247 nlassert(Vertices.size() > 0);
01248 float bestLength = 0.f;
01249 sint bestIndex = -1;
01250 for (uint k = 0; k < Vertices.size() - 1; ++k)
01251 {
01252 float norm2 = (Vertices[k + 1] - Vertices[k]).sqrnorm();
01253 if ( norm2 > bestLength)
01254 {
01255 bestLength = norm2;
01256 bestIndex = (int) k;
01257 }
01258 }
01259 float norm2 = (Vertices[Vertices.size() - 1] - Vertices[0]).sqrnorm();
01260 if ( norm2 > bestLength)
01261 {
01262 index = Vertices.size() - 1;
01263 return true;
01264 }
01265
01266 if (bestIndex != -1)
01267 {
01268 index = bestIndex;
01269 return true;
01270 }
01271 else
01272 {
01273 return false;
01274 }
01275 }
01276
01277
01278
01279 void CPolygon2D::getLineEquation(uint index, float &a, float &b, float &c) const
01280 {
01281 nlassert(index < Vertices.size());
01282 const CVector2f &v0 = getSegRef0(index);
01283 const CVector2f &v1 = getSegRef1(index);
01284
01285 NLMISC::CVector2f seg = v0 - v1;
01286 a = seg.y;
01287 b = - seg.x;
01288 c = - v0.x * a - v0.y * b;
01289 }
01290
01291
01292 bool CPolygon2D::intersect(const CPolygon2D &other) const
01293 {
01294 nlassert(other.Vertices.size() > 0);
01295 uint nonNullSegIndex;
01297 if (getNonNullSeg(nonNullSegIndex))
01298 {
01299 float a0, b0, c0;
01300 getLineEquation(nonNullSegIndex, a0, b0, c0);
01301 float orient = sumDPAgainstLine(a0, b0, c0);
01302
01303 for (uint k = 0; k < Vertices.size(); ++k)
01304 {
01306 if ( (getSegRef0(k) - getSegRef1(k)).sqrnorm() == 0.f) continue;
01307
01309 float a, b, c;
01310 getLineEquation(k, a, b, c);
01311 uint l;
01312 for (l = 0; l < other.Vertices.size(); ++l)
01313 {
01314 const CVector2f &ov = other.Vertices[l];
01315 if ( orient * (ov.x * a + ov.y * b +c) > 0.f) break;
01316 }
01317 if (l == other.Vertices.size())
01318 {
01319 return false;
01320 }
01321 }
01322 return true;
01323 }
01324 else
01325 {
01326 return other.contains(Vertices[0]);
01327 }
01328 }
01329
01330
01331 bool CPolygon2D::contains(const CVector2f &p) const
01332 {
01333 nlassert(Vertices.size() > 0);
01334 uint nonNullSegIndex;
01336 if (getNonNullSeg(nonNullSegIndex))
01337 {
01338 float a0, b0, c0;
01339 getLineEquation(nonNullSegIndex, a0, b0, c0);
01340
01341 for (uint k = 0; k < Vertices.size(); ++k)
01342 {
01344 if ( (getSegRef0(k) - getSegRef1(k)).sqrnorm() == 0.f) continue;
01345
01347 float a, b, c;
01348 getLineEquation(k, a, b, c);
01349
01350 if (a * p.x + b * p.y + c < 0) return false;
01351
01352 }
01353 return true;
01354 }
01355 else
01356 {
01357 return p == Vertices[0];
01358 }
01359 }
01360
01361
01362
01363 CPolygon2D::CPolygon2D(const CTriangle &tri, const CMatrix &projMat)
01364 {
01365 Vertices.resize(3);
01366 NLMISC::CVector proj[3] = { projMat * tri.V0, projMat * tri.V1, projMat * tri.V2 };
01367 Vertices[0].set(proj[0].x, proj[0].y);
01368 Vertices[1].set(proj[1].x, proj[1].y);
01369 Vertices[2].set(proj[2].x, proj[2].y);
01370 }
01371
01372 }