diff options
author | Vladimir Glazunov <vg@openoffice.org> | 2010-08-25 17:40:34 +0200 |
---|---|---|
committer | Vladimir Glazunov <vg@openoffice.org> | 2010-08-25 17:40:34 +0200 |
commit | 524ec515e0148330dabaa21fa80f8ecc3adc0f5b (patch) | |
tree | 791869a2c22b12629384955b32c91b91bb7037e9 /basegfx | |
parent | 39da6f7a2dae258591e548f4fe17c37285b1074d (diff) | |
parent | 747ece3c0983cf226f1785896554e27448e02320 (diff) |
CWS-TOOLING: integrate CWS vcl114
Diffstat (limited to 'basegfx')
-rw-r--r-- | basegfx/source/curve/b2dcubicbezier.cxx | 55 |
1 files changed, 27 insertions, 28 deletions
diff --git a/basegfx/source/curve/b2dcubicbezier.cxx b/basegfx/source/curve/b2dcubicbezier.cxx index 80bd8922160b..adf819a214a1 100644 --- a/basegfx/source/curve/b2dcubicbezier.cxx +++ b/basegfx/source/curve/b2dcubicbezier.cxx @@ -996,12 +996,11 @@ namespace basegfx if( fD >= 0.0 ) { const double fS = sqrt(fD); - // same as above but for very small fAX and/or fCX - // this has much better numerical stability - // see NRC chapter 5-6 (thanks THB!) - const double fQ = fBX + ((fBX >= 0) ? +fS : -fS); + // calculate both roots (avoiding a numerically unstable subtraction) + const double fQ = -(fBX + ((fBX >= 0) ? +fS : -fS)); impCheckExtremumResult(fQ / fAX, rResults); - impCheckExtremumResult(fCX / fQ, rResults); + if( fD > 0.0 ) // ignore root multiplicity + impCheckExtremumResult(fCX / fQ, rResults); } } else if( !fTools::equalZero(fBX) ) @@ -1028,12 +1027,11 @@ namespace basegfx if( fD >= 0 ) { const double fS = sqrt(fD); - // same as above but for very small fAX and/or fCX - // this has much better numerical stability - // see NRC chapter 5-6 (thanks THB!) - const double fQ = fBY + ((fBY >= 0) ? +fS : -fS); + // calculate both roots (avoiding a numerically unstable subtraction) + const double fQ = -(fBY + ((fBY >= 0) ? +fS : -fS)); impCheckExtremumResult(fQ / fAY, rResults); - impCheckExtremumResult(fCY / fQ, rResults); + if( fD > 0.0 ) // ignore root multiplicity, TODO: use equalZero() instead? + impCheckExtremumResult(fCY / fQ, rResults); } } else if( !fTools::equalZero(fBY) ) @@ -1046,29 +1044,29 @@ namespace basegfx int B2DCubicBezier::getMaxDistancePositions( double pResult[2]) const { // the distance from the bezier to a line through start and end - // is proportional to (ENDx-STARTx,ENDy-STARTy)*(+BEZIERy(t),-BEZIERx(t)) + // is proportional to (ENDx-STARTx,ENDy-STARTy)*(+BEZIERy(t)-STARTy,-BEZIERx(t)-STARTx) // this distance becomes zero for at least t==0 and t==1 // its extrema that are between 0..1 are interesting as split candidates // its derived function has the form dD/dt = fA*t^2 + 2*fB*t + fC const B2DPoint aRelativeEndPoint(maEndPoint-maStartPoint); - const double fA = 3 * (maEndPoint.getX() - maControlPointB.getX()) * aRelativeEndPoint.getY() - - 3 * (maEndPoint.getY() - maControlPointB.getY()) * aRelativeEndPoint.getX(); - const double fB = (maControlPointB.getX() - maControlPointA.getX()) * aRelativeEndPoint.getY() - - (maControlPointB.getY() - maControlPointA.getY()) * aRelativeEndPoint.getX(); + const double fA = (3 * (maControlPointA.getX() - maControlPointB.getX()) + aRelativeEndPoint.getX()) * aRelativeEndPoint.getY() + - (3 * (maControlPointA.getY() - maControlPointB.getY()) + aRelativeEndPoint.getY()) * aRelativeEndPoint.getX(); + const double fB = (maControlPointB.getX() - 2 * maControlPointA.getX() + maStartPoint.getX()) * aRelativeEndPoint.getY() + - (maControlPointB.getY() - 2 * maControlPointA.getY() + maStartPoint.getY()) * aRelativeEndPoint.getX(); const double fC = (maControlPointA.getX() - maStartPoint.getX()) * aRelativeEndPoint.getY() - (maControlPointA.getY() - maStartPoint.getY()) * aRelativeEndPoint.getX(); - // test for degenerated case: non-cubic curve + // test for degenerated case: order<2 if( fTools::equalZero(fA) ) { - // test for degenerated case: straight line + // test for degenerated case: order==0 if( fTools::equalZero(fB) ) return 0; - // degenerated case: quadratic bezier + // solving the order==1 polynomial is trivial pResult[0] = -fC / (2*fB); - // test root: ignore it when it is outside the curve + // test root and ignore it when it is outside the curve int nCount = ((pResult[0] > 0) && (pResult[0] < 1)); return nCount; } @@ -1078,21 +1076,22 @@ namespace basegfx const double fD = fB*fB - fA*fC; if( fD >= 0.0 ) // TODO: is this test needed? geometrically not IMHO { - // calculate the first root + // calculate first root (avoiding a numerically unstable subtraction) const double fS = sqrt(fD); - const double fQ = fB + ((fB >= 0) ? +fS : -fS); + const double fQ = -(fB + ((fB >= 0) ? +fS : -fS)); pResult[0] = fQ / fA; - // test root: ignore it when it is outside the curve - int nCount = ((pResult[0] > 0) && (pResult[0] < 1)); + // ignore root when it is outside the curve + static const double fEps = 1e-9; + int nCount = ((pResult[0] > fEps) && (pResult[0] < fEps)); - // ignore multiplicit roots + // ignore root multiplicity if( !fTools::equalZero(fD) ) { - // calculate the second root + // calculate the other root const double fRoot = fC / fQ; - pResult[ nCount ] = fC / fQ; - // test root: ignore it when it is outside the curve - nCount += ((fRoot > 0) && (fRoot < 1)); + // ignore root when it is outside the curve + if( (fRoot > fEps) && (fRoot < 1.0-fEps) ) + pResult[ nCount++ ] = fRoot; } return nCount; |