1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef _BGFX_CURVE_B2DCUBICBEZIER_HXX 29 #define _BGFX_CURVE_B2DCUBICBEZIER_HXX 30 31 #include <basegfx/point/b2dpoint.hxx> 32 #include <basegfx/range/b2drange.hxx> 33 34 ////////////////////////////////////////////////////////////////////////////// 35 // predeclarations 36 37 namespace basegfx 38 { 39 class B2DPolygon; 40 } // end of namespace basegfx 41 42 ////////////////////////////////////////////////////////////////////////////// 43 44 namespace basegfx 45 { 46 class B2DCubicBezier 47 { 48 B2DPoint maStartPoint; 49 B2DPoint maEndPoint; 50 B2DPoint maControlPointA; 51 B2DPoint maControlPointB; 52 53 public: 54 B2DCubicBezier(); 55 B2DCubicBezier(const B2DCubicBezier& rBezier); 56 B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rEnd); 57 B2DCubicBezier(const B2DPoint& rStart, const B2DPoint& rControlPointA, const B2DPoint& rControlPointB, const B2DPoint& rEnd); 58 ~B2DCubicBezier(); 59 60 // assignment operator 61 B2DCubicBezier& operator=(const B2DCubicBezier& rBezier); 62 63 // compare operators 64 bool operator==(const B2DCubicBezier& rBezier) const; 65 bool operator!=(const B2DCubicBezier& rBezier) const; 66 bool equal(const B2DCubicBezier& rBezier) const; 67 68 // test if vectors are used 69 bool isBezier() const; 70 71 // test if contained bezier is trivial and reset vectors accordingly 72 void testAndSolveTrivialBezier(); 73 74 /** get length of edge 75 76 This method handles beziers and simple edges. For 77 beziers, the deviation describes the maximum allowed 78 deviation from the real edge length. The default 79 allows a deviation of 1% from the correct length. 80 81 For beziers, there is no direct way to get the length, 82 thus this method may subdivide the bezier edge and may 83 not be cheap. 84 85 @param fDeviation 86 The maximal allowed deviation between correct length 87 and bezier edge length 88 89 @return 90 The length of the edge 91 */ 92 double getLength(double fDeviation = 0.01) const; 93 94 // get distance between start and end point 95 double getEdgeLength() const; 96 97 // get length of control polygon 98 double getControlPolygonLength() const; 99 100 // data interface 101 B2DPoint getStartPoint() const { return maStartPoint; } 102 void setStartPoint(const B2DPoint& rValue) { maStartPoint = rValue; } 103 104 B2DPoint getEndPoint() const { return maEndPoint; } 105 void setEndPoint(const B2DPoint& rValue) { maEndPoint = rValue; } 106 107 B2DPoint getControlPointA() const { return maControlPointA; } 108 void setControlPointA(const B2DPoint& rValue) { maControlPointA = rValue; } 109 110 B2DPoint getControlPointB() const { return maControlPointB; } 111 void setControlPointB(const B2DPoint& rValue) { maControlPointB = rValue; } 112 113 /** get the tangent in point t 114 115 This method handles all the exceptions, e.g. when control point 116 A is equal to start point and/or control point B is equal to end 117 point 118 119 @param t 120 The bezier index in the range [0.0 .. 1.0]. It will be truncated. 121 122 @return 123 The tangent vector in point t 124 */ 125 B2DVector getTangent(double t) const; 126 127 /** adaptive subdivide by angle criteria 128 no start point is added, but all necessary created edges 129 and the end point 130 #i37443# allow the criteria to get unsharp in recursions 131 */ 132 void adaptiveSubdivideByAngle(B2DPolygon& rTarget, double fAngleBound, bool bAllowUnsharpen) const; 133 134 /** #i37443# adaptive subdivide by nCount subdivisions 135 no start point is added, but all necessary created edges 136 and the end point 137 */ 138 void adaptiveSubdivideByCount(B2DPolygon& rTarget, sal_uInt32 nCount) const; 139 140 /** Subdivide cubic bezier segment. 141 142 This function adaptively subdivides the bezier 143 segment into as much straight line segments as necessary, 144 such that the maximal orthogonal distance from any of the 145 segments to the true curve is less than the given error 146 value. 147 No start point is added, but all necessary created edges 148 and the end point 149 150 @param rPoly 151 Output polygon. The subdivided bezier segment is added to 152 this polygon via B2DPolygon::append(). 153 154 @param rCurve 155 The cubic bezier curve to subdivide 156 157 @param fDistanceBound 158 Bound on the maximal distance of the approximation to the 159 true curve. 160 */ 161 void adaptiveSubdivideByDistance(B2DPolygon& rTarget, double fDistanceBound) const; 162 163 // get point at given relative position 164 B2DPoint interpolatePoint(double t) const; 165 166 // calculate the smallest distance from given point to this cubic bezier segment 167 // and return the value. The relative position on the segment is returned in rCut. 168 double getSmallestDistancePointToBezierSegment(const B2DPoint& rTestPoint, double& rCut) const; 169 170 // do a split at position t and fill both resulting segments 171 void split(double t, B2DCubicBezier* pBezierA, B2DCubicBezier* pBezierB) const; 172 173 // extract snippet from fStart to fEnd from this bezier 174 B2DCubicBezier snippet(double fStart, double fEnd) const; 175 176 // get range including conrol points 177 B2DRange getRange() const; 178 179 /** Get the minimum extremum position t 180 181 @param rfResult 182 Will be changed and set to a eventually found split value which should be in the 183 range [0.0 .. 1.0]. It will be the smallest current extremum; there may be more 184 185 @return 186 Returns true if there was at least one extremum found 187 */ 188 bool getMinimumExtremumPosition(double& rfResult) const; 189 190 /** Get all extremum pos of this segment 191 192 This method will calculate all extremum positions of the segment 193 and add them to rResults if they are in the range ]0.0 .. 1.0[ 194 195 @param rResults 196 The vector of doubles where the results will be added. Evtl. 197 existing contents will be removed since an empty vector is a 198 necessary result to express that there are no extreme positions 199 anymore. Since there is an upper maximum of 4 values, it makes 200 sense to use reserve(4) at the vector as preparation. 201 */ 202 void getAllExtremumPositions(::std::vector< double >& rResults) const; 203 204 /** Get optimum-split position on this segment 205 206 This method calculates the positions of all points of the segment 207 that have the maximimum distance to the corresponding line from 208 startpoint-endpoint. This helps to approximate the bezier curve 209 with a minimum number of line segments 210 211 @param fResults 212 Result positions are in the range ]0.0 .. 1.0[ 213 Cubic beziers have at most two of these positions 214 215 @return 216 Returns the number of split positions found 217 */ 218 int getMaxDistancePositions( double fResults[2]) const; 219 }; 220 } // end of namespace basegfx 221 222 #endif /* _BGFX_CURVE_B2DCUBICBEZIER_HXX */ 223