23 #ifndef __FM_T_CONTOUR2D_IMPL_H__
24 #define __FM_T_CONTOUR2D_IMPL_H__
50 bool & bValidRegion );
53 std::vector< Intersection > & vecPoints,
const OdGeTol & gTol );
66 template <
class TContourData >
69 protected TContourData
96 return this->_implClass();
105 return this->_closed();
113 if ( this->_closed() != bClosed )
114 this->_setClosed( bClosed );
126 return this->_empty();
132 return this->_numVerts();
139 return this->_numSegments();
168 double & dBulge )
const;
325 virtual bool areEqualParams(
double dParam1,
double dParam2,
const double dTol = 1e-10 )
const;
396 std::vector< Intersection > & vecPoints,
403 std::vector< Intersection > & vecPoints,
413 std::vector< Intersection > & vecPoints,
496 OdUInt32& iNumPeriodsAB,
const double dParamTol = DBL_EPSILON )
const;
517 template <
class TContourData >
520 if (
this == &rSrcCont )
526 this->_reset( iNumVerts, bClosed );
530 for (
OdUInt32 iVert = 0; iVert < iNumVerts; iVert++ )
535 eRes = rSrcCont.
getVertexAt( iVert, & rVert.point(), & rVert.bulge(), & rVert.attributes() );
540 this->_setModifiedAll();
544 template <
class TContourData >
552 template <
class TContourData >
555 OdUInt32 uNumVerts = this->_numVerts();
560 if ( ! this->_vertex( 0 ).point().isEqualTo( this->_vertex( uNumVerts - 1 ).point(), gTol ) )
563 this->_removeVertices( uNumVerts - 1 );
564 this->_setClosed(
true );
570 template <
class TContourData >
573 OdUInt32 iNumSeg = this->_numSegments();
576 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
578 this->_getSegment( iSeg, ImplSeg );
579 if ( ImplSeg.type() ==
estArc )
589 template <
class TContourData >
593 if (
isError( this->_getSegment( iIndex, Seg ) ) )
600 template <
class TContourData >
603 if ( iIndex < this->_numVerts() )
604 return this->_vertex( iIndex ).attributes();
609 template <
class TContourData >
612 if ( iIndex < this->_numVerts() )
613 return this->_vertex( iIndex ).attributes();
618 template <
class TContourData >
621 if ( iIndex < this->_numVerts() )
623 this->_vertex( iIndex ).attributes() = rAttr;
630 template <
class TContourData >
635 if ( iIndex < this->_numVerts() )
636 uData = this->_vertex( iIndex ).attributes().metadata();
641 template <
class TContourData >
646 if ( iIndex < this->_numVerts() )
647 this->_vertex( iIndex ).attributes().metadata() = uNewData;
678 template <
class TContourData >
682 Result eRes = this->_getSegment( iIndex, ImplSeg );
691 template <
class TContourData >
695 double & dBulge )
const
698 Result eRes = this->_getSegment( iIndex, ImplSeg );
702 ptStart = ImplSeg._startPt();
703 ptEnd = ImplSeg._endPt();
704 dBulge = ImplSeg._bulge();
712 template <
class TContourData >
716 Result eRes = this->_getSegment( iIndex, ImplSeg );
720 return worstResult( eRes, ImplSeg.getLineSeg( geLine ) );
725 template <
class TContourData >
729 Result eRes = this->_getSegment( iIndex, ImplSeg );
733 return worstResult( eRes, ImplSeg.getArcSeg( geArc ) );
738 template <
class TContourData >
741 Result eRes = this->_normalizeIndex( iIndex );
745 ptPoint = this->_vertex(iIndex).point();
751 template <
class TContourData >
754 Result eRes = this->_normalizeIndex( iIndex );
758 dBulge = this->_vertex(iIndex).bulge();
763 template <
class TContourData >
766 Result eRes = this->_normalizeIndex( iIndex );
773 *pptPoint = rVert.point();
776 *pdBulge = rVert.bulge();
779 *pAttr = rVert.attributes();
785 template <
class TContourData >
788 Result eRes = this->_normalizeIndex( iIndex );
792 OdUInt32 iSize = this->numSegments();
793 if( !this->_closed() && ( iIndex == 0 || iIndex == iSize-1 ) )
803 this->_getSegment( iIndex, rSeg );
804 rSeg.getTangent( 0.0, vA );
807 this->_getSegment( iSize-1, rSeg );
809 this->_getSegment( iIndex-1, rSeg );
811 rSeg.getTangent( 1.0, vB );
822 template <
class TContourData >
830 template <
class TContourData >
833 this->_reserveVertices( iReservedSize );
838 template <
class TContourData >
841 Result eRes = this->_normalizeIndex( iIndex );
845 this->_vertex( iIndex ).point() = ptPoint;
846 this->_setModifiedVerts( iIndex );
853 template <
class TContourData >
856 Result eRes = this->_normalizeIndex( iIndex );
860 this->_vertex( iIndex ).bulge() = dBulge;
861 this->_setModifiedSegs( iIndex );
867 template <
class TContourData >
870 Result eRes = this->_normalizeIndex( iIndex );
875 rVert.point() = ptPoint;
876 rVert.bulge() = dBulge;
877 this->_setModifiedVerts( iIndex );
884 template <
class TContourData >
887 return this->_insertVerticesAt( iIndex, 1, &ptStart, &dBulge, &rAttr );
892 template <
class TContourData >
895 return this->_insertVerticesAt( this->_numVerts(), 1, &ptStart, &dBulge, &rAttr );
902 template <
class TContourData >
905 if ( vecSource.
empty() )
908 return this->_insertVerticesAt( this->_numVerts(), vecSource.
size(), &(vecSource[0]) );
912 template <
class TContourData >
915 if ( this->_empty() )
918 double vBulges[2] = { rSeg.
bulge(), 0.0 };
920 Result eRes = this->_insertVerticesAt( 0, 2, vPoints, vBulges );
922 this->_vertex( 0 ).attributes() = rSeg.
attributes();
928 OdUInt32 iLastVert = this->_numVerts() - 1;
930 TVertexData & rLastVert = this->_vertex( iLastVert );
938 if ( !ptEnd.
isEqualTo( rSegStart, gTol ) )
946 ptSegEnd.
x += ptEnd.
x - rSegStart.
x;
947 ptSegEnd.
y += ptEnd.
y - rSegStart.
y;
950 double dBulge = rSeg.
bulge();
951 if ( dBulge != rLastVert.bulge() )
953 rLastVert.bulge() = dBulge;
954 this->_setModifiedVerts( iLastVert );
958 eRes =
worstResult( eRes, this->_insertVerticesAt( iLastVert+1, 1, &ptSegEnd ) );
965 template <
class TContourData >
968 if ( this->_empty() )
972 OdUInt32 iLastVert = this->_numVerts() - 1;
973 TVertexData & rLastVert = this->_vertex( iLastVert );
976 if ( dBulge != rLastVert.bulge() )
978 rLastVert.bulge() = dBulge;
979 this->_setModifiedVerts( iLastVert );
983 rLastVert.attributes() = rAttr;
986 return this->_insertVerticesAt( iLastVert+1, 1, &ptNewEnd );
990 template <
class TContourData >
994 if ( _isEqualToThis( rCont ) )
1000 if ( this->_empty() )
1014 OdUInt32 iLastVert = this->_numVerts() - 1;
1016 TVertexData & rLastVert = this->_vertex( iLastVert );
1021 if ( !bCloseGap || dMaxGap < ptEnd.
distanceTo( ptContStart ) )
1028 if ( rLastVert.bulge() != 0.0 )
1030 rLastVert.bulge() = 0.0;
1031 this->_setModifiedVerts( iLastVert );
1040 OdUInt32 iModifiedVert = iLastVert;
1041 this->_resize( iLastVert + iNumContVerts );
1043 for (
OdUInt32 iContVert = 0 ; iContVert < iNumContVerts; ++iContVert, ++iLastVert )
1047 eRes = rCont.
getVertexAt( iContVert, & rVert.point(), & rVert.bulge(), & rVert.attributes() );
1051 this->_setModifiedVerts( iModifiedVert, iNumContVerts );
1060 template <
class TContourData >
1063 return this->_removeVertices( iIndex );
1069 template <
class TContourData >
1072 if ( this->_empty() )
1075 ptPoint = this->_vertex(0).point();
1082 template <
class TContourData >
1085 if ( this->_empty() )
1088 OdUInt32 iIndex = this->_closed() ? 0 : (this->_numVerts()-1);
1090 ptPoint = this->_vertex(iIndex).point();
1098 template <
class TContourData >
1101 OdUInt32 iNumSeg = this->_numSegments();
1106 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1108 this->_getSegment( iSeg, ImplSeg );
1109 dL += ImplSeg.length();
1119 template <
class TContourData >
1122 long iNumSegs = this->_numSegments();
1123 if ( iNumSegs <= 0 )
1130 const double dParamTol = 4*DBL_EPSILON;
1133 double dNormalizedParam = ::modf( dParam, &dIdx );
1134 long iNormalizedIdx = long( ::floor( dIdx + 0.5 ) );
1135 if ( dNormalizedParam < 0 )
1137 dNormalizedParam += 1;
1138 iNormalizedIdx -= 1;
1143 if ( iNormalizedIdx >=
long(iNumSegs) )
1145 if ( iNormalizedIdx==iNumSegs && dNormalizedParam <= dParamTol )
1148 dNormalizedParam = 1.0;
1150 else if ( this->_closed() )
1152 iNormalizedIdx = ::ldiv( iNormalizedIdx, iNumSegs ).rem;
1158 else if ( iNormalizedIdx < 0 )
1160 if ( iNormalizedIdx== -1 && dNormalizedParam >= (1.0-dParamTol) )
1163 dNormalizedParam = 0.0;
1165 else if ( this->_closed() )
1167 iNormalizedIdx = ::ldiv( iNormalizedIdx, iNumSegs ).rem + iNumSegs;
1174 dSegParam = dNormalizedParam;
1175 iIndex =
OdUInt32( iNormalizedIdx );
1177 FMGE_ASSERT( dSegParam >= -DBL_EPSILON && dSegParam <= (1.0+DBL_EPSILON) );
1185 template <
class TContourData >
1191 OdUInt32 iNumSegs = this->_numSegments();
1192 if ( iNumSegs <= 0 )
1197 bool bClosed = this->_closed();
1199 bool bDistNormalized =
false;
1206 double dLength = ((
IContour2D*)
this)->length();
1207 if ( dLength <= dTol )
1211 bDistNormalized =
true;
1212 dDist -= ::floor( dDist/dLength ) * dLength;
1213 if (dDist < 0.0 || dDist >= dLength )
1219 double dCurDist = 0;
1225 this->_getSegment( iSeg, ImplSeg );
1226 double dL = ImplSeg.length();
1227 if ( (dCurDist + dL) > dDist )
1231 dSegParam = (dDist - dCurDist)/dL;
1237 }
while ( ++iSeg < iNumSegs );
1240 if ( bDistNormalized )
1242 FMGE_FAULT(
"It seems that contour::length() returned a wrong value!" );
1247 double dLength = dCurDist;
1249 if ( !this->_closed() || dLength <= dTol )
1251 iIndex = iNumSegs - 1;
1257 bDistNormalized =
true;
1258 dDist -= ::floor( dDist/dLength ) * dLength;
1259 if (dDist < 0.0 || dDist >= dLength )
1267 template <
class TContourData >
1272 Result eRes = _param2IdxParam( dParam, iIndex, dSegParam );
1281 if ( dSegParam!= 0.0 )
1283 this->_getSegment( iIndex, ImplSeg );
1284 dSumLen += ImplSeg.length()*dSegParam;
1288 for (
OdUInt32 iSeg = 0; iSeg<iIndex; iSeg++ )
1290 this->_getSegment( iSeg, ImplSeg );
1291 dSumLen += ImplSeg.length();
1300 template <
class TContourData >
1307 Result eRes = _param2IdxParam( dParam, iIndex, dSegParam );
1316 return worstResult( eRes, ImplSeg.getTangent( dSegParam, vTangent ) );
1322 template <
class TContourData >
1326 if ( this->_numVerts()<=1 )
1328 if ( !this->_empty() &&
OdZero(dParam) )
1330 ptPoint = this->_vertex(0).point();
1341 Result eRes = _param2IdxParam( dParam, iIndex, dSegParam );
1350 return worstResult( eRes, ImplSeg.getPoint( dSegParam, ptPoint ) );
1356 template <
class TContourData >
1362 if ( this->_numVerts() <= 1 )
1366 ptPoint = this->_vertex(0).point();
1377 OdUInt32 iNumSegs = this->_numSegments();
1378 if ( dParam < 0.0 || dParam > iNumSegs )
1380 FMGE_FAULT(
"Contour::getParamAtDist returned an invalid parameter value." );
1385 if ( iIndex == iNumSegs )
1389 eRes =
worstResult( eRes, this->_getSegment( iIndex, ImplSeg ) );
1393 return worstResult( eRes, ImplSeg.getPoint( dParam - iIndex, ptPoint ) );
1399 template <
class TContourData >
1402 return _param2dist( dParam, dDist );
1407 template <
class TContourData >
1413 Result eRes = _dist2IdxParam( dDist, iIndex, dSegParam );
1420 dParam = iIndex + dSegParam;
1429 template <
class TContourData >
1432 const double dParamEps = 1e-10;
1434 int iNumSegs = this->_numSegments();
1435 if ( iNumSegs <= 0 )
1437 if ( this->_empty() )
1440 if ( ::fabs( dParam ) > dParamEps )
1450 if ( this->_closed() )
1452 if ( dParam < 0.0 || dParam >= iNumSegs )
1454 dParam -= ::floor(dParam/iNumSegs)*iNumSegs;
1455 if ( dParam < 0.0 || dParam >=iNumSegs )
1464 if ( dParam >= -dParamEps )
1469 else if ( dParam > iNumSegs )
1472 if ( dParam < (iNumSegs+dParamEps) )
1483 template <
class TContourData >
1486 return _normalizeParam( dParam );
1491 template <
class TContourData >
1496 double dLength =
length();
1500 if ( this->_closed() )
1502 if ( dDist < 0.0 || dDist >= dLength )
1504 if ( dLength > dTol )
1506 dDist -= ::floor(dDist/dLength)*dLength;
1507 if ( dDist < 0.0 || dDist > dLength )
1519 if ( dDist >= -dTol )
1524 else if ( dDist > dLength )
1527 if ( dDist < (dLength + dTol) )
1538 template <
class TContourData >
1541 double dDelta = ::fabs( dParam2 - dParam1 );
1543 if ( this->_closed() )
1545 OdUInt32 iNumSegs = this->_numSegments();
1549 if ( dDelta > iNumSegs )
1550 dDelta -= ::floor(dDelta/iNumSegs)*iNumSegs;
1552 if ( 2.0*dDelta > iNumSegs )
1553 dDelta = iNumSegs - dDelta;
1557 return ( dDelta <= dTol );
1561 template <
class TContourData >
1564 double dDelta = ::fabs( dDist2 - dDist1 );
1566 if ( this->_closed() )
1568 if ( dDelta <= dTol )
1571 double dLength =
length();
1573 if ( dLength > dTol )
1575 if ( dDelta > dLength )
1576 dDelta -= ::floor(dDelta/dLength)*dLength;
1578 if ( 2.0*dDelta > dLength )
1579 dDelta = dLength - dDelta;
1583 return ( dDelta <= dTol );
1587 template <
class TContourData >
1590 if ( ! this->_closed() )
1593 return dDist2 - dDist1;
1600 if (
OdEqual( dDist1, dDist2, dTol ) )
1603 double dLength =
length();
1605 if ( dLength < dTol )
1608 if ( dDist1 < 0.0 || dDist1 >= dLength )
1609 dDist1 -= ::floor(dDist1/dLength)*dLength;
1611 if ( dDist2 < 0.0 || dDist2 >= dLength )
1612 dDist2 -= ::floor(dDist2/dLength)*dLength;
1614 bool bSwap = ( dDist1 > dDist2 );
1618 double dDelta = dDist2 - dDist1;
1620 if ( dDelta > dLength/2 )
1621 dDelta = dLength - dDelta;
1623 return bSwap ? -dDelta : dDelta;
1627 template <
class TContourData >
1630 if ( dParam1 == dParam2 )
1633 double dDist1, dDist2;
1635 getDistAtParam ( dParam1, dDist1 ),
1636 getDistAtParam ( dParam2, dDist2 ) );
1640 return signedMinDist( dDist1, dDist2 );
1654 template <
class TContourData >
1657 if ( this->_empty() )
1662 OdUInt32 iNumSeg = this->_numSegments();
1668 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1670 this->_getSegment( iSeg, ImplSeg );
1671 ImplSeg.addExtents( myExts );
1676 myExts.
addPoint( this->_vertex(0).point() );
1681 geExtents.
addExt( myExts );
1689 template <
class TContourData >
1695 OdUInt32 iNumSeg = this->_numSegments();
1701 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1703 this->_getSegment( iSeg, ImplSeg );
1704 dSum += ImplSeg.integrate();
1707 if ( !this->_closed() )
1710 dSum +=
BulgeSeg2D( this->_vertex(iNumSeg).point(), this->_vertex(0).point() ).
integrate();
1720 template <
class TContourData >
1723 bool bResult =
false;
1725 OdUInt32 iSize = this->numSegments();
1726 if( iSize > 1 && this->_closed() )
1729 this->_getSegment( iSize-1, rSeg );
1733 rSeg.getTangent( 1.0, vB );
1735 double dCrossProduct;
1739 for(
OdUInt32 i = 0; i < iSize; i++ )
1742 this->_getSegment( i, rSeg );
1743 rSeg.getTangent( 0.0, vA );
1756 if( dCrossProduct >= 0.0 )
1775 template <
class TContourData >
1783 template <
class TContourData >
1789 OdUInt32 iNumSeg = this->_numSegments();
1795 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1797 this->_getSegment( iSeg, ImplSeg );
1800 bOn = ImplSeg.isOn( ptTest, &dSegParam, gTol );
1803 dParam = iSeg + dSegParam;
1808 else if ( !this->_empty() )
1811 bOn =
BulgeSeg2D( this->_vertex(0).point(), this->_vertex(0).point() ).
isOn( ptTest, &dParam, gTol);
1822 template <
class TContourData >
1825 if ( this->_empty() )
1828 *pptNearest = ptTest;
1833 double dNearestParam = 0;
1837 double dMinDist = ptNearest.
distanceTo( ptTest );
1839 const double dZeroDist = 1e-15;
1841 OdUInt32 iNumSeg = this->_numSegments();
1842 if ( ( iNumSeg > 0 ) && (dMinDist > dZeroDist) )
1849 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1851 this->_getSegment( iSeg, ImplSeg );
1853 double dSegParam = ImplSeg.nearestParam( ptTest, &ptTmp );
1857 if ( dDist < dMinDist )
1861 dNearestParam = iSeg + dSegParam;
1864 if ( dMinDist <= dZeroDist )
1871 *pptNearest = ptNearest;
1873 return dNearestParam;
1878 template <
class TContourData >
1882 *pbOnBorder =
false;
1884 if ( this->_empty() )
1887 if ( !this->_closed() )
1890 bool bInside =
false;
1893 OdUInt32 iNumSeg = this->_numSegments();
1899 for (
OdUInt32 iSeg = 0; iSeg<iNumSeg; iSeg++ )
1901 this->_getSegment( iSeg, ImplSeg );
1903 bool bOnSegment =
false;
1904 OdUInt32 iCount = ImplSeg.intersectXRay( rPoint, &bOnSegment, gTol );
1916 else if ( !this->_empty() )
1919 bInside =
BulgeSeg2D( this->_vertex(0).point(), this->_vertex(0).point() ).
isOn( rPoint, 0, gTol);
1921 *pbOnBorder = bInside;
1931 template <
class TContourData >
1934 OdUInt32 iNumSegs = this->_numSegments();
1936 if ( iNumSegs <= 1 )
1941 if ( iNumSegs > 16 && !bExcludeTouch )
1943 bool bIntersects =
false;
1957 for (
OdUInt32 iSegA = 0; iSegA < iNumSegs; iSegA++ )
1959 this->_getSegment( iSegA, ImplSegA );
1961 for (
OdUInt32 iSegB = 0; iSegB < iSegA; iSegB++ )
1963 this->_getSegment( iSegB, ImplSegB );
1965 OdUInt32 iCrosses = ImplSegA.intersect( ImplSegB, &(XPt[0]), &(XPt[1]), gTol );
1971 if(bExcludeTouch && (iSegA != iNumSegs-1 || iSegB != 0) && iCrosses == 1 &&
Intersection::eitTouch == XPt[0].eType && !this->areEqualParams( iSegB + XPt[0].dParamB, iSegA + XPt[0].dParamA, 1e-14 ))
1973 const bool bAisTouchEnd =
OdEqual(XPt[0].dParamA, 1., 1e-10);
1974 const bool bAisTouchBeg =
OdEqual(XPt[0].dParamA, 0., 1e-10);
1976 const bool bBisTouchEnd =
OdEqual(XPt[0].dParamB, 1., 1e-10);
1977 const bool bBisTouchBeg =
OdEqual(XPt[0].dParamB, 0., 1e-10);
1979 const bool bAisTouch = bAisTouchEnd || bAisTouchBeg;
1980 const bool bBisTouch = bBisTouchEnd || bBisTouchBeg;
1981 if(bAisTouch && bBisTouch)
1983 const OdGeVector2d vA1 = bAisTouchEnd ? ImplSegA.startPt() - ImplSegA.endPt() : ImplSegA.endPt() - ImplSegA.startPt();
1984 int iNext = ((iSegA + (bAisTouchEnd ? 1 : -1)) + iNumSegs) % iNumSegs;
1986 this->_getSegment( iNext, ImplNext );
1987 const OdGeVector2d vA2 = bAisTouchEnd ? ImplNext.endPt() - ImplSegA.endPt() : ImplNext.startPt() - ImplSegA.startPt();
1989 const OdGeVector2d vB1 = bBisTouchEnd ? ImplSegB.startPt() - ImplSegB.endPt() : ImplSegB.endPt() - ImplSegB.startPt();
1990 iNext = ((iSegB + (bBisTouchEnd ? 1 : -1)) + iNumSegs) % iNumSegs;
1991 this->_getSegment( iNext, ImplNext );
1992 const OdGeVector2d vB2 = bBisTouchEnd ? ImplNext.endPt() - ImplSegB.endPt() : ImplNext.startPt() - ImplSegB.startPt();
2009 if((angB1 < angA && angB2 < angA) || (angB1 > angA && angB2 > angA))
2016 int iNext = ((iSegA + (bAisTouchEnd ? 1 : -1)) + iNumSegs) % iNumSegs;
2018 this->_getSegment( iNext, ImplNext );
2019 const OdGePoint2d pt1 = bAisTouchEnd ? ImplNext.endPt() : ImplNext.startPt();
2020 const OdGePoint2d pt2 = bAisTouchEnd ? ImplSegA.startPt() : ImplSegA.endPt();
2022 OdGeVector2d vLine = ImplSegB.endPt() - ImplSegB.startPt();
2023 const double sign1 = vLine.
crossProduct(pt1 - ImplSegB.startPt());
2024 const double sign2 = vLine.
crossProduct(pt2 - ImplSegB.startPt());
2025 if(sign1*sign2 > -1e-14)
2032 int iNext = ((iSegB + (bBisTouchEnd ? 1 : -1)) + iNumSegs) % iNumSegs;
2034 this->_getSegment( iNext, ImplNext );
2035 const OdGePoint2d pt1 = bBisTouchEnd ? ImplNext.endPt() : ImplNext.startPt();
2036 const OdGePoint2d pt2 = bBisTouchEnd ? ImplSegB.startPt() : ImplSegB.endPt();
2038 OdGeVector2d vLine = ImplSegA.endPt() - ImplSegA.startPt();
2039 const double sign1 = vLine.
crossProduct(pt1 - ImplSegA.startPt());
2040 const double sign2 = vLine.
crossProduct(pt2 - ImplSegA.startPt());
2041 if(sign1*sign2 > -1e-14)
2050 for (
OdUInt32 iC = 0; iC < iCrosses; iC++ )
2052 if ( !XPt[iC].eType )
2061 if ( this->areEqualParams( iSegB + XPt[iC].dParamB, iSegA + XPt[iC].dParamA, 1e-14 ) )
2064 double dDist = this->signedMinDistByParams( iSegB + XPt[iC].dParamB, iSegA + XPt[iC].dParamA );
2077 template <
class TContourData >
2080 bool bValidRegion =
false;
2084 return bValidRegion;
2087 template <
class TContourData >
2094 const OdUInt32 numVertices = this->numVerts();
2096 for(
OdUInt32 uVertexIdx = 0; uVertexIdx < numVertices; uVertexIdx++)
2098 this->getVertexAt(uVertexIdx, &ptVertex);
2100 bool fOnBorder =
false;
2101 if(!c2dOuter.
contains(ptVertex, &fOnBorder))
2104 if(!fAllowBordersTouch && fOnBorder)
2112 template <
class TContourData >
2114 std::vector< Intersection > & vecPoints,
2117 if ( this->_empty() )
2124 OdUInt32 iNumSegs = this->_numSegments();
2133 for (
OdUInt32 iSeg = 0; iSeg < iNumSegs; iSeg++ )
2135 this->_getSegment( iSeg, ImplSeg );
2137 OdUInt32 iCrosses = ImplSeg.intersect( rSegB, &(XPt[0]), &(XPt[1]), gTol );
2141 for (
OdUInt32 iC = 0; iC < iCrosses; iC++ )
2148 vecPoints.push_back( XPt[iC] );
2152 else if ( this->_numVerts() > 0 )
2154 const OdGePoint2d & ptVert = this->_vertex(0).point();
2157 if ( rSegB.
isOn( ptVert, &dBParam, gTol ) )
2164 vecPoints.push_back( XPt[0] );
2168 return (
OdUInt32)vecPoints.size() - iOrigCrossCount;
2174 template <
class TContourData >
2176 std::vector< Intersection > & vecPoints,
2179 if ( this->_empty() || rContB.
isEmpty() )
2182 OdUInt32 iNumSegs = this->_numSegments();
2186 OdUInt32 iCrossCount = iOrigCrossCount;
2195 return (
OdUInt32)vecPoints.size() - iOrigCrossCount;
2205 for (
OdUInt32 iSeg = 0; iSeg < iNumSegs; iSeg++ )
2207 this->_getSegment( iSeg, ImplSeg );
2210 rContB.
intersect( ImplSeg, vecPoints, gTol );
2214 while ( iCrossCount < vecPoints.size() )
2218 double dBParam = rCross.
dParamA;
2230 else if ( this->_numVerts() > 0 )
2233 BulgeSeg2D ASeg( this->_vertex(0).point(), this->_vertex(0).point() );
2236 rContB.
intersect( ASeg, vecPoints, gTol );
2238 while ( iCrossCount < vecPoints.size() )
2248 return iCrossCount - iOrigCrossCount;
2252 template <
class TContourData >
2256 std::vector< Intersection > & vecPoints,
2262 OdUInt32 iNumSegs = this->_numSegments();
2283 for (
OdUInt32 iSeg = 0; iSeg < iNumSegs; iSeg++ )
2285 this->_getSegment( iSeg, ImplSeg );
2287 OdUInt32 iCrosses = ImplSeg.intersectLine( ptLineOrigin, vLineDir, &(XPt[0]), &(XPt[1]), gTol );
2293 for (
OdUInt32 iC = 0; iC < iCrosses; iC++ )
2300 vecPoints.push_back( XPt[iC] );
2305 else if ( this->_numVerts() > 0 )
2307 BulgeSeg2D ASeg( this->_vertex(0).point(), this->_vertex(0).point() );
2315 vecPoints.push_back( XPt[0] );
2319 return (
OdUInt32)vecPoints.size() - iOrigCrossCount;
2323 template <
class TContourData >
2334 bool bExplodeRequired =
false;
2342 bExplodeRequired =
true;
2346 if ( bExplodeRequired )
2350 this->explodeTo( *
this, devDeviation );
2353 OdUInt32 iNumVerts = this->_numVerts();
2354 if ( this->_numVerts() <= 0 )
2357 bool bInverse = ( geMatrix.
det() < 0 );
2359 for (
OdUInt32 iVert = 0; iVert<iNumVerts; iVert++ )
2362 rVert.point().transformBy( geMatrix );
2364 rVert.bulge() = -rVert.bulge();
2367 this->_setModifiedAll();
2374 template <
class TContourData >
2377 OdUInt32 iNumVerts = this->_numVerts();
2378 if ( this->_numVerts() <= 0 )
2381 if ( ! this->_closed() )
2386 for (
OdUInt32 iS = 0; iS < iSwapNum; iS++ )
2389 OdGePoint2d& rPtB = this->_vertex(iNumVerts - 1 - iS).point();
2393 TVertexData & rVertB = this->_vertex(iNumVerts - 2 - iS);
2395 std::swap( rVertA.bulge(), rVertB.bulge() );
2396 std::swap( rVertA.attributes(), rVertB.attributes() );
2405 OdUInt32 iPSwapNum = (iNumVerts-1)/2;
2406 for (
OdUInt32 iS = 0; iS < iPSwapNum; iS++ )
2409 OdGePoint2d& rPtB = this->_vertex(iNumVerts - iS - 1).point();
2417 for (
OdUInt32 iS = 0; iS < iBSwapNum; iS++ )
2420 TVertexData & rVertB = this->_vertex(iNumVerts - iS - 1);
2422 std::swap( rVertA.bulge(), rVertB.bulge() );
2423 std::swap( rVertA.attributes(), rVertB.attributes() );
2430 for (
OdUInt32 i = 0, iSize = numVerts(); i < iSize; i++ )
2433 rVert.bulge() = -rVert.bulge();
2434 rVert.attributes().reverse();
2438 this->_setModifiedAll();
2445 template <
class TContourData >
2448 OdUInt32 iNumVerts = this->_numVerts();
2449 if ( this->_numVerts() <= 1 )
2457 for (
OdUInt32 iVert = 1; iVert<iNumVerts; iVert++)
2460 if ( rThisVert.point().isEqualTo( pPrevVert->point(), gTol ) )
2463 pPrevVert->bulge() = rThisVert.bulge();
2464 pPrevVert->attributes() = rThisVert.attributes();
2468 pPrevVert = & this->_vertex(iNumHandled);
2469 if ( iNumHandled < iVert )
2470 *pPrevVert = rThisVert;
2476 if ( this->_closed() )
2478 if ( this->_vertex(0).point().isEqualTo( pPrevVert->point(), gTol ) )
2486 if ( iNumHandled < (iNumVerts-1) )
2487 this->_vertex(iNumHandled) = this->_vertex( iNumVerts-1 );
2490 if ( iNumHandled < iNumVerts )
2493 this->_resize( iNumHandled );
2494 this->_setModifiedAll();
2499 template <
class TContourData >
2506 template <
class TContourData >
2512 bool bThisDest = ( ((
const IContour2D*)
this) == &rDestCont );
2514 bool bClosed = this->_closed();
2516 OdUInt32 iNumVerts = this->_numVerts();
2517 OdUInt32 iNumSegs = this->_numSegments();
2524 rDestCont.
set( *
this );
2535 typedef std::pair< OdUInt32, Attributes2D > SegDataPair;
2536 std::vector< SegDataPair > vecAttributes;
2538 vecAttributes.
reserve( iNumVerts + 1);
2539 vecPoints.
reserve( iNumVerts );
2544 bool bHasArcs =
false;
2546 for (
OdUInt32 iSeg = 0; iSeg < iNumSegs; iSeg++ )
2548 this->_getSegment( iSeg, ImplSeg );
2551 vecAttributes.push_back( SegDataPair( vecPoints.
size(), Attr ) );
2553 vecPoints.
push_back( ImplSeg.startPt() );
2555 if ( ImplSeg.type() ==
estArc )
2558 vecAttributes.back().second.setExplodedArc(
true).metadata() |= uArcMetadata;
2560 eRes = arcSeg.
set( ImplSeg );
2572 for (
OdUInt32 iPt = 1; iPt<iSegmentCount; iPt++ )
2574 eRes = arcSeg.
getPoint(
double(iPt)/iSegmentCount, ptVertex );
2586 const TVertexData & rLast = this->_vertex( iNumVerts-1 );
2587 FMGE_ASSERT( ImplSeg.endPt().isEqualTo( rLast.point() ) );
2589 vecAttributes.push_back( SegDataPair( vecPoints.
size(), rLast.attributes() ) );
2601 rDestCont.
set( *
this );
2614 for (
OdUInt32 uI = 1; uI < vecAttributes.size(); ++uI )
2616 const Attributes2D& rAttr = vecAttributes[ uI-1 ].second;
2619 OdUInt32 uVert = vecAttributes[ uI-1 ].first;
2620 OdUInt32 uLastVert = vecAttributes[ uI ].first;
2622 for ( ; uVert < uLastVert; ++uVert )
2634 template <
class TContourData >
2639 Result eRes = _param2IdxParam( dParam, iIndex, dSegParam );
2644 eRes = this->_getSegment( iIndex, ImplSeg );
2650 double dLen = ImplSeg.length();
2656 if ( dSegParam*dLen <= dTol )
2661 else if ( (1.0 - dSegParam)*dLen <= dTol )
2664 return (iIndex+1) % this->_numVerts();
2672 eRes = ImplSeg.getPoint( dSegParam, ptSplit);
2679 if ( ImplSeg.type()==
estArc )
2682 double dAngle = ImplSeg.arcAngle();
2683 double dBulge1 = ::tan( 0.25 * dAngle * dSegParam );
2684 double dBulge2 = ::tan( 0.25 * dAngle * (1.0 - dSegParam) );
2688 this->_vertex( iIndex ).bulge() = dBulge1;
2689 this->_setModifiedSegs( iIndex );
2690 eRes = this->_insertVerticesAt(iNewIndex, 1, &ptSplit, &dBulge2, &Attr );
2695 if ( ImplSeg._bulge() != 0.0 )
2697 this->_vertex( iIndex ).bulge() = 0.0;
2698 this->_setModifiedSegs( iIndex );
2701 eRes = this->_insertVerticesAt(iNewIndex, 1, &ptSplit, 0, &Attr );
2712 template <
class TContourData >
2716 if ( uCount<1 || !pdParams )
2719 typedef std::pair< OdUInt32, double > SegOffsPair;
2720 std::vector< SegOffsPair > vecParams;
2721 vecParams.reserve( uCount );
2729 for (
OdUInt32 uP = 0; uP < uCount; ++uP )
2731 Result eRes = _param2IdxParam( pdParams[uP], currSO.first, currSO.second );
2734 vecParams.push_back( currSO );
2737 std::sort( vecParams.begin(), vecParams.end() );
2741 if ( !vecParams.empty() )
2747 std::vector< double > vecSegParams;
2748 std::vector< OdGePoint2d > vecSegPoints;
2749 std::vector< double > vecSegBulges;
2750 std::vector< Attributes2D > vecSegAttributes;
2760 OdUInt32 uSeg = vecParams[uSBegin].first;
2761 while ( uSBegin > 0 && ( uSeg == vecParams[uSBegin-1].first ) )
2765 eRes = this->_getSegment( uSeg, ImplSeg );
2767 currSeg.
set( ImplSeg );
2770 double dLen = currSeg.
length();
2774 vecSegParams.resize( 0 );
2776 for (
OdUInt32 uP = uSBegin; uP < uSEnd; ++uP )
2778 double dSegParam = vecParams[uP].second;
2779 if ( dSegParam*dLen > dTol && (1.0 - dSegParam)*dLen > dTol )
2782 if ( vecSegParams.empty()
2783 || !
OdEqual( vecSegParams.back(), dSegParam, dTol ) )
2786 vecSegParams.push_back( dSegParam );
2792 if ( !vecSegParams.empty() )
2797 vecSegPoints.resize( uNewNum );
2799 for (
OdUInt32 uP = 0 ; uP < uNewNum; ++uP )
2801 eRes = currSeg.
getPoint( vecSegParams[uP], vecSegPoints[uP] );
2808 vecSegAttributes.resize( 0 );
2811 vecSegAttributes.resize( uNewNum, currSeg.
attributes() );
2812 pAttributes = &( vecSegAttributes.front() );
2819 vecSegBulges.resize( uNewNum+1 );
2820 vecSegParams.push_back( 1.0 );
2822 double dAngle4 = currSeg.
arcAngle()/4.0;
2824 double dPrevParam = 0;
2825 for (
OdUInt32 uP = 0; uP <= uNewNum; ++uP )
2827 vecSegBulges[ uP ] = ::tan( dAngle4 * ( vecSegParams[uP] - dPrevParam ) );
2828 dPrevParam = vecSegParams[uP];
2832 this->_vertex( uSeg ).bulge() = vecSegBulges[0];
2833 this->_setModifiedSegs( uSeg );
2836 eRes = this->_insertVerticesAt( uSeg + 1, uNewNum,
2837 & ( vecSegPoints[0] ),
2838 & ( vecSegBulges[1] ),
2848 if ( ImplSeg._bulge() != 0.0 )
2850 this->_vertex( uSeg ).bulge() = 0.0;
2851 this->_setModifiedSegs( uSeg );
2855 eRes = this->_insertVerticesAt( uSeg + 1, uNewNum, &( vecSegPoints.front() ), 0, pAttributes );
2870 template <
class TContourData >
2873 return _createVerticesAt( (
OdUInt32)vecParams.size(), &( vecParams.front() ), gTol );
2878 template <
class TContourData >
2880 const double dParamA,
const double dParamB,
2882 OdUInt32& iNumPeriodsAB,
const double dParamTol )
const
2886 OdUInt32 iNumSegs = this->_numSegments();
2887 if ( iNumSegs <= 0 )
2890 dSegParamA = dSegParamB = 0;
2891 if ( this->_numVerts() > 0 &&
OdZero(dParamA, dParamTol) &&
OdZero(dParamB, dParamTol) )
2897 bool bReverse = (dParamA > dParamB);
2901 double adSegParams[2];
2903 for (
int i = 0; i<2; ++i )
2906 adSegParams[i] = ::modf( i==
int(bReverse) ? dParamA : dParamB, &dIdx );
2907 aiIdx[i] = long( ::floor( dIdx + 0.5 ) );
2908 if ( adSegParams[i] < 0 )
2910 adSegParams[i] += 1;
2918 if ( adSegParams[0] >= 1.0-dParamTol )
2920 adSegParams[0] = 0.0;
2923 else if ( adSegParams[0] <= dParamTol )
2925 adSegParams[0] = 0.0;
2928 if ( adSegParams[1] <= dParamTol )
2930 adSegParams[1] = 1.0;
2933 else if ( adSegParams[1] >= 1.0-dParamTol )
2935 adSegParams[1] = 1.0;
2941 if ( aiIdx[0] > aiIdx[1] || ( aiIdx[0] == aiIdx[1] && adSegParams[0] >= adSegParams[1] ) )
2944 "Critical floating-point inaccuracy!" );
2946 aiIdx[1] = aiIdx[0];
2947 adSegParams[1] = adSegParams[0];
2953 if ( this->_closed() )
2957 ldiv_t aPeriodsIdxs[2];
2958 for (
int i=0; i<2; ++i )
2960 ldiv_t& rDest = aPeriodsIdxs[i];
2961 rDest = ::ldiv( aiIdx[i],
long(iNumSegs) );
2962 if ( rDest.rem < 0 )
2964 rDest.rem += long(iNumSegs);
2969 iNumPeriodsAB = aPeriodsIdxs[ !bReverse ].quot - aPeriodsIdxs[ bReverse ].quot;
2970 uIdxA =
OdUInt32( aPeriodsIdxs[ bReverse ].rem );
2971 uIdxB =
OdUInt32( aPeriodsIdxs[!bReverse ].rem );
2972 dSegParamA = adSegParams[ bReverse ];
2973 dSegParamB = adSegParams[!bReverse ];
2980 for (
int i=0; i<2; ++i )
2984 if ( aiIdx[i] == -1 && adSegParams[i] >= (1.0-dParamTol) )
2987 adSegParams[i] = 0.0;
2992 else if ( aiIdx[i] >=
long(iNumSegs) )
2994 if ( aiIdx[i] ==
long(iNumSegs) && adSegParams[i] <= dParamTol )
2996 aiIdx[i] = long(iNumSegs)-1;
2997 adSegParams[i] = 1.0;
3005 uIdxA =
OdUInt32( aiIdx[ bReverse ] );
3006 uIdxB =
OdUInt32( aiIdx[!bReverse ] );
3007 dSegParamA = adSegParams[ bReverse ];
3008 dSegParamB = adSegParams[!bReverse ];
3016 template <
class TContourData >
3020 Result eRes = this->_getSegment( iIndex, srcSeg );
3024 return worstResult( eRes, srcSeg.getSubSegment( dStartOffs, dEndOffs, rDestSeg ) );
3028 template <
class TContourData >
3032 OdUInt32 iNumSegs = this->_numSegments();
3038 double adSegParams[2];
3041 bool bReverse = ( dStartParam > dEndParam );
3043 eRes = _paramRange2IdxParams(
3044 bReverse ? dEndParam : dStartParam,
3045 bReverse ? dStartParam : dEndParam,
3046 auSegIdxs[0], adSegParams[0], auSegIdxs[1], adSegParams[1], iNumPeriods, 1e-14 );
3053 double dOldLen = ( bReverse ? -1 : 1)*(dEndParam - dStartParam);
3054 double dNewLen = (auSegIdxs[1]+adSegParams[1]) - (auSegIdxs[0]+adSegParams[0]) + iNumPeriods*double(iNumSegs);
3062 if ( iNumPeriods < 0 || ( iNumPeriods==0 && auSegIdxs[0] > auSegIdxs[1] ) )
3064 FMGE_FAULT(
"Illegal values caused by buggy code or FP-inaccuracy!");
3072 Result tmpRes = this->_getSegment( auSegIdxs[bReverse], srcSeg );
3077 tmpRes = srcSeg.getPoint( adSegParams[bReverse], ptPoint );
3082 BulgeSeg2D( ptPoint, ptPoint, 0.0, srcSeg.attributes() ),
3089 if ( auSegIdxs[0]==auSegIdxs[1] && 0==iNumPeriods )
3093 auSegIdxs[0], adSegParams[ bReverse ], adSegParams[ !bReverse ], gSingleSeg ) );
3103 if ( iNumSegs <= 0 )
3111 eRes =
worstResult( eRes, _getSubSegment( auSegIdxs[0], adSegParams[0], 1.0, gBoundarySegs[0] ) );
3112 eRes =
worstResult( eRes, _getSubSegment( auSegIdxs[1], 0.0, adSegParams[1], gBoundarySegs[1] ) );
3118 aiUnbrokenSegs[0] = auSegIdxs[0] + 1;
3119 aiUnbrokenSegs[1] = auSegIdxs[1] - 1 + iNumPeriods*
OdUInt32(iNumSegs);
3121 OdUInt32 iNumUnbroken = ( aiUnbrokenSegs[1] - aiUnbrokenSegs[0] + 1 );
3145 for (
OdUInt32 iSeg = aiUnbrokenSegs[0]; iSeg <= aiUnbrokenSegs[1]; ++iSeg )
3148 Result tmpRes = this->_getSegment( iIndex, srcSeg );
3154 tmpRes = rSubContour.
appendSegment( srcSeg._bulge(), srcSeg._endPt(), srcSeg._attr() );
3163 for (
OdUInt32 iSeg = aiUnbrokenSegs[1]; iSeg >= aiUnbrokenSegs[0]; --iSeg )
3166 const TVertexData & rVert = this->_vertex( iIndex );
3169 Result tmpRes = rSubContour.
appendSegment( -rVert.bulge(), rVert.point(), rVert.attributes().getReversed() );
3186 template <
class TContourData >
3188 double dStartParam,
double dEndParam,
IContour2D & rSubContour,
const OdGeTol & gTol )
const
3191 if ( _isEqualToThis(rSubContour) )
3194 rSubContour.
reset();
3195 return _appendSubContourTo( dStartParam, dEndParam, rSubContour, gTol );
3198 template <
class TContourData >
3200 double dStartParam,
double dEndParam,
IContour2D & rSubContour,
const OdGeTol & gTol )
const
3203 if ( _isEqualToThis(rSubContour) )
3206 return _appendSubContourTo( dStartParam, dEndParam, rSubContour, gTol );
3211 template <
class TContourData >
3214 FMGE_ASSERT( !_isEqualToThis(rDest) && (&rDest != &rSubContour) );
3215 if ( _isEqualToThis(rDest) || &rDest == &rSubContour )
3232 if ( !isOn( aSubEnds[0], &(adParams[0]), gTol )
3233 ||!isOn( aSubEnds[1], &(adParams[1]), gTol ) )
3239 bool bEqualEnds = aSubEnds[0].
isEqualTo( aSubEnds[1], gTol );
3240 double dParamLength = double( this->_numSegments() );
3242 if ( this->_closed() )
3246 double dLoopStart = adParams[1];
3247 double dLoopEnd = adParams[0];
3250 dLoopEnd = dLoopStart + dParamLength;
3251 else if ( dLoopEnd < dLoopStart )
3252 dLoopEnd += dParamLength;
3254 eRes = _appendSubContourTo( dLoopStart, dLoopEnd, rDest, gTol );
3270 adParams[1] = adParams[0];
3271 else if ( adParams[0] > adParams[1] )
3276 if ( adParams[0] > 0 )
3277 eRes = _appendSubContourTo( 0.0, adParams[0], rDest, gTol );
3282 if (
isOk(eRes) && ( adParams[1] < dParamLength ) )
3283 eRes = _appendSubContourTo( adParams[1], dParamLength, rDest, gTol );
3296 #endif //__FM_T_CONTOUR2D_IMPL_H__