xref: /trunk/main/basegfx/inc/basegfx/polygon/b2dpolygon.hxx (revision 4847aa32f2d96614c90f6a889c046d3046a3c838)
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_POLYGON_B2DPOLYGON_HXX
25 #define _BGFX_POLYGON_B2DPOLYGON_HXX
26 
27 #include <sal/types.h>
28 #include <o3tl/cow_wrapper.hxx>
29 #include <basegfx/vector/b2enums.hxx>
30 #include <basegfx/range/b2drange.hxx>
31 #include <basegfx/basegfxdllapi.h>
32 
33 //////////////////////////////////////////////////////////////////////////////
34 // predeclarations
35 class ImplB2DPolygon;
36 
37 namespace basegfx
38 {
39     class B2DPolygon;
40     class B2DPoint;
41     class B2DVector;
42     class B2DHomMatrix;
43     class B2DCubicBezier;
44 } // end of namespace basegfx
45 
46 //////////////////////////////////////////////////////////////////////////////
47 
48 namespace basegfx
49 {
50     class BASEGFX_DLLPUBLIC B2DPolygon
51     {
52     public:
53         typedef o3tl::cow_wrapper< ImplB2DPolygon > ImplType;
54 
55     private:
56         // internal data.
57         ImplType                                    mpPolygon;
58 
59     public:
60         /// diverse constructors
61         B2DPolygon();
62         B2DPolygon(const B2DPolygon& rPolygon);
63         B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount);
64         ~B2DPolygon();
65 
66         /// assignment operator
67         B2DPolygon& operator=(const B2DPolygon& rPolygon);
68 
69         /// unshare this polygon with all internally shared instances
70         void makeUnique();
71 
72         /// compare operators
73         bool operator==(const B2DPolygon& rPolygon) const;
74         bool operator!=(const B2DPolygon& rPolygon) const;
75 
76         /// member count
77         sal_uInt32 count() const;
78 
79         /// Coordinate interface
80         basegfx::B2DPoint getB2DPoint(sal_uInt32 nIndex) const;
81         void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
82 
83         /// Coordinate insert/append
84         void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount = 1);
85         void append(const basegfx::B2DPoint& rPoint, sal_uInt32 nCount);
86         void append(const basegfx::B2DPoint& rPoint);
87         void reserve(sal_uInt32 nCount);
88 
89         /// Basic ControlPoint interface
90         basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const;
91         basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const;
92         void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
93         void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue);
94         void setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext);
95 
96         /// ControlPoint resets
97         void resetPrevControlPoint(sal_uInt32 nIndex);
98         void resetNextControlPoint(sal_uInt32 nIndex);
99         void resetControlPoints(sal_uInt32 nIndex);
100         void resetControlPoints();
101 
102         /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point.
103         void appendBezierSegment(const basegfx::B2DPoint& rNextControlPoint, const basegfx::B2DPoint& rPrevControlPoint, const basegfx::B2DPoint& rPoint);
104 
105         /// ControlPoint checks
106         bool areControlPointsUsed() const;
107         bool isPrevControlPointUsed(sal_uInt32 nIndex) const;
108         bool isNextControlPointUsed(sal_uInt32 nIndex) const;
109         B2VectorContinuity getContinuityInPoint(sal_uInt32 nIndex) const;
110 
111         /** check edge for being a bezier segment
112 
113             This test the existence of control vectors, but do not apply
114             testAndSolveTrivialBezier() to the bezier segment, so it is still useful
115             to do so.
116             Since it can use internal data representations, it is faster
117             than using getBezierSegment() and applying isBezier() on it.
118 
119             @param nIndex
120             Index of the addressed edge's start point
121 
122             @return
123             true if edge exists and at least one control vector is used
124         */
125         bool isBezierSegment(sal_uInt32 nIndex) const;
126 
127         /** bezier segment access
128 
129             This method also works when it is no bezier segment at all and will fill
130             the given B2DCubicBezier as needed.
131             In any case, the given B2DCubicBezier will be filled, if necessary with
132             the single start point (if no valid edge exists).
133 
134             @param nIndex
135             Index of the addressed edge's start point
136 
137             @param rTarget
138             The B2DCubicBezier to be filled. It's data WILL be changed.
139         */
140         void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const;
141 
142         /** Default adaptive subdivision access
143 
144             This method will return a default adapive subdivision of the polygon.
145             If the polygon does not contain any bezier curve segments, it will
146             just return itself.
147 
148             The subdivision is created on first request and buffered, so when using
149             this subdivision You have the guarantee for fast accesses for multiple
150             usages. It is intended for tooling usage for tasks which would be hard
151             to accomplish on bezier segments (e.g. isInEpsilonRange).
152 
153             The current default subdivision uses adaptiveSubdivideByCount with 9
154             subdivisions which gives 10 edges and 11 points per segment and is
155             usually pretty usable for processing purposes. There is no parameter
156             passing here ATM but it may be changed on demand. If needed, a TYPE
157             and PARAMETER (both defaulted) may be added to allow for switching
158             between the different kinds of subdivision and passing them one
159             parameter.
160 
161             The lifetime of the buffered subdivision is based on polygon changes.
162             When changing the polygon, it will be flushed. It is buffered at the
163             refcounted implementation class, so it will survive copy by value and
164             combinations in PolyPolygons.
165 
166             @return
167             The default (and buffered) subdivision of this polygon. It may
168             be this polygon itself when it has no bezier segments. It is guaranteed
169             to have no more bezier segments
170         */
171         B2DPolygon getDefaultAdaptiveSubdivision() const;
172 
173         /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon
174 
175             A polygon may have up to three ranges:
176 
177             (a) the range of the polygon points
178             (b) the range of the polygon points and control points
179             (c) the outer range of the subdivided bezier curve
180 
181             Ranges (a) and (c) are produced by tools::getRange(); resp. this
182             getB2DRange(). tools::getRangeWithControlPoints handles case (b).
183 
184             To get range (c) a simple solution would be to subdivide the polygon
185             and use getRange() on it. Since subdivision is expensive and decreases
186             the polygon quality, i added this new method. It will use a
187             methodology suggested by HDU. First, it gets the range (a).
188             Then it iterates over the bezier segments and for each it
189             first tests if the outer range of the bezier segment is already
190             contained in the result range.
191 
192             The subdivision itself uses getAllExtremumPositions() to only
193             calculate extremum points and to expand the result accordingly.
194             Thus it calculates maximal four extremum points on the bezier
195             segment, no split is used at all.
196 
197             @return
198             The outer range of the bezier curve/polygon
199         */
200         B2DRange getB2DRange() const;
201 
202         /** insert other 2D polygons
203 
204             The default (with nIndex2 == 0 && nCount == 0) inserts the whole
205             rPoly at position nIndex
206 
207             @param nIndex
208             Target index for points to be inserted
209 
210             @param rPoly
211             The source for new points
212 
213             @param nIndex2
214             The index to the first source point into rPoly
215 
216             @param nCount
217             How many points to add from rPoly to this polygon. Null
218             means to copy all (starting from nIndex2)
219         */
220         void insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2 = 0, sal_uInt32 nCount = 0);
221 
222         /** append other 2D polygons
223 
224             The default (nIndex ==0 && nCount == 0) will append
225             the whole rPoly
226 
227             @param rPoly
228             The source polygon
229 
230             @param nIndex
231             The index to the first point of rPoly to append
232 
233             @param nCount
234             The number of points to append from rPoly, starting
235             from nIndex. If zero, as much as possible is appended
236         */
237         void append(const B2DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0);
238 
239         /// remove points
240         void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1);
241 
242         /// clear all points
243         void clear();
244 
245         /// closed state interface
246         bool isClosed() const;
247         void setClosed(bool bNew);
248 
249         /// flip polygon direction
250         void flip();
251 
252         /// test if Polygon has double points
253         bool hasDoublePoints() const;
254 
255         /// remove double points, at the begin/end and follow-ups, too
256         void removeDoublePoints();
257 
258         /// apply transformation given in matrix form
259         void transform(const basegfx::B2DHomMatrix& rMatrix);
260 
261         // point iterators (same iterator validity conditions as for vector)
262         const B2DPoint* begin() const;
263         const B2DPoint* end() const;
264         B2DPoint* begin();
265         B2DPoint* end();
266     };
267 
268     // typedef for a vector of B2DPolygons
269     typedef ::std::vector< B2DPolygon > B2DPolygonVector;
270 
271 } // end of namespace basegfx
272 
273 //////////////////////////////////////////////////////////////////////////////
274 
275 #endif /* _BGFX_POLYGON_B2DPOLYGON_HXX */
276 
277 /* vim: set noet sw=4 ts=4: */
278