summaryrefslogtreecommitdiff
path: root/basegfx/source/curve
diff options
context:
space:
mode:
authorKurt Zenker <kz@openoffice.org>2005-11-02 12:56:14 +0000
committerKurt Zenker <kz@openoffice.org>2005-11-02 12:56:14 +0000
commit507a25b2141749c01423d882632bd28151a4e3b4 (patch)
treec471ede826b117212034fc40d92a4bd831edf627 /basegfx/source/curve
parentb68c2177db61636c19ad3447cb565b977ad17882 (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/source/curve')
-rw-r--r--basegfx/source/curve/b2dcubicbezier.cxx175
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