/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basegfx.hxx"
#include <basegfx/curve/b2dcubicbezier.hxx>
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/numeric/ftools.hxx>

#include <limits>

// #i37443# 
#define FACTOR_FOR_UNSHARPEN	(1.6)
#ifdef DBG_UTIL
static double fMultFactUnsharpen = FACTOR_FOR_UNSHARPEN;
#endif

//////////////////////////////////////////////////////////////////////////////

namespace basegfx
{
	namespace
	{
		void ImpSubDivAngle(
			const B2DPoint& rfPA,			// start point
			const B2DPoint& rfEA,			// edge on A
			const B2DPoint& rfEB,			// edge on B
			const B2DPoint& rfPB,			// end point
			B2DPolygon& rTarget,			// target polygon
			double fAngleBound,				// angle bound in [0.0 .. 2PI]
			bool bAllowUnsharpen,			// #i37443# allow the criteria to get unsharp in recursions
			sal_uInt16 nMaxRecursionDepth)	// endless loop protection
		{
			if(nMaxRecursionDepth)
			{
				// do angle test
				B2DVector aLeft(rfEA - rfPA);
				B2DVector aRight(rfEB - rfPB);
				
				// #i72104#
				if(aLeft.equalZero())
				{
					aLeft = rfEB - rfPA;
				}

				if(aRight.equalZero())
				{
					aRight = rfEA - rfPB;
				}

				const double fCurrentAngle(aLeft.angle(aRight));

				if(fabs(fCurrentAngle) > (F_PI - fAngleBound))
				{
					// end recursion
					nMaxRecursionDepth = 0;
				}
				else
				{
					if(bAllowUnsharpen)
					{
						// #i37443# unsharpen criteria
#ifdef DBG_UTIL
						fAngleBound *= fMultFactUnsharpen;
#else
						fAngleBound *= FACTOR_FOR_UNSHARPEN;
#endif
					}
				}
			}

			if(nMaxRecursionDepth)
			{
				// divide at 0.5
				const B2DPoint aS1L(average(rfPA, rfEA));
				const B2DPoint aS1C(average(rfEA, rfEB));
				const B2DPoint aS1R(average(rfEB, rfPB));
				const B2DPoint aS2L(average(aS1L, aS1C));
				const B2DPoint aS2R(average(aS1C, aS1R));
				const B2DPoint aS3C(average(aS2L, aS2R));

				// left recursion
				ImpSubDivAngle(rfPA, aS1L, aS2L, aS3C, rTarget, fAngleBound, bAllowUnsharpen, nMaxRecursionDepth - 1);

				// right recursion
				ImpSubDivAngle(aS3C, aS2R, aS1R, rfPB, rTarget, fAngleBound, bAllowUnsharpen, nMaxRecursionDepth - 1);
			}
			else
			{
				rTarget.append(rfPB);
			}
		}

		void ImpSubDivAngleStart(
			const B2DPoint& rfPA,			// start point
			const B2DPoint& rfEA,			// edge on A
			const B2DPoint& rfEB,			// edge on B
			const B2DPoint& rfPB,			// end point
			B2DPolygon& rTarget,			// target polygon
			const double& rfAngleBound,		// angle bound in [0.0 .. 2PI]
			bool bAllowUnsharpen)			// #i37443# allow the criteria to get unsharp in recursions
		{
			sal_uInt16 nMaxRecursionDepth(8);
			const B2DVector aLeft(rfEA - rfPA);
			const B2DVector aRight(rfEB - rfPB);
			bool bLeftEqualZero(aLeft.equalZero());
			bool bRightEqualZero(aRight.equalZero());
			bool bAllParallel(false);

			if(bLeftEqualZero && bRightEqualZero)
			{
				nMaxRecursionDepth = 0;
			}
			else
			{
				const B2DVector aBase(rfPB - rfPA);
				const bool bBaseEqualZero(aBase.equalZero()); // #i72104#

				if(!bBaseEqualZero)
				{
					const bool bLeftParallel(bLeftEqualZero ? true : areParallel(aLeft, aBase));
					const bool bRightParallel(bRightEqualZero ? true : areParallel(aRight, aBase));

					if(bLeftParallel && bRightParallel)
					{
						bAllParallel = true;

						if(!bLeftEqualZero)
						{
							double fFactor;
							
							if(fabs(aBase.getX()) > fabs(aBase.getY()))
							{
								fFactor = aLeft.getX() / aBase.getX();
							}
							else
							{
								fFactor = aLeft.getY() / aBase.getY();
							}

							if(fFactor >= 0.0 && fFactor <= 1.0)
							{
								bLeftEqualZero = true;
							}
						}

						if(!bRightEqualZero)
						{
							double fFactor;
							
							if(fabs(aBase.getX()) > fabs(aBase.getY()))
							{
								fFactor = aRight.getX() / -aBase.getX();
							}
							else
							{
								fFactor = aRight.getY() / -aBase.getY();
							}

							if(fFactor >= 0.0 && fFactor <= 1.0)
							{
								bRightEqualZero = true;
							}
						}

						if(bLeftEqualZero && bRightEqualZero)
						{
							nMaxRecursionDepth = 0;
						}
					}
				}
			}

			if(nMaxRecursionDepth)
			{
				// divide at 0.5 ad test both edges for angle criteria
				const B2DPoint aS1L(average(rfPA, rfEA));
				const B2DPoint aS1C(average(rfEA, rfEB));
				const B2DPoint aS1R(average(rfEB, rfPB));
				const B2DPoint aS2L(average(aS1L, aS1C));
				const B2DPoint aS2R(average(aS1C, aS1R));
				const B2DPoint aS3C(average(aS2L, aS2R));

				// test left
				bool bAngleIsSmallerLeft(bAllParallel && bLeftEqualZero);
				if(!bAngleIsSmallerLeft)
				{
					const B2DVector aLeftLeft(bLeftEqualZero ? aS2L - aS1L : aS1L - rfPA); // #i72104#
					const B2DVector aRightLeft(aS2L - aS3C);
					const double fCurrentAngleLeft(aLeftLeft.angle(aRightLeft));
					bAngleIsSmallerLeft = (fabs(fCurrentAngleLeft) > (F_PI - rfAngleBound));
				}

				// test right
				bool bAngleIsSmallerRight(bAllParallel && bRightEqualZero);
				if(!bAngleIsSmallerRight)
				{
					const B2DVector aLeftRight(aS2R - aS3C);
					const B2DVector aRightRight(bRightEqualZero ? aS2R - aS1R : aS1R - rfPB); // #i72104#
					const double fCurrentAngleRight(aLeftRight.angle(aRightRight));
					bAngleIsSmallerRight = (fabs(fCurrentAngleRight) > (F_PI - rfAngleBound));
				}

				if(bAngleIsSmallerLeft && bAngleIsSmallerRight)
				{
					// no recursion necessary at all
					nMaxRecursionDepth = 0;
				}
				else
				{
					// left
					if(bAngleIsSmallerLeft)
					{
						rTarget.append(aS3C);
					}
					else
					{
						ImpSubDivAngle(rfPA, aS1L, aS2L, aS3C, rTarget, rfAngleBound, bAllowUnsharpen, nMaxRecursionDepth);
					}

					// right
					if(bAngleIsSmallerRight)
					{
						rTarget.append(rfPB);
					}
					else
					{
						ImpSubDivAngle(aS3C, aS2R, aS1R, rfPB, rTarget, rfAngleBound, bAllowUnsharpen, nMaxRecursionDepth);
					}
				}
			}

			if(!nMaxRecursionDepth)
			{
				rTarget.append(rfPB);
			}
		}

		void ImpSubDivDistance(
			const B2DPoint& rfPA,			// start point
			const B2DPoint& rfEA,			// edge on A
			const B2DPoint& rfEB,			// edge on B
			const B2DPoint& rfPB,			// end point
			B2DPolygon& rTarget,			// target polygon
			double fDistanceBound2,			// quadratic distance criteria
			double fLastDistanceError2,		// the last quadratic distance error
			sal_uInt16 nMaxRecursionDepth)	// endless loop protection
		{
			if(nMaxRecursionDepth)
			{
				// decide if another recursion is needed. If not, set
				// nMaxRecursionDepth to zero

				// Perform bezier flatness test (lecture notes from R. Schaback,
				// Mathematics of Computer-Aided Design, Uni Goettingen, 2000)
				//
				// ||P(t) - L(t)|| <= max     ||b_j - b_0 - j/n(b_n - b_0)||
				//                    0<=j<=n
				//
				// What is calculated here is an upper bound to the distance from
				// a line through b_0 and b_3 (rfPA and P4 in our notation) and the
				// curve. We can drop 0 and n from the running indices, since the
				// argument of max becomes zero for those cases.
				const double fJ1x(rfEA.getX() - rfPA.getX() - 1.0/3.0*(rfPB.getX() - rfPA.getX()));
				const double fJ1y(rfEA.getY() - rfPA.getY() - 1.0/3.0*(rfPB.getY() - rfPA.getY()));
				const double fJ2x(rfEB.getX() - rfPA.getX() - 2.0/3.0*(rfPB.getX() - rfPA.getX()));
				const double fJ2y(rfEB.getY() - rfPA.getY() - 2.0/3.0*(rfPB.getY() - rfPA.getY()));
				const double fDistanceError2(::std::max(fJ1x*fJ1x + fJ1y*fJ1y, fJ2x*fJ2x + fJ2y*fJ2y));

				// stop if error measure does not improve anymore. This is a
				// safety guard against floating point inaccuracies.
				// stop if distance from line is guaranteed to be bounded by d
				const bool bFurtherDivision(fLastDistanceError2 > fDistanceError2 && fDistanceError2 >= fDistanceBound2);

				if(bFurtherDivision)
				{
					// remember last error value
					fLastDistanceError2 = fDistanceError2;
				}
				else
				{
					// stop recustion
					nMaxRecursionDepth = 0;
				}
			}

			if(nMaxRecursionDepth)
			{
				// divide at 0.5
				const B2DPoint aS1L(average(rfPA, rfEA));
				const B2DPoint aS1C(average(rfEA, rfEB));
				const B2DPoint aS1R(average(rfEB, rfPB));
				const B2DPoint aS2L(average(aS1L, aS1C));
				const B2DPoint aS2R(average(aS1C, aS1R));
				const B2DPoint aS3C(average(aS2L, aS2R));

				// left recursion
				ImpSubDivDistance(rfPA, aS1L, aS2L, aS3C, rTarget, fDistanceBound2, fLastDistanceError2, nMaxRecursionDepth - 1);

				// right recursion
				ImpSubDivDistance(aS3C, aS2R, aS1R, rfPB, rTarget, fDistanceBound2, fLastDistanceError2, nMaxRecursionDepth - 1);
			}
			else
			{
				rTarget.append(rfPB);
			}
		}
	} // end of anonymous namespace
} // end of namespace basegfx

//////////////////////////////////////////////////////////////////////////////

namespace basegfx
{
	B2DCubicBezier::B2DCubicBezier(const B2DCubicBezier& rBezier)
	:	maStartPoint(rBezier.maStartPoint),
		maEndPoint(rBezier.maEndPoint),
		maControlPointA(rBezier.maControlPointA),
		maControlPointB(rBezier.maControlPointB)
	{
	}
	
	B2DCubicBezier::B2DCubicBezier()
	{
	}
	
	B2DCubicBezier::B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rEnd)
	:	maStartPoint(rStart),
		maEndPoint(rEnd),
		maControlPointA(rStart),
		maControlPointB(rEnd)
	{
	}

	B2DCubicBezier::B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rControlPointA, const B2DPoint& rControlPointB, const B2DPoint& rEnd)
	:	maStartPoint(rStart),
		maEndPoint(rEnd),
		maControlPointA(rControlPointA),
		maControlPointB(rControlPointB)
	{
	}

	B2DCubicBezier::~B2DCubicBezier()
	{
	}

	// assignment operator
	B2DCubicBezier& B2DCubicBezier::operator=(const B2DCubicBezier& rBezier)
	{
		maStartPoint = rBezier.maStartPoint;
		maEndPoint = rBezier.maEndPoint;
		maControlPointA = rBezier.maControlPointA;
		maControlPointB = rBezier.maControlPointB;
		
		return *this;
	}

	// compare operators
	bool B2DCubicBezier::operator==(const B2DCubicBezier& rBezier) const
	{
		return (
			maStartPoint == rBezier.maStartPoint
			&& maEndPoint == rBezier.maEndPoint
			&& maControlPointA == rBezier.maControlPointA
			&& maControlPointB == rBezier.maControlPointB
		);
	}

	bool B2DCubicBezier::operator!=(const B2DCubicBezier& rBezier) const
	{
		return (
			maStartPoint != rBezier.maStartPoint
			|| maEndPoint != rBezier.maEndPoint
			|| maControlPointA != rBezier.maControlPointA
			|| maControlPointB != rBezier.maControlPointB
		);
	}

    bool B2DCubicBezier::equal(const B2DCubicBezier& rBezier) const
    {
		return (
			maStartPoint.equal(rBezier.maStartPoint)
			&& maEndPoint.equal(rBezier.maEndPoint)
			&& maControlPointA.equal(rBezier.maControlPointA)
			&& maControlPointB.equal(rBezier.maControlPointB)
		);
    }

	// test if vectors are used
	bool B2DCubicBezier::isBezier() const
	{
		if(maControlPointA != maStartPoint || maControlPointB != maEndPoint)
		{
			return true;
		}

		return false;
	}

	void B2DCubicBezier::testAndSolveTrivialBezier()
	{
		if(maControlPointA != maStartPoint || maControlPointB != maEndPoint)
		{
			const B2DVector aEdge(maEndPoint - maStartPoint);
			
			// controls parallel to edge can be trivial. No edge -> not parallel -> control can 
            // still not be trivial (e.g. ballon loop)
			if(!aEdge.equalZero())
			{
                // get control vectors
				const B2DVector aVecA(maControlPointA - maStartPoint);
				const B2DVector aVecB(maControlPointB - maEndPoint);

                // check if trivial per se
                bool bAIsTrivial(aVecA.equalZero());
                bool bBIsTrivial(aVecB.equalZero());

                // #i102241# prepare inverse edge length to normalize cross values;
                // else the small compare value used in fTools::equalZero
                // will be length dependent and this detection will work as less
                // precise as longer the edge is. In principle, the length of the control
				// vector would need to be used too, but to be trivial it is assumed to
				// be of roughly equal length to the edge, so edge length can be used
				// for both. Only needed when one of both is not trivial per se.
                const double fInverseEdgeLength(bAIsTrivial && bBIsTrivial 
					? 1.0 
					: 1.0 / aEdge.getLength());

				// if A is not zero, check if it could be
				if(!bAIsTrivial)
				{
					// #i102241# parallel to edge? Check aVecA, aEdge. Use cross() which does what
					// we need here with the precision we need
					const double fCross(aVecA.cross(aEdge) * fInverseEdgeLength);

					if(fTools::equalZero(fCross))
					{
						// get scale to edge. Use bigger distance for numeric quality
						const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY()) 
							? aVecA.getX() / aEdge.getX() 
							: aVecA.getY() / aEdge.getY());

						// relative end point of vector in edge range?
						if(fTools::moreOrEqual(fScale, 0.0) && fTools::lessOrEqual(fScale, 1.0))
						{
							bAIsTrivial = true;
						}
					}
				}

                // if B is not zero, check if it could be, but only if A is already trivial;
                // else solve to trivial will not be possible for whole edge
				if(bAIsTrivial && !bBIsTrivial)
				{
					// parallel to edge? Check aVecB, aEdge
					const double fCross(aVecB.cross(aEdge) * fInverseEdgeLength);
					
					if(fTools::equalZero(fCross))
					{
						// get scale to edge. Use bigger distance for numeric quality
						const double fScale(fabs(aEdge.getX()) > fabs(aEdge.getY()) 
							? aVecB.getX() / aEdge.getX() 
							: aVecB.getY() / aEdge.getY());

						// end point of vector in edge range? Caution: controlB is directed AGAINST edge
						if(fTools::lessOrEqual(fScale, 0.0) && fTools::moreOrEqual(fScale, -1.0))
						{
							bBIsTrivial = true;
						}
					}
				}

                // if both are/can be reduced, do it.
				// Not possible if only one is/can be reduced (!)
				if(bAIsTrivial && bBIsTrivial)
				{
					maControlPointA = maStartPoint;
					maControlPointB = maEndPoint;
				}
			}
		}
	}

    namespace {
        double impGetLength(const B2DCubicBezier& rEdge, double fDeviation, sal_uInt32 nRecursionWatch)
        {
            const double fEdgeLength(rEdge.getEdgeLength());
            const double fControlPolygonLength(rEdge.getControlPolygonLength());
            const double fCurrentDeviation(fTools::equalZero(fControlPolygonLength) ? 0.0 : 1.0 - (fEdgeLength / fControlPolygonLength));

            if(!nRecursionWatch || fTools:: lessOrEqual(fCurrentDeviation, fDeviation))
            {
                return (fEdgeLength + fControlPolygonLength) * 0.5;
            }
            else
            {
                B2DCubicBezier aLeft, aRight;
                const double fNewDeviation(fDeviation * 0.5);
                const sal_uInt32 nNewRecursionWatch(nRecursionWatch - 1);

                rEdge.split(0.5, &aLeft, &aRight);

                return impGetLength(aLeft, fNewDeviation, nNewRecursionWatch)
                    + impGetLength(aRight, fNewDeviation, nNewRecursionWatch);
            }
        }
    }

	double B2DCubicBezier::getLength(double fDeviation) const
    {
        if(isBezier())
        {
            if(fDeviation < 0.00000001)
            {
                fDeviation = 0.00000001;
            }

            return impGetLength(*this, fDeviation, 6);
        }
        else
        {
            return B2DVector(getEndPoint() - getStartPoint()).getLength();
        }
    }

	double B2DCubicBezier::getEdgeLength() const
	{
		const B2DVector aEdge(maEndPoint - maStartPoint);
		return aEdge.getLength();
	}

	double B2DCubicBezier::getControlPolygonLength() const
	{
		const B2DVector aVectorA(maControlPointA - maStartPoint);
		const B2DVector aVectorB(maEndPoint - maControlPointB);

		if(!aVectorA.equalZero() || !aVectorB.equalZero())
		{
			const B2DVector aTop(maControlPointB - maControlPointA);
			return (aVectorA.getLength() + aVectorB.getLength() + aTop.getLength());
		}
		else
		{
			return getEdgeLength();
		}
	}

	void B2DCubicBezier::adaptiveSubdivideByAngle(B2DPolygon& rTarget, double fAngleBound, bool bAllowUnsharpen) const
	{
		if(isBezier())
		{
			// use support method #i37443# and allow unsharpen the criteria
			ImpSubDivAngleStart(maStartPoint, maControlPointA, maControlPointB, maEndPoint, rTarget, fAngleBound * F_PI180, bAllowUnsharpen);
		}
		else
		{
			rTarget.append(getEndPoint());
		}
	}

    B2DVector B2DCubicBezier::getTangent(double t) const
    {
        if(fTools::lessOrEqual(t, 0.0))
        {
            // tangent in start point
            B2DVector aTangent(getControlPointA() - getStartPoint());

            if(!aTangent.equalZero())
            {
                return aTangent;
            }

            // start point and control vector are the same, fallback
            // to implicit start vector to control point B
            aTangent = (getControlPointB() - getStartPoint()) * 0.3;

            if(!aTangent.equalZero())
            {
                return aTangent;
            }

            // not a bezier at all, return edge vector
            return (getEndPoint() - getStartPoint()) * 0.3;
        }
        else if(fTools::moreOrEqual(t, 1.0))
        {
            // tangent in end point
            B2DVector aTangent(getEndPoint() - getControlPointB());

            if(!aTangent.equalZero())
            {
                return aTangent;
            }

            // end point and control vector are the same, fallback
            // to implicit start vector from control point A
            aTangent = (getEndPoint() - getControlPointA()) * 0.3;

            if(!aTangent.equalZero())
            {
                return aTangent;
            }

            // not a bezier at all, return edge vector
            return (getEndPoint() - getStartPoint()) * 0.3;
        }
        else
        {
            // t is in ]0.0 .. 1.0[. Split and extract
            B2DCubicBezier aRight;
            split(t, 0, &aRight);

            return aRight.getControlPointA() - aRight.getStartPoint();
        }
    }

	// #i37443# adaptive subdivide by nCount subdivisions
	void B2DCubicBezier::adaptiveSubdivideByCount(B2DPolygon& rTarget, sal_uInt32 nCount) const
	{
		const double fLenFact(1.0 / static_cast< double >(nCount + 1));

		for(sal_uInt32 a(1); a <= nCount; a++)
		{
			const double fPos(static_cast< double >(a) * fLenFact);
			rTarget.append(interpolatePoint(fPos));
		}

		rTarget.append(getEndPoint());
	}

	// adaptive subdivide by distance
	void B2DCubicBezier::adaptiveSubdivideByDistance(B2DPolygon& rTarget, double fDistanceBound) const
	{
		if(isBezier())
		{
			ImpSubDivDistance(maStartPoint, maControlPointA, maControlPointB, maEndPoint, rTarget, 
				fDistanceBound * fDistanceBound, ::std::numeric_limits<double>::max(), 30);
		}
		else
		{
			rTarget.append(getEndPoint());
		}
	}

	B2DPoint B2DCubicBezier::interpolatePoint(double t) const
	{
		OSL_ENSURE(t >= 0.0 && t <= 1.0, "B2DCubicBezier::interpolatePoint: Access out of range (!)");

		if(isBezier())
		{
			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);
		}
		else
		{
			return interpolate(maStartPoint, maEndPoint, 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
		aInitialPolygon.append(getStartPoint());
		adaptiveSubdivideByCount(aInitialPolygon, nInitialDivisions);

		// 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* pBezierA, B2DCubicBezier* pBezierB) const
	{
		OSL_ENSURE(t >= 0.0 && t <= 1.0, "B2DCubicBezier::split: Access out of range (!)");

		if(!pBezierA && !pBezierB)
		{
			return;
		}

		if(isBezier())
		{
			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));

			if(pBezierA)
			{
				pBezierA->setStartPoint(maStartPoint);
				pBezierA->setEndPoint(aS3C);
				pBezierA->setControlPointA(aS1L);
				pBezierA->setControlPointB(aS2L);
			}

			if(pBezierB)
			{
				pBezierB->setStartPoint(aS3C);
				pBezierB->setEndPoint(maEndPoint);
				pBezierB->setControlPointA(aS2R);
				pBezierB->setControlPointB(aS1R);
			}
		}
		else
		{
			const B2DPoint aSplit(interpolate(maStartPoint, maEndPoint, t));

			if(pBezierA)
			{
				pBezierA->setStartPoint(maStartPoint);
				pBezierA->setEndPoint(aSplit);
				pBezierA->setControlPointA(maStartPoint);
				pBezierA->setControlPointB(aSplit);
			}

			if(pBezierB)
			{
				pBezierB->setStartPoint(aSplit);
				pBezierB->setEndPoint(maEndPoint);
				pBezierB->setControlPointA(aSplit);
				pBezierB->setControlPointB(maEndPoint);
			}
		}
	}

	B2DCubicBezier B2DCubicBezier::snippet(double fStart, double fEnd) const
	{
		B2DCubicBezier aRetval;
		
		if(fTools::more(fStart, 1.0))
		{
			fStart = 1.0;
		}
		else if(fTools::less(fStart, 0.0))
		{
			fStart = 0.0;
		}

		if(fTools::more(fEnd, 1.0))
		{
			fEnd = 1.0;
		}
		else if(fTools::less(fEnd, 0.0))
		{
			fEnd = 0.0;
		}

		if(fEnd <= fStart)
		{
			// empty or NULL, create single point at center
			const double fSplit((fEnd + fStart) * 0.5);
			const B2DPoint aPoint(interpolate(getStartPoint(), getEndPoint(), fSplit));
			aRetval.setStartPoint(aPoint);
			aRetval.setEndPoint(aPoint);
			aRetval.setControlPointA(aPoint);
			aRetval.setControlPointB(aPoint);
		}
		else
		{
			if(isBezier())
			{
				// copy bezier; cut off right, then cut off left. Do not forget to
				// adapt cut value when both cuts happen
				const bool bEndIsOne(fTools::equal(fEnd, 1.0));
				const bool bStartIsZero(fTools::equalZero(fStart));
				aRetval = *this;

				if(!bEndIsOne)
				{
					aRetval.split(fEnd, &aRetval, 0);

					if(!bStartIsZero)
					{
						fStart /= fEnd;
					}
				}

				if(!bStartIsZero)
				{
					aRetval.split(fStart, 0, &aRetval);
				}
			}
			else
			{
				// no bezier, create simple edge
				const B2DPoint aPointA(interpolate(getStartPoint(), getEndPoint(), fStart));
				const B2DPoint aPointB(interpolate(getStartPoint(), getEndPoint(), fEnd));
				aRetval.setStartPoint(aPointA);
				aRetval.setEndPoint(aPointB);
				aRetval.setControlPointA(aPointA);
				aRetval.setControlPointB(aPointB);
			}
		}

		return aRetval;
	}

	B2DRange B2DCubicBezier::getRange() const
	{
		B2DRange aRetval(maStartPoint, maEndPoint);

		aRetval.expand(maControlPointA);
		aRetval.expand(maControlPointB);

		return aRetval;
	}

	bool B2DCubicBezier::getMinimumExtremumPosition(double& rfResult) const
	{
		::std::vector< double > aAllResults;

		aAllResults.reserve(4);
		getAllExtremumPositions(aAllResults);

		const sal_uInt32 nCount(aAllResults.size());

		if(!nCount)
		{
			return false;
		}
		else if(1 == nCount)
		{
			rfResult = aAllResults[0];
			return true;
		}
		else
		{
			rfResult = *(::std::min_element(aAllResults.begin(), aAllResults.end()));
			return true;
		}
	}

	namespace
	{
		inline void impCheckExtremumResult(double fCandidate, ::std::vector< double >& rResult)
		{
            // check for range ]0.0 .. 1.0[ with excluding 1.0 and 0.0 clearly
            // by using the equalZero test, NOT ::more or ::less which will use the
            // ApproxEqual() which is too exact here
            if(fCandidate > 0.0 && !fTools::equalZero(fCandidate))
            {
                if(fCandidate < 1.0 && !fTools::equalZero(fCandidate - 1.0))
                {
    				rResult.push_back(fCandidate);
                }
			}
		}
	}

	void B2DCubicBezier::getAllExtremumPositions(::std::vector< double >& rResults) const
	{
		rResults.clear();

		// calculate the x-extrema parameters by zeroing first x-derivative
		// of the cubic bezier's parametric formula, which results in a
		// quadratic equation: dBezier/dt = t*t*fAX - 2*t*fBX + fCX
		const B2DPoint aControlDiff( maControlPointA - maControlPointB );
		double fCX = maControlPointA.getX() - maStartPoint.getX();
		const double fBX = fCX + aControlDiff.getX();
		const double fAX = 3 * aControlDiff.getX() + (maEndPoint.getX() - maStartPoint.getX());

		if(fTools::equalZero(fCX))
		{
			// detect fCX equal zero and truncate to real zero value in that case
			fCX = 0.0;
		}

		if( !fTools::equalZero(fAX) )
		{
			// derivative is polynomial of order 2 => use binomial formula
			const double fD = fBX*fBX - fAX*fCX;
			if( fD >= 0.0 )
			{
				const double fS = sqrt(fD);
				// calculate both roots (avoiding a numerically unstable subtraction)
				const double fQ = fBX + ((fBX >= 0) ? +fS : -fS);
				impCheckExtremumResult(fQ / fAX, rResults);
				if( !fTools::equalZero(fS) ) // ignore root multiplicity
					impCheckExtremumResult(fCX / fQ, rResults);
			}
		}
		else if( !fTools::equalZero(fBX) )
		{
			// derivative is polynomial of order 1 => one extrema
			impCheckExtremumResult(fCX / (2 * fBX), rResults);
		}

		// calculate the y-extrema parameters by zeroing first y-derivative
		double fCY = maControlPointA.getY() - maStartPoint.getY();
		const double fBY = fCY + aControlDiff.getY();
		const double fAY = 3 * aControlDiff.getY() + (maEndPoint.getY() - maStartPoint.getY());

		if(fTools::equalZero(fCY))
		{
			// detect fCY equal zero and truncate to real zero value in that case
			fCY = 0.0;
		}

		if( !fTools::equalZero(fAY) )
		{
			// derivative is polynomial of order 2 => use binomial formula
			const double fD = fBY*fBY - fAY*fCY;
			if( fD >= 0.0 )
			{
				const double fS = sqrt(fD);
				// calculate both roots (avoiding a numerically unstable subtraction)
				const double fQ = fBY + ((fBY >= 0) ? +fS : -fS);
				impCheckExtremumResult(fQ / fAY, rResults);
				if( !fTools::equalZero(fS) ) // ignore root multiplicity
					impCheckExtremumResult(fCY / fQ, rResults);
			}
		}
		else if( !fTools::equalZero(fBY) )
		{
			// derivative is polynomial of order 1 => one extrema
			impCheckExtremumResult(fCY / (2 * fBY), rResults);
		}
	}

	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)-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 * (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: order<2
		if( fTools::equalZero(fA) )
		{
			// test for degenerated case: order==0
			if( fTools::equalZero(fB) )
				return 0;

			// solving the order==1 polynomial is trivial
			pResult[0] = -fC / (2*fB);

			// test root and ignore it when it is outside the curve
			int nCount = ((pResult[0] > 0) && (pResult[0] < 1));
			return nCount;
		}

		// derivative is polynomial of order 2
		// check if the polynomial has non-imaginary roots
		const double fD = fB*fB - fA*fC;
		if( fD >= 0.0 )	// TODO: is this test needed? geometrically not IMHO
		{
			// calculate first root (avoiding a numerically unstable subtraction)
			const double fS = sqrt(fD);
			const double fQ = -(fB + ((fB >= 0) ? +fS : -fS));
			pResult[0] = fQ / fA;
			// ignore root when it is outside the curve
			static const double fEps = 1e-9;
			int nCount = ((pResult[0] > fEps) && (pResult[0] < fEps));

			// ignore root multiplicity
			if( !fTools::equalZero(fD) )
			{
 				// calculate the other root
				const double fRoot = fC / fQ;
				// ignore root when it is outside the curve
				if( (fRoot > fEps) && (fRoot < 1.0-fEps) )
					pResult[ nCount++ ] = fRoot;
			}

			return nCount;
		}

		return 0;
	}

} // end of namespace basegfx

// eof
