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 #ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
23 #define _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
24 
25 #include <basegfx/point/b2dpoint.hxx>
26 #include <basegfx/vector/b2dvector.hxx>
27 #include <basegfx/polygon/b2dpolygon.hxx>
28 #include <basegfx/polygon/b3dpolypolygon.hxx>
29 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
30 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
31 #include <vector>
32 #include <set>
33 #include <basegfx/basegfxdllapi.h>
34 
35 namespace rtl
36 {
37     class OUString;
38 }
39 
40 //////////////////////////////////////////////////////////////////////////////
41 
42 namespace basegfx
43 {
44 	// predefinitions
45 	class B2DPolyPolygon;
46 	class B2DRange;
47 
48 	namespace tools
49 	{
50 		// B2DPolyPolygon tools
51 
52 		// Check and evtl. correct orientations of all contained Polygons so that
53 		// the orientations of contained polygons will variate to express areas and
54 		// holes
55 		BASEGFX_DLLPUBLIC B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate);
56 
57 		// make sure polygon with index 0L is not a hole. This may evtl. change the
58 		// sequence of polygons, but allows to use polygon with index 0L to
59 		// get the correct normal for the whole polyPolygon
60 		BASEGFX_DLLPUBLIC B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate);
61 
62 		// Subdivide all contained curves. Use distanceBound value if given.
63 		BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound = 0.0);
64 
65 		// Subdivide all contained curves. Use distanceBound value if given. Else, a convenient one
66 		// is created.
67 		BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound = 0.0);
68 
69 		// Subdivide all contained curves. Use nCount divisions if given. Else, a convenient one
70 		// is created.
71 		BASEGFX_DLLPUBLIC B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount = 0L);
72 
73         // isInside test for B2dPoint. On border is not inside as long as not true is given
74 		// in bWithBorder flag. It is assumed that the orientations of the given polygon are correct.
75 		BASEGFX_DLLPUBLIC bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false);
76 
77 		/** get range of PolyPolygon. Control points are included.
78 
79 			For detailed description look at getRangeWithControlPoints(const B2DPolygon&).
80 			This method just expands by the range of every sub-Polygon.
81 
82 			@param rCandidate
83 			The B2DPolyPolygon eventually containing bezier segments
84 
85 			@return
86 			The outer range including control points
87 		*/
88 		BASEGFX_DLLPUBLIC B2DRange getRangeWithControlPoints(const B2DPolyPolygon& rCandidate);
89 
90 		/** Get the range of a polyPolygon
91 
92 			For detailed description look at getRange(const B2DPolygon&).
93 			This method just expands by the range of every sub-Polygon.
94 
95 			@param rCandidate
96 			The B2DPolyPolygon eventually containing bezier segments
97 
98 			@return
99 			The outer range of the polygon
100 		*/
101 		BASEGFX_DLLPUBLIC B2DRange getRange(const B2DPolyPolygon& rCandidate);
102 
103 		// get signed area of polygon
104 		BASEGFX_DLLPUBLIC double getSignedArea(const B2DPolyPolygon& rCandidate);
105 
106 		// get area of polygon
107 		BASEGFX_DLLPUBLIC double getArea(const B2DPolyPolygon& rCandidate);
108 
109         /** Apply given LineDashing to given polyPolygon
110 
111 			For a description see applyLineDashing in b2dpolygontoos.hxx
112 		*/
113 		BASEGFX_DLLPUBLIC void applyLineDashing(
114 			const B2DPolyPolygon& rCandidate,
115 			const ::std::vector<double>& rDotDashArray,
116 			B2DPolyPolygon* pLineTarget,
117             B2DPolyPolygon* pGapTarget = 0,
118 			double fFullDashDotLen = 0.0);
119 
120 		// test if point is inside epsilon-range around the given PolyPolygon. Can be used
121 		// for HitTesting. The epsilon-range is defined to be the tube around the PolyPolygon
122 		// with distance fDistance and rounded edges (start and end point).
123 		BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance);
124 
125         /** Helper class to transport PointIndices to a PolyPolygon,
126             with an operator< for convenient sorting in a std::set usage
127          */
128         class BASEGFX_DLLPUBLIC PointIndex
129         {
130         private:
131             sal_uInt32 mnPolygonIndex;
132             sal_uInt32 mnPointIndex;
133 
134         public:
PointIndex(sal_uInt32 nPolygonIndex,sal_uInt32 nPointIndex)135             PointIndex(sal_uInt32 nPolygonIndex, sal_uInt32 nPointIndex)
136             :   mnPolygonIndex(nPolygonIndex),
137                 mnPointIndex(nPointIndex)
138             {}
139 
getPolygonIndex() const140             sal_uInt32 getPolygonIndex() const { return mnPolygonIndex; }
getPointIndex() const141             sal_uInt32 getPointIndex() const { return mnPointIndex; }
142             bool operator<(const PointIndex& rComp) const;
143         };
144 
145         /** the PointIndexSet itself; it allows to define a 'selection'of
146             points in a PolyPolygon by giving the polygon and point index.
147             Adding points double makes no sense, hence the std::set
148          */
149         typedef std::set< PointIndex > PointIndexSet;
150 
151         /** Read poly-polygon from SVG.
152 
153             This function imports a poly-polygon from an SVG-D
154             attribute. Currently, elliptical arc elements are not yet
155             supported (and ignored during parsing).
156 
157             @param o_rPolyPoly
158             The output poly-polygon
159 
160             @param rSvgDAttribute
161             A valid SVG-D attribute string
162 
163             @param bHandleRelativeNextPointCompatible
164             If set to true, the old error that after a relative 'z' command
165             the current point was not reset to the first point of the current
166             polygon is kept; this is needed to read odf files.
167             If false, pure svg is used; this is needed for svg import.
168 
169             @param pHelpPointIndexSet
170             If given, all points created in the target PolyPolygon
171             which are only helper points are added here using their
172             point indices; this are currently points created from
173             import of the 'a' and 'A' svg:d statements which create
174             bezier curve info as representation and maybe points
175             which are no 'real' svg:d points, but helper points. It
176             is necessary to identify these e.g. when markers need to
177             be created in the svg import
178 
179             @return true, if the string was successfully parsed
180          */
181 
182         BASEGFX_DLLPUBLIC bool importFromSvgD(
183             B2DPolyPolygon& o_rPolyPoly,
184             const ::rtl::OUString& rSvgDAttribute,
185             bool bHandleRelativeNextPointCompatible,
186             PointIndexSet* pHelpPointIndexSet);
187 
188 		// grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point
189 		// with the given amount. Value may be negative.
190 		BASEGFX_DLLPUBLIC B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue);
191 
192 		// This method will correct a pair of polyPolygons where the goal is to keep same point count
193 		// to allow direct point association and also to remove self-intersections produced by shrinks.
194 		// This method will eventually change both polyPolygons to reach that goal because there are cases
195 		// where it is necessary to add new cut points to the original
196 		BASEGFX_DLLPUBLIC void correctGrowShrinkPolygonPair(B2DPolyPolygon& rOriginal, B2DPolyPolygon& rGrown);
197 
198 		// force all sub-polygons to a point count of nSegments
199 		BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments);
200 
201 		// create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same
202 		// organisation, e.g. same amount of polygons
203 		BASEGFX_DLLPUBLIC B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t);
204 
205 		// create 3d PolyPolygon from given 2d PolyPolygon. The given fZCoordinate is used to expand the
206 		// third coordinate.
207 		BASEGFX_DLLPUBLIC B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate = 0.0);
208 
209 		// create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given
210 		// matrix and the resulting x,y is used to form the new polygon.
211 		BASEGFX_DLLPUBLIC B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat);
212 
213 		// for each contained edge in each contained polygon calculate the smallest distance. Return the index to the smallest
214 		// edge in rEdgeIndex and the index to the polygon in rPolygonIndex. The relative position on the edge is returned in rCut.
215 		// If nothing was found (e.g. empty input plygon), DBL_MAX is returned.
216 		BASEGFX_DLLPUBLIC double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut);
217 
218 		// distort PolyPolygon. rOriginal describes the original range, where the given points describe the distorted
219 		// corresponding points.
220 		BASEGFX_DLLPUBLIC B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight);
221 
222 		// rotate PolyPolygon around given point with given angle.
223 		BASEGFX_DLLPUBLIC B2DPolyPolygon rotateAroundPoint(const B2DPolyPolygon& rCandidate, const B2DPoint& rCenter, double fAngle);
224 
225 		// expand all segments (which are not yet) to curve segments. This is done with setting the control
226 		// vectors on the 1/3 resp. 2/3 distances on each segment.
227 		BASEGFX_DLLPUBLIC B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate);
228 
229 		// set continuity for the whole curve. If not a curve, nothing will change. Non-curve points are not changed, too.
230 		BASEGFX_DLLPUBLIC B2DPolyPolygon setContinuity(const B2DPolyPolygon& rCandidate, B2VectorContinuity eContinuity);
231 
232         /** Predicate whether a given poly-polygon is a rectangle.
233 
234         	@param rPoly
235             PolyPolygon to check
236 
237             @return true, if the poly-polygon describes a rectangle
238             (contains exactly one polygon, polygon is closed, and the
239             points are either cw or ccw enumerations of a rectangle's
240             vertices). Note that intermediate points and duplicate
241             points are ignored.
242          */
243         BASEGFX_DLLPUBLIC bool isRectangle( const B2DPolyPolygon& rPoly );
244 
245         /** Export poly-polygon to SVG.
246 
247         	This function exports a poly-polygon into an SVG-D
248         	statement. Currently, output of relative point sequences
249         	is not yet supported (might cause slightly larger output)
250 
251             @param rPolyPoly
252             The poly-polygon to export
253 
254             @param bUseRelativeCoordinates
255             When true, all coordinate values are exported as relative
256             to the current position. This tends to save some space,
257             since fewer digits needs to be written.
258 
259             @param bDetectQuadraticBeziers
260             When true, the export tries to detect cubic bezier
261             segments in the input polygon, which can be represented by
262             quadratic bezier segments. Note that the generated string
263             causes versions prior to OOo2.0 to crash.
264 
265             @param bHandleRelativeNextPointCompatible
266             If set to true, the old error that after a relative 'z' command
267             the current point was not reset to the first point of the current
268             polygon is kept; this is needed to read odf files.
269             If false, pure svg is used; this is needed for svg import.
270 
271             @return the generated SVG-D statement (the XML d attribute
272             value alone, without any "<path ...>" or "d="...")
273          */
274         BASEGFX_DLLPUBLIC ::rtl::OUString exportToSvgD(
275             const B2DPolyPolygon& rPolyPoly,
276             bool bUseRelativeCoordinates,
277             bool bDetectQuadraticBeziers,
278             bool bHandleRelativeNextPointCompatible);
279 
280 		// #i76891# Try to remove existing curve segments if they are simply edges
281 		BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate);
282 
283         /** split each edge of a polyPolygon in exactly nSubEdges equidistant edges
284 
285             @param rCandidate
286             The source polyPolygon. If too small (no edges), nSubEdges too small (<2)
287             or neither bHandleCurvedEdgesnor bHandleStraightEdges it will just be returned.
288             Else for each edge nSubEdges will be created. Closed state is preserved.
289 
290             @param nSubEdges
291             @param bHandleCurvedEdges
292             @param bHandleStraightEdges
293             Please take a look at reSegmentPolygonEdges description, these are the same.
294         */
295 		BASEGFX_DLLPUBLIC B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges);
296 
297 		//////////////////////////////////////////////////////////////////////
298 		// comparators with tolerance for 2D PolyPolygons
299 		BASEGFX_DLLPUBLIC bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue);
300 		BASEGFX_DLLPUBLIC bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB);
301 
302 		/** snap some polygon coordinates to discrete coordinates
303 
304 			This method allows to snap some polygon points to discrete (integer) values
305 			which equals e.g. a snap to discrete coordinates. It will snap points of
306 			horizontal and vertical edges
307 
308 			@param rCandidate
309 			The source polygon
310 
311 			@return
312 			The modified version of the source polygon
313 		*/
314 		BASEGFX_DLLPUBLIC B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate);
315 
316         /** returns true if the Polygon only contains horizontal or vertical edges
317             so that it could be represented by RegionBands
318         */
319         BASEGFX_DLLPUBLIC bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate);
320 
321         /// converters for com::sun::star::drawing::PointSequence
322         BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
323             const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
324             bool bCheckClosed = true);
325         BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPointSequenceSequence(
326             const B2DPolyPolygon& rPolyPolygon,
327             com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval);
328 
329         /// converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
330         BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
331             const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
332             bool bCheckClosed = true);
333         BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
334             const B2DPolyPolygon& rPolyPolygon,
335             com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval);
336 
337     } // end of namespace tools
338 } // end of namespace basegfx
339 
340 #endif /* _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX */
341