summaryrefslogtreecommitdiff
path: root/basegfx/source/polygon/b2dpolygontools.cxx
diff options
context:
space:
mode:
authorArmin Weiss <aw@openoffice.org>2003-11-06 15:30:30 +0000
committerArmin Weiss <aw@openoffice.org>2003-11-06 15:30:30 +0000
commitfef23aeb65bed8951a90ed71beb1552b62cfce71 (patch)
treed2ee4fe2d735d77de4f1618ea6664042269a67fa /basegfx/source/polygon/b2dpolygontools.cxx
parent8db4a5314c1b74eba07f4f4e383fafa24239e1f1 (diff)
Added tooling for PolyPolygon cutting and some more tooling at B2DPolygon and B2DPolyPolygon
Diffstat (limited to 'basegfx/source/polygon/b2dpolygontools.cxx')
-rw-r--r--basegfx/source/polygon/b2dpolygontools.cxx345
1 files changed, 328 insertions, 17 deletions
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index c5b56dd72e31..c7211c12bd07 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: b2dpolygontools.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: aw $ $Date: 2003-11-05 12:25:54 $
+ * last change: $Author: aw $ $Date: 2003-11-06 16:30:29 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -99,7 +99,7 @@ namespace basegfx
}
// Get index of outmost point (e.g. biggest X and biggest Y)
- sal_uInt32 getIndexOfOutmostPoint(const polygon::B2DPolygon& rCandidate)
+ sal_uInt32 getIndexOfOutmostPoint(const ::basegfx::polygon::B2DPolygon& rCandidate)
{
sal_uInt32 nRetval(0L);
@@ -132,7 +132,7 @@ namespace basegfx
// Get successor and predecessor indices. Returning the same index means there
// is none. Same for successor.
- sal_uInt32 getIndexOfPredecessor(sal_uInt32 nIndex, const polygon::B2DPolygon& rCandidate)
+ sal_uInt32 getIndexOfPredecessor(sal_uInt32 nIndex, const ::basegfx::polygon::B2DPolygon& rCandidate)
{
if(nIndex)
{
@@ -148,7 +148,7 @@ namespace basegfx
}
}
- sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const polygon::B2DPolygon& rCandidate)
+ sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const ::basegfx::polygon::B2DPolygon& rCandidate)
{
if(nIndex + 1L < rCandidate.count())
{
@@ -160,7 +160,7 @@ namespace basegfx
}
}
- sal_uInt32 getIndexOfDifferentPredecessor(sal_uInt32 nIndex, const polygon::B2DPolygon& rCandidate)
+ sal_uInt32 getIndexOfDifferentPredecessor(sal_uInt32 nIndex, const ::basegfx::polygon::B2DPolygon& rCandidate)
{
if(rCandidate.count() > 1)
{
@@ -177,7 +177,7 @@ namespace basegfx
return nIndex;
}
- sal_uInt32 getIndexOfDifferentSuccessor(sal_uInt32 nIndex, const polygon::B2DPolygon& rCandidate)
+ sal_uInt32 getIndexOfDifferentSuccessor(sal_uInt32 nIndex, const ::basegfx::polygon::B2DPolygon& rCandidate)
{
if(rCandidate.count() > 1)
{
@@ -214,8 +214,8 @@ namespace basegfx
for(sal_uInt32 a(0L); a < nPointCount; a++)
{
- const basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
- const basegfx::point::B2DPoint aPreviousPoint(rCandidate.getB2DPoint((!a) ? nPointCount - 1L : a - 1L));
+ const ::basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
+ const ::basegfx::point::B2DPoint aPreviousPoint(rCandidate.getB2DPoint((!a) ? nPointCount - 1L : a - 1L));
// cross-over in Y?
const sal_Bool bCompYA(::basegfx::numeric::fTools::more(aPreviousPoint.getY(), rPoint.getY()));
@@ -291,8 +291,8 @@ namespace basegfx
{
for(sal_uInt32 a(0L); a < nPointCount; a++)
{
- const basegfx::point::B2DPoint aPreviousPoint(rCandidate.getB2DPoint((!a) ? nPointCount - 1L : a - 1L));
- const basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
+ const ::basegfx::point::B2DPoint aPreviousPoint(rCandidate.getB2DPoint((!a) ? nPointCount - 1L : a - 1L));
+ const ::basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
fRetval += aPreviousPoint.getX() * aCurrentPoint.getY();
fRetval -= aPreviousPoint.getY() * aCurrentPoint.getX();
@@ -321,9 +321,9 @@ namespace basegfx
if(rCandidate.isClosed() || nIndex + 1 != nPointCount)
{
const sal_uInt32 nNextIndex(nIndex + 1 == nPointCount ? 0L : nIndex + 1L);
- const basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(nIndex));
- const basegfx::point::B2DPoint aNextPoint(rCandidate.getB2DPoint(nNextIndex));
- const basegfx::vector::B2DVector aVector(aNextPoint - aCurrentPoint);
+ const ::basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(nIndex));
+ const ::basegfx::point::B2DPoint aNextPoint(rCandidate.getB2DPoint(nNextIndex));
+ const ::basegfx::vector::B2DVector aVector(aNextPoint - aCurrentPoint);
fRetval = aVector.getLength();
}
}
@@ -343,9 +343,9 @@ namespace basegfx
for(sal_uInt32 a(0L); a < nLoopCount; a++)
{
const sal_uInt32 nNextIndex(a + 1 == nPointCount ? 0L : a + 1L);
- const basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
- const basegfx::point::B2DPoint aNextPoint(rCandidate.getB2DPoint(nNextIndex));
- const basegfx::vector::B2DVector aVector(aNextPoint - aCurrentPoint);
+ const ::basegfx::point::B2DPoint aCurrentPoint(rCandidate.getB2DPoint(a));
+ const ::basegfx::point::B2DPoint aNextPoint(rCandidate.getB2DPoint(nNextIndex));
+ const ::basegfx::vector::B2DVector aVector(aNextPoint - aCurrentPoint);
fRetval += aVector.scalar(aVector);
}
@@ -498,6 +498,317 @@ namespace basegfx
return eRetval;
}
+
+ CutFlagValue findCut(
+ const ::basegfx::polygon::B2DPolygon& rCandidate,
+ sal_uInt32 nIndex1, sal_uInt32 nIndex2,
+ CutFlagValue aCutFlags,
+ double* pCut1, double* pCut2)
+ {
+ CutFlagValue aRetval(CUTFLAG_NONE);
+ const sal_uInt32 nPointCount(rCandidate.count());
+
+ if(nIndex1 < nPointCount && nIndex2 < nPointCount && nIndex1 != nIndex2)
+ {
+ sal_uInt32 nEnd1(getIndexOfSuccessor(nIndex1, rCandidate));
+ sal_uInt32 nEnd2(getIndexOfSuccessor(nIndex2, rCandidate));
+
+ const ::basegfx::point::B2DPoint aStart1(rCandidate.getB2DPoint(nIndex1));
+ const ::basegfx::point::B2DPoint aEnd1(rCandidate.getB2DPoint(nEnd1));
+ const ::basegfx::vector::B2DVector aVector1(aEnd1 - aStart1);
+
+ const ::basegfx::point::B2DPoint aStart2(rCandidate.getB2DPoint(nIndex2));
+ const ::basegfx::point::B2DPoint aEnd2(rCandidate.getB2DPoint(nEnd2));
+ const ::basegfx::vector::B2DVector aVector2(aEnd2 - aStart2);
+
+ aRetval = findCut(
+ aStart1, aVector1, aStart2, aVector2,
+ aCutFlags, pCut1, pCut2);
+ }
+
+ return aRetval;
+ }
+
+ CutFlagValue findCut(
+ const ::basegfx::polygon::B2DPolygon& rCandidate1, sal_uInt32 nIndex1,
+ const ::basegfx::polygon::B2DPolygon& rCandidate2, sal_uInt32 nIndex2,
+ CutFlagValue aCutFlags,
+ double* pCut1, double* pCut2)
+ {
+ CutFlagValue aRetval(CUTFLAG_NONE);
+ const sal_uInt32 nPointCount1(rCandidate1.count());
+ const sal_uInt32 nPointCount2(rCandidate2.count());
+
+ if(nIndex1 < nPointCount1 && nIndex2 < nPointCount2)
+ {
+ sal_uInt32 nEnd1(getIndexOfSuccessor(nIndex1, rCandidate1));
+ sal_uInt32 nEnd2(getIndexOfSuccessor(nIndex2, rCandidate2));
+
+ const ::basegfx::point::B2DPoint aStart1(rCandidate1.getB2DPoint(nIndex1));
+ const ::basegfx::point::B2DPoint aEnd1(rCandidate1.getB2DPoint(nEnd1));
+ const ::basegfx::vector::B2DVector aVector1(aEnd1 - aStart1);
+
+ const ::basegfx::point::B2DPoint aStart2(rCandidate2.getB2DPoint(nIndex2));
+ const ::basegfx::point::B2DPoint aEnd2(rCandidate2.getB2DPoint(nEnd2));
+ const ::basegfx::vector::B2DVector aVector2(aEnd2 - aStart2);
+
+ aRetval = findCut(
+ aStart1, aVector1, aStart2, aVector2,
+ aCutFlags, pCut1, pCut2);
+ }
+
+ return aRetval;
+ }
+
+ CutFlagValue findCut(
+ const ::basegfx::point::B2DPoint& rEdge1Start, const ::basegfx::vector::B2DVector& rEdge1Delta,
+ const ::basegfx::point::B2DPoint& rEdge2Start, const ::basegfx::vector::B2DVector& rEdge2Delta,
+ CutFlagValue aCutFlags,
+ double* pCut1, double* pCut2)
+ {
+ CutFlagValue aRetval(CUTFLAG_NONE);
+ double fCut1(0.0);
+ double fCut2(0.0);
+ sal_Bool bFinished(!((sal_Bool)(aCutFlags & CUTFLAG_ALL)));
+
+ // test for same points?
+ if(!bFinished
+ && (aCutFlags & (CUTFLAG_START1|CUTFLAG_END1))
+ && (aCutFlags & (CUTFLAG_START2|CUTFLAG_END2)))
+ {
+ // same startpoint?
+ if(!bFinished && (aCutFlags & (CUTFLAG_START1|CUTFLAG_START2)) == (CUTFLAG_START1|CUTFLAG_START2))
+ {
+ if(rEdge1Start.equal(rEdge2Start))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_START1|CUTFLAG_START2);
+ }
+ }
+
+ // same endpoint?
+ if(!bFinished && (aCutFlags & (CUTFLAG_END1|CUTFLAG_END2)) == (CUTFLAG_END1|CUTFLAG_END2))
+ {
+ const ::basegfx::point::B2DPoint aEnd1(rEdge1Start + rEdge1Delta);
+ const ::basegfx::point::B2DPoint aEnd2(rEdge2Start + rEdge2Delta);
+
+ if(aEnd1.equal(aEnd2))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_END1|CUTFLAG_END2);
+ fCut1 = fCut2 = 1.0;
+ }
+ }
+
+ // startpoint1 == endpoint2?
+ if(!bFinished && (aCutFlags & (CUTFLAG_START1|CUTFLAG_END2)) == (CUTFLAG_START1|CUTFLAG_END2))
+ {
+ const ::basegfx::point::B2DPoint aEnd2(rEdge2Start + rEdge2Delta);
+
+ if(rEdge1Start.equal(aEnd2))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_START1|CUTFLAG_END2);
+ fCut1 = 0.0;
+ fCut2 = 1.0;
+ }
+ }
+
+ // startpoint2 == endpoint1?
+ if(!bFinished&& (aCutFlags & (CUTFLAG_START2|CUTFLAG_END1)) == (CUTFLAG_START2|CUTFLAG_END1))
+ {
+ const ::basegfx::point::B2DPoint aEnd1(rEdge1Start + rEdge1Delta);
+
+ if(rEdge2Start.equal(aEnd1))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_START2|CUTFLAG_END1);
+ fCut1 = 1.0;
+ fCut2 = 0.0;
+ }
+ }
+ }
+
+ if(!bFinished && (aCutFlags & CUTFLAG_LINE))
+ {
+ if(!bFinished && (aCutFlags & CUTFLAG_START1))
+ {
+ // start1 on line 2 ?
+ if(isPointOnEdge(rEdge1Start, rEdge2Start, rEdge2Delta, &fCut2))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_LINE|CUTFLAG_START1);
+ }
+ }
+
+ if(!bFinished && (aCutFlags & CUTFLAG_START2))
+ {
+ // start2 on line 1 ?
+ if(isPointOnEdge(rEdge2Start, rEdge1Start, rEdge1Delta, &fCut1))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_LINE|CUTFLAG_START2);
+ }
+ }
+
+ if(!bFinished && (aCutFlags & CUTFLAG_END1))
+ {
+ // end1 on line 2 ?
+ const ::basegfx::point::B2DPoint aEnd1(rEdge1Start + rEdge1Delta);
+
+ if(isPointOnEdge(aEnd1, rEdge2Start, rEdge2Delta, &fCut2))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_LINE|CUTFLAG_END1);
+ }
+ }
+
+ if(!bFinished && (aCutFlags & CUTFLAG_END2))
+ {
+ // end2 on line 1 ?
+ const ::basegfx::point::B2DPoint aEnd2(rEdge2Start + rEdge2Delta);
+
+ if(isPointOnEdge(aEnd2, rEdge1Start, rEdge1Delta, &fCut1))
+ {
+ bFinished = sal_True;
+ aRetval = (CUTFLAG_LINE|CUTFLAG_END2);
+ }
+ }
+
+ if(!bFinished)
+ {
+ // cut in line1, line2 ?
+ fCut1 = (rEdge1Delta.getX() * rEdge2Delta.getY()) - (rEdge1Delta.getY() * rEdge2Delta.getX());
+
+ if(!::basegfx::numeric::fTools::equalZero(fCut1))
+ {
+ fCut1 = (rEdge2Delta.getY() * (rEdge2Start.getX() - rEdge1Start.getX())
+ + rEdge2Delta.getX() * (rEdge1Start.getY() - rEdge2Start.getY())) / fCut1;
+
+ const double fZero(0.0);
+ const double fOne(1.0);
+
+ // inside parameter range edge1 AND fCut2 is calcable
+ if(::basegfx::numeric::fTools::more(fCut1, fZero) && ::basegfx::numeric::fTools::less(fCut1, fOne)
+ && (!::basegfx::numeric::fTools::equalZero(rEdge2Delta.getX()) || !::basegfx::numeric::fTools::equalZero(rEdge2Delta.getY())))
+ {
+ // take the mopre precise calculation of the two possible
+ if(fabs(rEdge2Delta.getX()) > fabs(rEdge2Delta.getY()))
+ {
+ fCut2 = (rEdge1Start.getX() + fCut1
+ * rEdge1Delta.getX() - rEdge2Start.getX()) / rEdge2Delta.getX();
+ }
+ else
+ {
+ fCut2 = (rEdge1Start.getY() + fCut1
+ * rEdge1Delta.getY() - rEdge2Start.getY()) / rEdge2Delta.getY();
+ }
+
+ // inside parameter range edge2, too
+ if(::basegfx::numeric::fTools::more(fCut2, fZero) && ::basegfx::numeric::fTools::less(fCut2, fOne))
+ {
+ bFinished = sal_True;
+ aRetval = CUTFLAG_LINE;
+ }
+ }
+ }
+ }
+ }
+
+ // copy values if wanted
+ if(pCut1)
+ {
+ *pCut1 = fCut1;
+ }
+
+ if(pCut2)
+ {
+ *pCut2 = fCut2;
+ }
+
+ return aRetval;
+ }
+
+ sal_Bool isPointOnEdge(
+ const ::basegfx::point::B2DPoint& rPoint,
+ const ::basegfx::point::B2DPoint& rEdgeStart,
+ const ::basegfx::vector::B2DVector& rEdgeDelta,
+ double* pCut)
+ {
+ sal_Bool bDeltaXIsZero(::basegfx::numeric::fTools::equalZero(rEdgeDelta.getX()));
+ sal_Bool bDeltaYIsZero(::basegfx::numeric::fTools::equalZero(rEdgeDelta.getY()));
+ const double fZero(0.0);
+ const double fOne(1.0);
+
+ if(bDeltaXIsZero && bDeltaYIsZero)
+ {
+ // no line, just a point
+ return sal_False;
+ }
+ else if(bDeltaXIsZero)
+ {
+ // vertical line
+ if(::basegfx::numeric::fTools::equal(rPoint.getX(), rEdgeStart.getX()))
+ {
+ double fValue = (rPoint.getY() - rEdgeStart.getY()) / rEdgeDelta.getY();
+
+ if(::basegfx::numeric::fTools::more(fValue, fZero) && ::basegfx::numeric::fTools::less(fValue, fOne))
+ {
+ if(pCut)
+ {
+ *pCut = fValue;
+ }
+
+ return sal_True;
+ }
+ }
+ }
+ else if(bDeltaYIsZero)
+ {
+ // horizontal line
+ if(::basegfx::numeric::fTools::equal(rPoint.getY(), rEdgeStart.getY()))
+ {
+ double fValue = (rPoint.getX() - rEdgeStart.getX()) / rEdgeDelta.getX();
+
+ if(::basegfx::numeric::fTools::more(fValue, fZero)
+ && ::basegfx::numeric::fTools::less(fValue, fOne))
+ {
+ if(pCut)
+ {
+ *pCut = fValue;
+ }
+
+ return sal_True;
+ }
+ }
+ }
+ else
+ {
+ // any angle line
+ double fTOne = (rPoint.getX() - rEdgeStart.getX()) / rEdgeDelta.getX();
+ double fTTwo = (rPoint.getY() - rEdgeStart.getY()) / rEdgeDelta.getY();
+
+ if(::basegfx::numeric::fTools::equal(fTOne, fTTwo))
+ {
+ // same parameter representation, point is on line. Take
+ // middle value for better results
+ double fValue = (fTOne + fTTwo) / 2.0;
+
+ if(::basegfx::numeric::fTools::more(fValue, fZero) && ::basegfx::numeric::fTools::less(fValue, fOne))
+ {
+ // point is inside line bounds, too
+ if(pCut)
+ {
+ *pCut = fValue;
+ }
+
+ return sal_True;
+ }
+ }
+ }
+
+ return sal_False;
+ }
} // end of namespace tools
} // end of namespace polygon
} // end of namespace basegfx