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