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