diff options
author | Kurt Zenker <kz@openoffice.org> | 2005-11-02 12:56:14 +0000 |
---|---|---|
committer | Kurt Zenker <kz@openoffice.org> | 2005-11-02 12:56:14 +0000 |
commit | 507a25b2141749c01423d882632bd28151a4e3b4 (patch) | |
tree | c471ede826b117212034fc40d92a4bd831edf627 /basegfx | |
parent | b68c2177db61636c19ad3447cb565b977ad17882 (diff) |
INTEGRATION: CWS canvas02 (1.9.22); FILE MERGED
2005/10/08 13:13:44 thb 1.9.22.2: RESYNC: (1.9-1.10); FILE MERGED
2005/07/28 10:10:17 thb 1.9.22.1: Join from cws_src680_aw024: #i48939# and new rendering subsystem need AW's clipper changes
Diffstat (limited to 'basegfx')
-rw-r--r-- | basegfx/source/curve/b2dcubicbezier.cxx | 175 |
1 files changed, 159 insertions, 16 deletions
diff --git a/basegfx/source/curve/b2dcubicbezier.cxx b/basegfx/source/curve/b2dcubicbezier.cxx index a221df17fb44..335e9ec154b0 100644 --- a/basegfx/source/curve/b2dcubicbezier.cxx +++ b/basegfx/source/curve/b2dcubicbezier.cxx @@ -4,9 +4,9 @@ * * $RCSfile: b2dcubicbezier.cxx,v $ * - * $Revision: 1.10 $ + * $Revision: 1.11 $ * - * last change: $Author: rt $ $Date: 2005-09-07 20:40:27 $ + * last change: $Author: kz $ $Date: 2005-11-02 13:56:14 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -314,8 +314,7 @@ namespace basegfx { } - B2DCubicBezier::B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rControlPointA, - const B2DPoint& rControlPointB, const B2DPoint& rEnd) + B2DCubicBezier::B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rControlPointA, const B2DPoint& rControlPointB, const B2DPoint& rEnd) : maStartPoint(rStart), maEndPoint(rEnd), maControlPointA(rControlPointA), @@ -323,6 +322,14 @@ namespace basegfx { } + B2DCubicBezier::B2DCubicBezier(const B2DPoint& rStart, const B2DVector& rControlVectorA, const B2DVector& rControlVectorB, const B2DPoint& rEnd) + : maStartPoint(rStart), + maEndPoint(rEnd), + maControlPointA(rStart + rControlVectorA), + maControlPointB(rStart + rControlVectorB) + { + } + B2DCubicBezier::~B2DCubicBezier() { } @@ -402,19 +409,10 @@ namespace basegfx { rTarget.append(maStartPoint); - if(nCount) + for(sal_uInt32 a(0L); a < nCount; a++) { - for(sal_uInt32 a(0L); a < nCount; a++) - { - const double fPos(double(a + 1L) / double(nCount + 1L)); - const B2DPoint aS1L(interpolate(maStartPoint, maControlPointA, fPos)); - const B2DPoint aS1C(interpolate(maControlPointA, maControlPointB, fPos)); - const B2DPoint aS1R(interpolate(maControlPointB, maEndPoint, fPos)); - const B2DPoint aS2L(interpolate(aS1L, aS1C, fPos)); - const B2DPoint aS2R(interpolate(aS1C, aS1R, fPos)); - const B2DPoint aS3C(interpolate(aS2L, aS2R, fPos)); - rTarget.append(aS3C); - } + const double fPos(double(a + 1L) / double(nCount + 1L)); + rTarget.append(interpolatePoint(fPos)); } if(bAddLastPoint) @@ -422,6 +420,151 @@ namespace basegfx rTarget.append(maEndPoint); } } + + B2DPoint B2DCubicBezier::interpolatePoint(double t) const + { + OSL_ENSURE(t >= 0.0 && t <= 1.0, "B2DCubicBezier::interpolatePoint: Access out of range (!)"); + const B2DPoint aS1L(interpolate(maStartPoint, maControlPointA, t)); + const B2DPoint aS1C(interpolate(maControlPointA, maControlPointB, t)); + const B2DPoint aS1R(interpolate(maControlPointB, maEndPoint, t)); + const B2DPoint aS2L(interpolate(aS1L, aS1C, t)); + const B2DPoint aS2R(interpolate(aS1C, aS1R, t)); + return interpolate(aS2L, aS2R, t); + } + + double B2DCubicBezier::getSmallestDistancePointToBezierSegment(const B2DPoint& rTestPoint, double& rCut) const + { + const sal_uInt32 nInitialDivisions(3L); + B2DPolygon aInitialPolygon; + + // as start make a fix division, creates nInitialDivisions + 2L points + adaptiveSubdivideByCount(aInitialPolygon, nInitialDivisions, true); + + // now look for the closest point + const sal_uInt32 nPointCount(aInitialPolygon.count()); + B2DVector aVector(rTestPoint - aInitialPolygon.getB2DPoint(0L)); + double fQuadDist(aVector.getX() * aVector.getX() + aVector.getY() * aVector.getY()); + double fNewQuadDist; + sal_uInt32 nSmallestIndex(0L); + + for(sal_uInt32 a(1L); a < nPointCount; a++) + { + aVector = B2DVector(rTestPoint - aInitialPolygon.getB2DPoint(a)); + fNewQuadDist = aVector.getX() * aVector.getX() + aVector.getY() * aVector.getY(); + + if(fNewQuadDist < fQuadDist) + { + fQuadDist = fNewQuadDist; + nSmallestIndex = a; + } + } + + // look right and left for even smaller distances + double fStepValue(1.0 / (double)((nPointCount - 1L) * 2L)); // half the edge step width + double fPosition((double)nSmallestIndex / (double)(nPointCount - 1L)); + bool bDone(false); + + while(!bDone) + { + if(!bDone) + { + // test left + double fPosLeft(fPosition - fStepValue); + + if(fPosLeft < 0.0) + { + fPosLeft = 0.0; + aVector = B2DVector(rTestPoint - maStartPoint); + } + else + { + aVector = B2DVector(rTestPoint - interpolatePoint(fPosLeft)); + } + + fNewQuadDist = aVector.getX() * aVector.getX() + aVector.getY() * aVector.getY(); + + if(fTools::less(fNewQuadDist, fQuadDist)) + { + fQuadDist = fNewQuadDist; + fPosition = fPosLeft; + } + else + { + // test right + double fPosRight(fPosition + fStepValue); + + if(fPosRight > 1.0) + { + fPosRight = 1.0; + aVector = B2DVector(rTestPoint - maEndPoint); + } + else + { + aVector = B2DVector(rTestPoint - interpolatePoint(fPosRight)); + } + + fNewQuadDist = aVector.getX() * aVector.getX() + aVector.getY() * aVector.getY(); + + if(fTools::less(fNewQuadDist, fQuadDist)) + { + fQuadDist = fNewQuadDist; + fPosition = fPosRight; + } + else + { + // not less left or right, done + bDone = true; + } + } + } + + if(0.0 == fPosition || 1.0 == fPosition) + { + // if we are completely left or right, we are done + bDone = true; + } + + if(!bDone) + { + // prepare next step value + fStepValue /= 2.0; + } + } + + rCut = fPosition; + return sqrt(fQuadDist); + } + + void B2DCubicBezier::split(double t, B2DCubicBezier& rBezierA, B2DCubicBezier& rBezierB) const + { + OSL_ENSURE(t >= 0.0 && t <= 1.0, "B2DCubicBezier::split: Access out of range (!)"); + const B2DPoint aS1L(interpolate(maStartPoint, maControlPointA, t)); + const B2DPoint aS1C(interpolate(maControlPointA, maControlPointB, t)); + const B2DPoint aS1R(interpolate(maControlPointB, maEndPoint, t)); + const B2DPoint aS2L(interpolate(aS1L, aS1C, t)); + const B2DPoint aS2R(interpolate(aS1C, aS1R, t)); + const B2DPoint aS3C(interpolate(aS2L, aS2R, t)); + + rBezierA.setStartPoint(maStartPoint); + rBezierA.setEndPoint(aS3C); + rBezierA.setControlPointA(aS1L); + rBezierA.setControlPointB(aS2L); + + rBezierB.setStartPoint(aS3C); + rBezierB.setEndPoint(maEndPoint); + rBezierB.setControlPointA(aS2R); + rBezierB.setControlPointB(aS1R); + } + + B2DRange B2DCubicBezier::getRange() const + { + B2DRange aRetval(maStartPoint, maEndPoint); + + aRetval.expand(maControlPointA); + aRetval.expand(maControlPointB); + + return aRetval; + } } // end of namespace basegfx // eof |