diff options
Diffstat (limited to 'basegfx/inc/basegfx/polygon')
17 files changed, 2756 insertions, 0 deletions
diff --git a/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx b/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx new file mode 100644 index 000000000000..d95f0687dbf8 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx @@ -0,0 +1,147 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dlinegeometry.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DLINEGEOMETRY_HXX +#define _BGFX_POLYGON_B2DLINEGEOMETRY_HXX + +#include <sal/types.h> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + /** Create line start/end geometry element, mostly arrows and things like that. + + @param rCandidate + The polygon which needs to get that line ends and needs to have two points + at least. + + @param rArrow + The line start/end geometry. It is assumed that the tip is pointing + upwards. Result will be rotated and scaled to fit. + + @param bStart + describes if creation is for start or end of candidate. + + @param fWidth + defines the size of the element, it's describing the target width in X + of the arrow. + + @param fDockingPosition needs to be in [0.0 ..1.0] range, where 0.0 means + that the tip of the arrow will be aligned with the polygon start, 1.0 means + the bottom. The default of 0.5 describes a centered arrow. + + @param pConsumedLength + Using this parameter it is possible to get back how much from the candidate + geometry is overlapped by the created element (consumed). + + @param fCandidateLength + This should contain the length of rCandidate to allow work without + again calculating the length (which may be expensive with beziers). If 0.0 is + given, the length is calculated on demand. + + @return + The Line start and end polygon, correctly rotated and scaled + */ + B2DPolyPolygon createAreaGeometryForLineStartEnd( + const B2DPolygon& rCandidate, + const B2DPolyPolygon& rArrow, + bool bStart, + double fWidth, + double fCandidateLength = 0.0, // 0.0 -> calculate self + double fDockingPosition = 0.5, // 0->top, 1->bottom + double* pConsumedLength = 0L); + + /** create filled polygon geometry for lines with a line width + + This method will create bezier based, fillable polygons which + will resample the curve if it was extended for the given half + line width. It will remove extrema positions from contained + bezier segments and get as close as possible and defined by + the given parameters to the ideal result. + + It will check edges for trivial bezier to avoid unnecessary + bezier polygons. Care is taken to produce the in-between + polygon points (the ones original on the source poygon) since + it has showed that without those, the raster converters leave + non-filled gaps. + + @param rCandidate + The source polygon defining the hairline polygon path + + @param fHalfLineWidth + The width of the line to one side + + @param eJoin + The LineJoin if the edges meeting in a point do not have a C1 + or C2 continuity + + @param fMaxAllowedAngle + Allows to hand over the maximum allowed angle between an edge and + it's control vectors. The smaller, the more subdivisions will be + needed to create the filled geometry. Allowed range is cropped to + [F_PI2 .. 0.01 * F_PI2]. + + @param fMaxPartOfEdge + Allows to influence from with relative length of a control vector + compared to it's edge a split is forced. The smaller, the more + subdivisions will be needed to create the filled geometry. Allowed + range is cropped to [1.0 .. 0.01] + + @praram fMiterMinimumAngle + The minimum wanted angle between two edges when edge rounding + is using miter. When an edge is smaller than this (tighter) + the usual fallback to bevel is used. Allowed range is cropped + to [F_PI .. 0.01 * F_PI]. + + @return + The PolyPolygon containing the geometry of the extended line by + it's line width. Contains bezier segments and edge roundings as + needed and defined. + */ + B2DPolyPolygon createAreaGeometry( + const B2DPolygon& rCandidate, + double fHalfLineWidth, + B2DLineJoin eJoin = B2DLINEJOIN_ROUND, + double fMaxAllowedAngle = (12.5 * F_PI180), + double fMaxPartOfEdge = 0.4, + double fMiterMinimumAngle = (15.0 * F_PI180)); + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_B2DLINEGEOMETRY_HXX */ +// eof diff --git a/basegfx/inc/basegfx/polygon/b2dpolygon.hxx b/basegfx/inc/basegfx/polygon/b2dpolygon.hxx new file mode 100644 index 000000000000..c0de4b57ced8 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolygon.hxx @@ -0,0 +1,270 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolygon.hxx,v $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX +#define _BGFX_POLYGON_B2DPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <basegfx/range/b2drange.hxx> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations +class ImplB2DPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DPoint; + class B2DVector; + class B2DHomMatrix; + class B2DCubicBezier; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B2DPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB2DPolygon > ImplType; + + private: + // internal data. + ImplType mpPolygon; + + public: + /// diverse constructors + B2DPolygon(); + B2DPolygon(const B2DPolygon& rPolygon); + B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount); + ~B2DPolygon(); + + /// assignment operator + B2DPolygon& operator=(const B2DPolygon& rPolygon); + + /// unshare this polygon with all internally shared instances + void makeUnique(); + + /// compare operators + bool operator==(const B2DPolygon& rPolygon) const; + bool operator!=(const B2DPolygon& rPolygon) const; + + /// member count + sal_uInt32 count() const; + + /// Coordinate interface + basegfx::B2DPoint getB2DPoint(sal_uInt32 nIndex) const; + void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + + /// Coordinate insert/append + void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount = 1); + void append(const basegfx::B2DPoint& rPoint, sal_uInt32 nCount); + void append(const basegfx::B2DPoint& rPoint); + void reserve(sal_uInt32 nCount); + + /// Basic ControlPoint interface + basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const; + basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const; + void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue); + void setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext); + + /// ControlPoint resets + void resetPrevControlPoint(sal_uInt32 nIndex); + void resetNextControlPoint(sal_uInt32 nIndex); + void resetControlPoints(sal_uInt32 nIndex); + void resetControlPoints(); + + /// Bezier segment append with control points. The current last polygon point is implicitly taken as start point. + void appendBezierSegment(const basegfx::B2DPoint& rNextControlPoint, const basegfx::B2DPoint& rPrevControlPoint, const basegfx::B2DPoint& rPoint); + + /// ControlPoint checks + bool areControlPointsUsed() const; + bool isPrevControlPointUsed(sal_uInt32 nIndex) const; + bool isNextControlPointUsed(sal_uInt32 nIndex) const; + B2VectorContinuity getContinuityInPoint(sal_uInt32 nIndex) const; + + /** check edge for being a bezier segment + + This test the existance of control vectors, but do not apply + testAndSolveTrivialBezier() to the bezier segment, so it is still useful + to do so. + Since it can use internal data representations, it is faster + than using getBezierSegment() and applying isBezier() on it. + + @param nIndex + Index of the addressed edge's start point + + @return + true if edge exists and at least one control vector is used + */ + bool isBezierSegment(sal_uInt32 nIndex) const; + + /** bezier segment access + + This method also works when it is no bezier segment at all and will fill + the given B2DCubicBezier as needed. + In any case, the given B2DCubicBezier will be filled, if necessary with + the single start point (if no valid edge exists). + + @param nIndex + Index of the addressed edge's start point + + @param rTarget + The B2DCubicBezier to be filled. It's data WILL be changed. + */ + void getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const; + + /** Default adaptive subdivision access + + This method will return a default adapive subdivision of the polygon. + If the polygon does not contain any bezier curve segments, it will + just return itself. + + The subdivision is created on first request and buffered, so when using + this subdivision You have the guarantee for fast accesses for multiple + usages. It is intended for tooling usage for tasks which would be hard + to accomplish on bezier segments (e.g. isInEpsilonRange). + + The current default subdivision uses adaptiveSubdivideByCount with 9 + subdivisions which gives 10 edges and 11 points per segment and is + usually pretty usable for processing purposes. There is no parameter + passing here ATM but it may be changed on demand. If needed, a TYPE + and PARAMETER (both defaulted) may be added to allow for switching + between the different kinds of subdivisiond and passing them one + parameter. + + The lifetime of the buffered subdivision is based on polygon changes. + When changing the polygon, it will be flushed. It is buffered at the + refcounted implementation class, so it will survive copy by value and + combinations in PolyPolygons. + + @return + The default (and buffered) subdivision of this polygon. It may + be this polygon itself when it has no bezier segments. It is guaranteed + to have no more bezier segments + */ + B2DPolygon getDefaultAdaptiveSubdivision() const; + + /** Get the B2DRange (Rectangle dimensions) of this B2DPolygon + + A polygon may have up to three ranges: + + (a) the range of the polygon points + (b) the range of the polygon points and control points + (c) the outer range of the subdivided bezier curve + + Ranges (a) and (c) are produced by tools::getRange(); resp. this + getB2DRange(). tools::getRangeWithControlPoints handles case (b). + + To get range (c) a simple solution would be to subdivide the polygon + and use getRange() on it. Since subdivision is expensive and decreases + the polygon quality, i added this new method. It will use a + methodology suggested by HDU. First, it gets the range (a). + Then it iterates over the bezier segments and for each it + first tests if the outer range of the bezier segment is already + contained in the result range. + + The subdivision itself uses getAllExtremumPositions() to only + calculate extremum points and to expand the result accordingly. + Thus it calculates maximal four extremum points on the bezier + segment, no split is used at all. + + @return + The outer range of the bezier curve/polygon + */ + B2DRange getB2DRange() const; + + /** insert other 2D polygons + + The default (with nIndex2 == 0 && nCount == 0) inserts the whole + rPoly at position nIndex + + @param nIndex + Target index for points to be inserted + + @param rPoly + The source for new points + + @param nIndex2 + The index to the first source point into rPoly + + @param nCount + How many points to add from rPoly to this polygon. Null + means to copy all (starting from nIndex2) + */ + void insert(sal_uInt32 nIndex, const B2DPolygon& rPoly, sal_uInt32 nIndex2 = 0, sal_uInt32 nCount = 0); + + /** append other 2D polygons + + The default (nIndex ==0 && nCount == 0) will append + the whole rPoly + + @param rPoly + The source polygon + + @param nIndex + The index to the first point of rPoly to append + + @param nCount + The number of points to append from rPoly, starting + from nIndex. If zero, as much as possibel is appended + */ + void append(const B2DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0); + + /// remove points + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + /// clear all points + void clear(); + + /// closed state interface + bool isClosed() const; + void setClosed(bool bNew); + + /// flip polygon direction + void flip(); + + /// test if Polygon has double points + bool hasDoublePoints() const; + + /// remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + /// apply transformation given in matrix form + void transform(const basegfx::B2DHomMatrix& rMatrix); + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_B2DPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolygonclipper.hxx b/basegfx/inc/basegfx/polygon/b2dpolygonclipper.hxx new file mode 100644 index 000000000000..d604c454a81f --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolygonclipper.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolygonclipper.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX +#define _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DRange; + + namespace tools + { + // This method clips the given PolyPolygon against a horizontal or vertical axis (parallell to X or Y axis). The axis is + // defined by bParallelToXAxis (true -> it's parallel to the X-Axis of the coordinate system, else to the Y-Axis) and the + // fValueOnOtherAxis (gives the translation to the coordinate system axis). For example, when You want to define + // a clip axis parallel to X.Axis and 100 above it, use bParallelToXAxis = true and fValueOnOtherAxis = 100. + // The value bAboveAxis defines on which side the return value will be (true -> above X, right of Y). + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B2DPolyPolygon clipPolyPolygonOnParallelAxis(const B2DPolyPolygon& rCandidate, bool bParallelToXAxis, bool bAboveAxis, double fValueOnOtherAxis, bool bStroke); + B2DPolyPolygon clipPolygonOnParallelAxis(const B2DPolygon& rCandidate, bool bParallelToXAxis, bool bAboveAxis, double fValueOnOtherAxis, bool bStroke); + + // Clip the given PolyPolygon against the given range. bInside defines if the result will contain the + // parts which are contained in the range or vice versa. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B2DPolyPolygon clipPolyPolygonOnRange(const B2DPolyPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + B2DPolyPolygon clipPolygonOnRange(const B2DPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + + // Clip given PolyPolygon against the endless edge (ray) defined by the given two points. bAbove defines on which side + // of the edge the result will be together with the definition of the edge. If the edge is seen as a vector + // from A to B and bAbove is true, the result will contain the geometry left of the vector. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B2DPolyPolygon clipPolyPolygonOnEdge(const B2DPolyPolygon& rCandidate, const B2DPoint& rPointA, const B2DPoint& rPointB, bool bAbove, bool bStroke); + B2DPolyPolygon clipPolygonOnEdge(const B2DPolygon& rCandidate, const B2DPoint& rPointA, const B2DPoint& rPointB, bool bAbove, bool bStroke); + + // Clip given PolyPolygon against given clipping polygon. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + // With stroke polygons, You get all line snippets inside rCip. + // With filled polygons, You get all PolyPolygon parts which were inside rClip. + // The switch bInside decides if the parts inside the clip polygon or outside shall be created. + // The clip polygon is always assumed closed, even when it's isClosed() is false. + B2DPolyPolygon clipPolyPolygonOnPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPolyPolygon& rClip, bool bInside, bool bStroke); + B2DPolyPolygon clipPolygonOnPolyPolygon(const B2DPolygon& rCandidate, const B2DPolyPolygon& rClip, bool bInside, bool bStroke); + + // clip the given polygon against the given range. the resulting polygon will always contain + // the inside parts which will always be interpreted as areas. the incoming polygon is expected + // to be a simple triangle list. the result is also a simple triangle list. + B2DPolygon clipTriangleListOnRange( const B2DPolygon& rCandidate, const B2DRange& rRange ); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B2DPOLYGONCLIPPER_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolygoncutandtouch.hxx b/basegfx/inc/basegfx/polygon/b2dpolygoncutandtouch.hxx new file mode 100644 index 000000000000..aa4682a665cd --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolygoncutandtouch.hxx @@ -0,0 +1,76 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolygoncutandtouch.hxx,v $ + * $Revision: 1.6 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_CUTANDTOUCH_HXX +#define _BGFX_POLYGON_CUTANDTOUCH_HXX + +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + // look for self-intersections and self-touches (points on an edge) in given polygon and add + // extra points there. Result will have no touches or intersections on an edge, only on points + B2DPolygon addPointsAtCutsAndTouches(const B2DPolygon& rCandidate); + + // look for polypolygon-intersections and polypolygon-touches (point of poly A on an edge of poly B) in given PolyPolygon and add + // extra points there. Result will have no touches or intersections between contained polygons on an edge, only on points. For + // convenience, the correction for self-intersections for each member polygon will be used, too. + // Changed: Self intersections are searched by default, but may be switched off by 2nd parameter. + B2DPolyPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rCandidate, bool bSelfIntersections = true); + + // look for intersections of rCandidate with all polygons from rMask and add extra points there. Do + // not change or add points to rMask. + B2DPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rMask, const B2DPolygon& rCandidate); + + // look for intersections of rCandidate with all polygons from rMask and add extra points there. Do + // not change or add points to rMask. + B2DPolyPolygon addPointsAtCutsAndTouches(const B2DPolyPolygon& rMask, const B2DPolyPolygon& rCandidate); + + // look for intersections of rCandidate with the edge from rStart to rEnd and add extra points there. + // Points are only added in the range of the edge, not on the endless vector. + B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPoint& rStart, const B2DPoint& rEnd); + B2DPolyPolygon addPointsAtCuts(const B2DPolyPolygon& rCandidate, const B2DPoint& rStart, const B2DPoint& rEnd); + + // look for intersections of rCandidate with the mask Polygon and add extra points there. + // The mask polygon is assumed to be closed, even when it's not explicitely. + B2DPolygon addPointsAtCuts(const B2DPolygon& rCandidate, const B2DPolyPolygon& rMask); + B2DPolyPolygon addPointsAtCuts(const B2DPolyPolygon& rCandidate, const B2DPolyPolygon& rMask); + + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#endif /* _BGFX_POLYGON_CUTANDTOUCH_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx new file mode 100644 index 000000000000..5eff6b0b9cc1 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx @@ -0,0 +1,594 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolygontools.hxx,v $ + * $Revision: 1.24.4.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#define _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DPolygon; + class B2DRange; + + namespace tools + { + // B2DPolygon tools + + // open/close with point add/remove and control point corrections + void openWithGeometryChange(B2DPolygon& rCandidate); + void closeWithGeometryChange(B2DPolygon& rCandidate); + + /** Check if given polygon is closed. + + This is kind of a 'classic' method to support old polygon + definitions. Those old polygon definitions define the + closed state of the polygon using identical start and + endpoints. This method corrects this (removes double + start/end points) and sets the Closed()-state of the + polygon correctly. + */ + void checkClosed(B2DPolygon& rCandidate); + + // Get successor and predecessor indices. Returning the same index means there + // is none. Same for successor. + sal_uInt32 getIndexOfPredecessor(sal_uInt32 nIndex, const B2DPolygon& rCandidate); + sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B2DPolygon& rCandidate); + + // Get orientation of Polygon + B2VectorOrientation getOrientation(const B2DPolygon& rCandidate); + + // isInside tests for B2dPoint and other B2dPolygon. On border is not inside as long as + // not true is given in bWithBorder flag. + bool isInside(const B2DPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false); + bool isInside(const B2DPolygon& rCandidate, const B2DPolygon& rPolygon, bool bWithBorder = false); + + /** Get the range of a polygon including bezier control points + + For detailed discussion, see B2DPolygon::getB2DRange() + + @param rCandidate + The B2DPolygon eventually containing bezier segments + + @return + The outer range of the bezier curve containing bezier control points + */ + B2DRange getRangeWithControlPoints(const B2DPolygon& rCandidate); + + /** Get the range of a polygon + + This method creates the outer range of the subdivided bezier curve. + For detailed discussion see B2DPolygon::getB2DRange() + + @param rCandidate + The B2DPolygon eventually containing bezier segments + + @return + The outer range of the bezier curve + */ + B2DRange getRange(const B2DPolygon& rCandidate); + + // get signed area of polygon + double getSignedArea(const B2DPolygon& rCandidate); + + // get area of polygon + double getArea(const B2DPolygon& rCandidate); + + /** get length of polygon edge from point nIndex to nIndex + 1 */ + double getEdgeLength(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + /** get length of polygon */ + double getLength(const B2DPolygon& rCandidate); + + // get position on polygon for absolute given distance. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + B2DPoint getPositionAbsolute(const B2DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + // get position on polygon for relative given distance in range [0.0 .. 1.0]. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + B2DPoint getPositionRelative(const B2DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + // get a snippet from given polygon for absolute distances. The polygon is assumed + // to be opened (not closed). fFrom and fTo need to be in range [0.0 .. fLength], where + // fTo >= fFrom. If length is given, it is assumed the correct polygon length, + // if 0.0 it is calculated using getLength(...) + B2DPolygon getSnippetAbsolute(const B2DPolygon& rCandidate, double fFrom, double fTo, double fLength = 0.0); + + // get a snippet from given polygon for relative distances. The polygon is assumed + // to be opened (not closed). fFrom and fTo need to be in range [0.0 .. 1.0], where + // fTo >= fFrom. If length is given, it is assumed the correct polygon length, + // if 0.0 it is calculated using getLength(...) + B2DPolygon getSnippetRelative(const B2DPolygon& rCandidate, double fFrom = 0.0, double fTo = 1.0, double fLength = 0.0); + + // Continuity check for point with given index + B2VectorContinuity getContinuityInPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // Subdivide all contained curves. Use distanceBound value if given. + B2DPolygon adaptiveSubdivideByDistance(const B2DPolygon& rCandidate, double fDistanceBound = 0.0); + + // Subdivide all contained curves. Use angleBound value if given. + B2DPolygon adaptiveSubdivideByAngle(const B2DPolygon& rCandidate, double fAngleBound = 0.0); + + // #i37443# Subdivide all contained curves. + B2DPolygon adaptiveSubdivideByCount(const B2DPolygon& rCandidate, sal_uInt32 nCount = 0L); + + // Definitions for the cut flags used from the findCut methods + typedef sal_uInt16 CutFlagValue; + + #define CUTFLAG_NONE (0x0000) + #define CUTFLAG_LINE (0x0001) + #define CUTFLAG_START1 (0x0002) + #define CUTFLAG_START2 (0x0004) + #define CUTFLAG_END1 (0x0008) + #define CUTFLAG_END2 (0x0010) + #define CUTFLAG_ALL (CUTFLAG_LINE|CUTFLAG_START1|CUTFLAG_START2|CUTFLAG_END1|CUTFLAG_END2) + #define CUTFLAG_DEFAULT (CUTFLAG_LINE|CUTFLAG_START2|CUTFLAG_END2) + + // Calculate cut between the points given by the two indices. pCut1 + // and pCut2 will contain the cut coordinate on each edge in ]0.0, 1.0] + // (if given) and the return value will contain a cut description. + CutFlagValue findCut( + const B2DPolygon& rCandidate, + sal_uInt32 nIndex1, sal_uInt32 nIndex2, + CutFlagValue aCutFlags = CUTFLAG_DEFAULT, + double* pCut1 = 0L, double* pCut2 = 0L); + + // This version is working with two indexed edges from different + // polygons. + CutFlagValue findCut( + const B2DPolygon& rCandidate1, sal_uInt32 nIndex1, + const B2DPolygon& rCandidate2, sal_uInt32 nIndex2, + CutFlagValue aCutFlags = CUTFLAG_DEFAULT, + double* pCut1 = 0L, double* pCut2 = 0L); + + // This version works with two points and vectors to define the + // edges for the cut test. + CutFlagValue findCut( + const B2DPoint& rEdge1Start, const B2DVector& rEdge1Delta, + const B2DPoint& rEdge2Start, const B2DVector& rEdge2Delta, + CutFlagValue aCutFlags = CUTFLAG_DEFAULT, + double* pCut1 = 0L, double* pCut2 = 0L); + + // test if point is on the given edge in range ]0.0..1.0[ without + // the start/end points. If so, return true and put the parameter + // value in pCut (if provided) + bool isPointOnEdge( + const B2DPoint& rPoint, + const B2DPoint& rEdgeStart, + const B2DVector& rEdgeDelta, + double* pCut = 0L); + + /** Apply given LineDashing to given polygon + + This method is used to cut down line polygons to the needed + pieces when a dashing needs to be applied. + It is now capable of keeping contained bezier segments. + It is also capable of delivering line and non-line portions + depending on what target polygons You provide. This is useful + e.g. for dashed lines with two colors. + If the last and the first snippet in one of the results have + a common start/end ppoint, they will be merged to achieve as + view as needed result line snippets. This is also relevant for + further processing the results. + + @param rCandidate + The polygon based on which the snippets will be created. + + @param rDotDashArray + The line pattern given as array of length values + + @param pLineTarget + The target for line snippets, e.g. the first entry will be + a line segment with length rDotDashArray[0]. The given + polygon will be emptied as preparation. + + @param pGapTarget + The target for gap snippets, e.g. the first entry will be + a line segment with length rDotDashArray[1]. The given + polygon will be emptied as preparation. + + @param fFullDashDotLen + The sumed-up length of the rDotDashArray. If zero, it will + be calculated internally. + */ + void applyLineDashing( + const B2DPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B2DPolyPolygon* pLineTarget, + B2DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + // test if point is inside epsilon-range around an edge defined + // by the two given points. Can be used for HitTesting. The epsilon-range + // is defined to be the rectangle centered to the given edge, using height + // 2 x fDistance, and the circle around both points with radius fDistance. + bool isInEpsilonRange(const B2DPoint& rEdgeStart, const B2DPoint& rEdgeEnd, const B2DPoint& rTestPosition, double fDistance); + + // test if point is inside epsilon-range around the given Polygon. Can be used + // for HitTesting. The epsilon-range is defined to be the rectangle centered + // to the given edge, using height 2 x fDistance, and the circle around both points + // with radius fDistance. + bool isInEpsilonRange(const B2DPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance); + + /** Create a polygon from a rectangle. + + @param rRect + The rectangle which describes the polygon size + + @param fRadius + Radius of the edge rounding, relative to the rectangle size. 0.0 means no + rounding, 1.0 will lead to an ellipse + */ + B2DPolygon createPolygonFromRect( const B2DRectangle& rRect, double fRadius ); + + /** Create a polygon from a rectangle. + + @param rRect + The rectangle which describes the polygon size + + @param fRadiusX + @param fRadiusY + Radius of the edge rounding, relative to the rectangle size. 0.0 means no + rounding, 1.0 will lead to an ellipse + */ + B2DPolygon createPolygonFromRect( const B2DRectangle& rRect, double fRadiusX, double fRadiusY ); + + /** Create a polygon from a rectangle. + */ + B2DPolygon createPolygonFromRect( const B2DRectangle& rRect ); + + /** Create a circle polygon with given radius. + + This method creates a circle approximation consisting of + four cubic bezier segments, which approximate the given + circle with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadius + Radius of the circle + */ + B2DPolygon createPolygonFromCircle( const B2DPoint& rCenter, double fRadius ); + + /** append a unit circle with one point and the control vectors to the given polygon + */ + void appendUnitCircleQuadrant(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, bool bEndPoint); + + /** append a segment of unit circle with one point and the control vectors to the given polygon + */ + void appendUnitCircleQuadrantSegment(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, double fStart, double fEnd, bool bEndPoint); + + /** create a polygon which describes the unit circle and close it + + @param nStartQuadrant + To be able to rebuild the old behaviour where the circles started at bottom, + this parameter is used. Default is 0 which is the first quadrant and the + polygon's start point will be the rightmost one. When using e.g. 1, the + first created quadrant will start at the YMax-position (with Y down on screens, + this is the lowest one). This is needed since when lines are dashed, toe old + geometry started at bottom point, else it would look different. + */ + B2DPolygon createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant = 0); + + /** Create an ellipse polygon with given radii. + + This method creates an ellipse approximation consisting of + four cubic bezier segments, which approximate the given + ellipse with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadiusX + Radius of the ellipse in X direction + + @param fRadiusY + Radius of the ellipse in Y direction + */ + B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY ); + + /** append a unit circle with one point and the control vectors to the given polygon + */ + void appendUnitCircleQuadrant(B2DPolygon& rPolygon, sal_uInt32 nQuadrant); + + /** append a segment of unit circle with start point, the control vectors and end point to the given polygon + */ + void appendUnitCircleQuadrantSegment(B2DPolygon& rPolygon, sal_uInt32 nQuadrant, double fStart, double fEnd); + + /** Create an ellipse polygon with given radii. + + This method creates an ellipse approximation consisting of + four cubic bezier segments, which approximate the given + ellipse with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadiusX + Radius of the ellipse in X direction + + @param fRadiusY + Radius of the ellipse in Y direction + + @param fStart + Start angle where the ellipe segment starts in the range [0.0 .. 2PI[ + + @param fEnd + End angle where the ellipe segment ends in the range [0.0 .. 2PI[ + */ + B2DPolygon createPolygonFromEllipse( const B2DPoint& rCenter, double fRadiusX, double fRadiusY ); + + /** Create an ellipse polygon with given radii and the given angles, from start to end + + This method creates an ellipse approximation consisting of + four cubic bezier segments, which approximate the given + ellipse with an error of less than 0.5 percent. + + @param rCenter + Center point of the circle + + @param fRadiusX + Radius of the ellipse in X direction + + @param fRadiusY + Radius of the ellipse in Y direction + + @param fStart + Start angle where the ellipe segment starts in the range [0.0 .. 2PI[ + + @param fEnd + End angle where the ellipe segment ends in the range [0.0 .. 2PI[ + */ + + /** Create an unit ellipse polygon with the given angles, from start to end + */ + B2DPolygon createPolygonFromEllipseSegment( const B2DPoint& rCenter, double fRadiusX, double fRadiusY, double fStart, double fEnd ); + + B2DPolygon createPolygonFromUnitEllipseSegment( double fStart, double fEnd ); + + /** Predicate whether a given polygon is a rectangle. + + @param rPoly + Polygon to check + + @return true, if the polygon describes a rectangle + (polygon is closed, and the points are either cw or ccw + enumerations of a rectangle's vertices). Note that + intermediate points and duplicate points are ignored. + */ + bool isRectangle( const B2DPolygon& rPoly ); + + // create 3d polygon from given 2d polygon. The given fZCoordinate is used to expand the + // third coordinate. + B3DPolygon createB3DPolygonFromB2DPolygon(const B2DPolygon& rCandidate, double fZCoordinate = 0.0); + + // create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given + // matrix and the resulting x,y is used to form the new polygon. + B2DPolygon createB2DPolygonFromB3DPolygon(const B3DPolygon& rCandidate, const B3DHomMatrix& rMat); + + // create simplified version of the original polygon by + // replacing segments with spikes/loops and self intersections + // by several trivial sub-segments + B2DPolygon createSimplifiedPolygon(const B2DPolygon&); + + // calculate the distance to the given endless ray and return. The relative position on the edge is returned in Cut. + // That position may be less than 0.0 or more than 1.0 + double getDistancePointToEndlessRay(const B2DPoint& rPointA, const B2DPoint& rPointB, const B2DPoint& rTestPoint, double& rCut); + + // calculate the smallest distance to given edge and return. The relative position on the edge is returned in Cut. + // That position is in the range [0.0 .. 1.0] and the returned distance is adapted accordingly to the start or end + // point of the edge + double getSmallestDistancePointToEdge(const B2DPoint& rPointA, const B2DPoint& rPointB, const B2DPoint& rTestPoint, double& rCut); + + // for each contained edge calculate the smallest distance. Return the index to the smallest + // edge in rEdgeIndex. The relative position on the edge is returned in rCut. + // If nothing was found (e.g. empty input plygon), DBL_MAX is returned. + double getSmallestDistancePointToPolygon(const B2DPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rEdgeIndex, double& rCut); + + // distort single point. rOriginal describes the original range, where the given points describe the distorted corresponding points. + B2DPoint distort(const B2DPoint& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // distort polygon. rOriginal describes the original range, where the given points describe the distorted corresponding points. + B2DPolygon distort(const B2DPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // rotate polygon around given point with given angle. + B2DPolygon rotateAroundPoint(const B2DPolygon& rCandidate, const B2DPoint& rCenter, double fAngle); + + // expand all segments (which are not yet) to curve segments. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances on each segment. + B2DPolygon expandToCurve(const B2DPolygon& rCandidate); + + // expand given segment to curve segment. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances. The return value describes if a change took place. + bool expandToCurveInPoint(B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // set continuity for the whole curve. If not a curve, nothing will change. Non-curve points are not changed, too. + B2DPolygon setContinuity(const B2DPolygon& rCandidate, B2VectorContinuity eContinuity); + + // set continuity for given index. If not a curve, nothing will change. Non-curve points are not changed, too. + // The return value describes if a change took place. + bool setContinuityInPoint(B2DPolygon& rCandidate, sal_uInt32 nIndex, B2VectorContinuity eContinuity); + + // test if polygon contains neutral points. A neutral point is one whos orientation is neutral + // e.g. positioned on the edge of it's predecessor and successor + bool hasNeutralPoints(const B2DPolygon& rCandidate); + + // remove neutral points. A neutral point is one whos orientation is neutral + // e.g. positioned on the edge of it's predecessor and successor + B2DPolygon removeNeutralPoints(const B2DPolygon& rCandidate); + + // tests if polygon is convex + bool isConvex(const B2DPolygon& rCandidate); + + // calculates the orientation at edge nIndex + B2VectorOrientation getOrientationForIndex(const B2DPolygon& rCandidate, sal_uInt32 nIndex); + + // calculates if given point is on given line, taking care of the numerical epsilon + bool isPointOnLine(const B2DPoint& rStart, const B2DPoint& rEnd, const B2DPoint& rCandidate, bool bWithPoints = false); + + // calculates if given point is on given polygon, taking care of the numerical epsilon. Uses + // isPointOnLine internally + bool isPointOnPolygon(const B2DPolygon& rCandidate, const B2DPoint& rPoint, bool bWithPoints = true); + + // test if candidate is inside triangle + bool isPointInTriangle(const B2DPoint& rA, const B2DPoint& rB, const B2DPoint& rC, const B2DPoint& rCandidate, bool bWithBorder = false); + + // test if candidateA and candidateB are on the same side of the given line + bool arePointsOnSameSideOfLine(const B2DPoint& rStart, const B2DPoint& rEnd, const B2DPoint& rCandidateA, const B2DPoint& rCandidateB, bool bWithLine = false); + + // add triangles for given rCandidate to rTarget. For each triangle, 3 points will be added to rCandidate. + // All triangles will go from the start point of rCandidate to two consecutive points, building (rCandidate.count() - 2) + // triangles. + void addTriangleFan(const B2DPolygon& rCandidate, B2DPolygon& rTarget); + + // grow for polygon. Move all geometry in each point in the direction of the normal in that point + // with the given amount. Value may be negative. + B2DPolygon growInNormalDirection(const B2DPolygon& rCandidate, double fValue); + + // force all sub-polygons to a point count of nSegments + B2DPolygon reSegmentPolygon(const B2DPolygon& rCandidate, sal_uInt32 nSegments); + + // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same + // organisation, e.g. same amount of points + B2DPolygon interpolate(const B2DPolygon& rOld1, const B2DPolygon& rOld2, double t); + + bool isPolyPolygonEqualRectangle( const B2DPolyPolygon& rPolyPoly, const B2DRange& rRect ); + + // #i76891# Try to remove existing curve segments if they are simply edges + B2DPolygon simplifyCurveSegments(const B2DPolygon& rCandidate); + + // makes the given indexed point the new polygon start point. To do that, the points in the + // polygon will be rotated. This is only valid for closed polygons, for non-closed ones + // an assertion will be triggered + B2DPolygon makeStartPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndexOfNewStatPoint); + + /** create edges of given length along given B2DPolygon + + @param rCandidate + The polygon to move along. Points at the given polygon are created, starting + at position fStart and stopping at less or equal to fEnd. The closed state is + preserved. + The polygon is subdivided if curve segments are included. That subdivision is the base + for the newly created points. + If the source is closed, the indirectly existing last edge may NOT have the + given length. + If the source is open, all edges will have the given length. You may use the last + point of the original when You want to add the last edge Yourself. + + @param fLength + The length of the created edges. If less or equal zero, an empty polygon is returned. + + @param fStart + The start distance for the first to be generated point. Use 0.0 to get the + original start point. Negative values are truncated to 0.0. + + @param fEnd + The maximum distance for the last point. No more points behind this distance will be created. + Use 0.0 to proccess the whole polygon. Negative values are truncated to 0.0. It also + needs to be more or equal to fStart, else it is truncated to fStart. + + @return + The newly created polygon + */ + B2DPolygon createEdgesOfGivenLength(const B2DPolygon& rCandidate, double fLength, double fStart = 0.0, double fEnd = 0.0); + + /** Create Waveline along given polygon + The implementation is based on createEdgesOfGivenLength and creates a curve + segment with the given dimensions for each created line segment. The polygon + is treated as if opened (closed state will be ignored) and only for whole + edges a curve segment will be created (no rest handling) + + @param rCandidate + The polygon along which the waveline will be created + + @param fWaveWidth + The length of a single waveline curve segment + + @param fgWaveHeight + The height of the waveline (amplitude) + */ + B2DPolygon createWaveline(const B2DPolygon& rCandidate, double fWaveWidth, double fWaveHeight); + + /** split each edge of a polygon in exactly nSubEdges equidistant edges + + @param rCandidate + The source polygon. If too small (no edges), nSubEdges too small (<2) + or neither bHandleCurvedEdgesnor bHandleStraightEdges it will just be returned. + Else for each edge nSubEdges will be created. Closed state is preserved. + + @param nSubEdges + How many edges shall be created as replacement for each single edge + + @param bHandleCurvedEdges + Process curved edges or not. If to handle the curved edges will be splitted + into nSubEdges part curved edges of equidistant bezier distances. If not, + curved edges will just be copied. + + @param bHandleStraightEdges + Process straight edges or not. If to handle the straight edges will be splitted + into nSubEdges part curved edges of equidistant length. If not, + straight edges will just be copied. + */ + B2DPolygon reSegmentPolygonEdges(const B2DPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges); + + ////////////////////////////////////////////////////////////////////// + // comparators with tolerance for 2D Polygons + bool equal(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB, const double& rfSmallValue); + bool equal(const B2DPolygon& rCandidateA, const B2DPolygon& rCandidateB); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + B2DPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolygontriangulator.hxx b/basegfx/inc/basegfx/polygon/b2dpolygontriangulator.hxx new file mode 100644 index 000000000000..a2e2a1958e0e --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolygontriangulator.hxx @@ -0,0 +1,52 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolygontriangulator.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX +#define _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace triangulator + { + // triangulate given polygon + ::basegfx::B2DPolygon triangulate(const ::basegfx::B2DPolygon& rCandidate); + + // triangulate given PolyPolygon + ::basegfx::B2DPolygon triangulate(const ::basegfx::B2DPolyPolygon& rCandidate); + + } // end of namespace triangulator +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYGONTRIANGULATOR_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx new file mode 100644 index 000000000000..9c8724b8ee6d --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygon.hxx @@ -0,0 +1,134 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolypolygon.hxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGON_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> +#include <basegfx/range/b2drange.hxx> + +// predeclarations +class ImplB2DPolyPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DHomMatrix; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B2DPolyPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB2DPolyPolygon > ImplType; + + private: + ImplType mpPolyPolygon; + + public: + B2DPolyPolygon(); + B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon); + explicit B2DPolyPolygon(const B2DPolygon& rPolygon); + ~B2DPolyPolygon(); + + // assignment operator + B2DPolyPolygon& operator=(const B2DPolyPolygon& rPolyPolygon); + + /// unshare this poly-polygon (and all included polygons) with all internally shared instances + void makeUnique(); + + // compare operators + bool operator==(const B2DPolyPolygon& rPolyPolygon) const; + bool operator!=(const B2DPolyPolygon& rPolyPolygon) const; + + // polygon interface + sal_uInt32 count() const; + + B2DPolygon getB2DPolygon(sal_uInt32 nIndex) const; + void setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon); + + // test for curve + bool areControlPointsUsed() const; + + // insert/append single polygon + void insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount = 1); + void append(const B2DPolygon& rPolygon, sal_uInt32 nCount = 1); + + /** Default adaptive subdivision access + + For details refer to B2DPolygon::getDefaultAdaptiveSubdivision() + + @return + The default subdivision of this polygon + */ + B2DPolyPolygon getDefaultAdaptiveSubdivision() const; + + /** Get the B2DRange (Rectangle dimensions) of this B2DPolyPolygon + + For details refer to B2DPolygon::getB2DRange() + + @return + The outer range of the bezier curve/polygon + */ + B2DRange getB2DRange() const; + + // insert/append multiple polygons + void insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon); + void append(const B2DPolyPolygon& rPolyPolygon); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // reset to empty state + void clear(); + + // closed state + bool isClosed() const; + void setClosed(bool bNew); + + // flip polygon direction + void flip(); + + // test if PolyPolygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const basegfx::B2DHomMatrix& rMatrix); + }; +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx new file mode 100644 index 000000000000..12532ff078f3 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygoncutter.hxx @@ -0,0 +1,122 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolypolygoncutter.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX + +#include <basegfx/polygon/b2dpolypolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + namespace tools + { + // Solve all crossovers in a polyPolygon. This re-layouts all contained polygons so that the + // result will contain only non-cutting polygons. For that reason, points will be added at + // crossover and touch points and the single Polygons may be re-combined. The orientations + // of the contained polygons in not changed but used as topological information. + // Self crossovers of the contained sub-polygons are implicitely handled, but to not lose + // the topological information, it may be necessary to remove self-intersections of the + // contained sub-polygons in a preparing step and to explicitely correct their orientations. + B2DPolyPolygon solveCrossovers(const B2DPolyPolygon& rCandidate); + + // Version for single polygons. This is for solving self-intersections. Result will be free of + // crossovers. When result contains multiple polygons, it may be necessary to rearrange their + // orientations since holes may have been created (use correctOrientations eventually). + B2DPolyPolygon solveCrossovers(const B2DPolygon& rCandidate); + + // Neutral polygons will be stripped. Neutral polygons are ones who's orientation is + // neutral, so normally they have no volume -> just closed paths. A polygon with the same + // positive and negative oriented volume is also neutral, so this may not be wanted. It is + // safe to call with crossover-free polygons, though (that's where it's mostly used). + B2DPolyPolygon stripNeutralPolygons(const B2DPolyPolygon& rCandidate); + + // Remove not necessary polygons. Works only correct with crossover-free polygons. For each + // polygon, the depth for the PolyPolygon is calculated. The orientation is used to identify holes. + // Start value for holes is -1, for polygons it's zero. Ech time a polygon is contained in another one, + // it's depth is increased when inside a polygon, decreased when inside a hole. The result is a depth + // which e.g. is -1 for holes outside everything, 1 for a polygon covered by another polygon and zero + // for e.g. holes in a polygon or polygons outside everythig else. + // In the 2nd step, all polygons with depth other than zero are removed. If bKeepAboveZero is used, + // all polygons < 1 are removed. The bKeepAboveZero mode is useful for clipping, e.g. just append + // one polygon to another and use this mode -> only parts where two polygons overlapped will be kept. + // In combination with correct orientation of the input orientations and the SolveCrossover calls this + // can be combined for logical polygon operations or polygon clipping. + B2DPolyPolygon stripDispensablePolygons(const B2DPolyPolygon& rCandidate, bool bKeepAboveZero = false); + + // For convenience: The four basic operations OR, XOR, AND and DIFF for + // two PolyPolygons. These are combinations of the above methods. To not be forced + // to do evtl. already done preparations twice, You have to do the operations Yourself. + // + // A source preparation consists of preparing it to be seen as XOR-Rule PolyPolygon, + // so it is freed of intersections, self-intersections and the orientations are corrected. + // Important is that it will define the same areas as before, but is intersection-free. + // As an example think about a single polygon looping in itself and having holes. To + // topologically correctly handle this, it is necessary to remove all intersections and + // to correct the orientations. The orientation of the isolated holes e.g. will be negative. + // Topologically it is necessary to prepare each polygon which is seen as entity. It is + // not sufficient just to concatenate them and prepare the result, this may be topologically + // different since the simple concatenation will be seen as XOR. To work correctly, You + // may need to OR those polygons. + + // Preparations: solve self-intersections and intersections, remove neutral + // parts and correct orientations. + B2DPolyPolygon prepareForPolygonOperation(const B2DPolygon& rCandidate); + B2DPolyPolygon prepareForPolygonOperation(const B2DPolyPolygon& rCandidate); + + // OR: Return all areas where CandidateA or CandidateB exist + B2DPolyPolygon solvePolygonOperationOr(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + // XOR: Return all areas where CandidateA or CandidateB exist, but not both + B2DPolyPolygon solvePolygonOperationXor(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + // AND: Return all areas where CandidateA and CandidateB exist + B2DPolyPolygon solvePolygonOperationAnd(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + // DIFF: Return all areas where CandidateA is not covered by CandidateB (cut B out of A) + B2DPolyPolygon solvePolygonOperationDiff(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /** merge all single PolyPolygons to a single, OR-ed PolyPolygon + + @param rInput + The source PolyPolygons + + @return A single PolyPolygon containing the Or-merged result + */ + B2DPolyPolygon mergeToSinglePolyPolygon(const std::vector< basegfx::B2DPolyPolygon >& rInput); + + } // end of namespace tools +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGONCUTTER_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygonfillrule.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygonfillrule.hxx new file mode 100644 index 000000000000..e90d0bbc1e32 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygonfillrule.hxx @@ -0,0 +1,63 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolypolygonfillrule.hxx,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX + +#include <sal/types.h> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** Fill rule to use for poly-polygon filling. + + The fill rule determines which areas are inside, and which are + outside the poly-polygon. + */ + enum FillRule + { + /** Areas, for which a scanline has crossed an odd number of + vertices, are regarded 'inside', the remainder 'outside' + of the poly-polygon. + */ + FillRule_EVEN_ODD, + + /** For each edge a scanline crosses, a current winding number + is updated. Downward edges count +1, upward edges count + -1. If the total accumulated winding number for one area + is not zero, this area is regarded 'inside', otherwise, + 'outside'. + */ + FillRule_NONZERO_WINDING_NUMBER + }; +} + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGONFILLRULE_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygonrasterconverter.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygonrasterconverter.hxx new file mode 100644 index 000000000000..e26b2063c3e9 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygonrasterconverter.hxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolypolygonrasterconverter.hxx,v $ + * $Revision: 1.5 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B2DPOLYPOLYGONRASTERCONVERTER_HXX +#define _BGFX_POLYGON_B2DPOLYPOLYGONRASTERCONVERTER_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/range/b2drectangle.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygonfillrule.hxx> +#include <vector> +#include <utility> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + /** Raster-convert a poly-polygon. + + This class can raster-convert a given poly-polygon. Simply + derive from this, and override the span() method, which will + get called for every scanline span of the poly-polygon. + + @derive + Overwrite span() with the render output method of your choice. + */ + class B2DPolyPolygonRasterConverter + { + public: + /** Create raster-converter for given poly-polygon + */ + B2DPolyPolygonRasterConverter(const B2DPolyPolygon& rPolyPolyRaster); + + /** Create raster-converter for given poly-polygon and raster + area. + + @param rPolyPolyRaster + Poly-Polygon to raster convert + + @param rMinUpdateArea + Minimal area to touch when raster-converting. The + rectangle given here is guaranteed to be iterated through + scanline by scanline (but the raster converter might + actually use more scanlines, e.g. if the poly-polygon's + bound rect is larger). One of the cases where this + parameter comes in handy is when rendering in the 'off' + spans, and a certain area must be filled. <em>Do not</em> + use this for clipping, as described above, the touched + area might also be larger. + */ + B2DPolyPolygonRasterConverter(const B2DPolyPolygon& rPolyPolyRaster, + const B2DRectangle& rRasterArea ); + + virtual ~B2DPolyPolygonRasterConverter(); + + /** Raster-convert the contained poly-polygon + + @param eFillRule + Fill rule to use for span filling + */ + void rasterConvert( FillRule eFillRule); + + /** Override this method, to be called for every scanline span + of the poly-polygon + + @param rfXLeft + The left end of the current horizontal span + + @param rfXRight + The right end of the current horizontal span + + @param nY + The y position of the current horizontal span + + @param bOn + Denotes whether this span is on or off, according to the + active fill rule. + */ + virtual void span(const double& rfXLeft, + const double& rfXRight, + sal_Int32 nY, + bool bOn ) = 0; + + /// @internal + struct Vertex + { + inline Vertex(); + inline Vertex( const B2DPoint&, const B2DPoint&, bool ); + + B2DPoint aP1; + B2DPoint aP2; + bool bDownwards; + }; + + private: + // default: disabled copy/assignment + B2DPolyPolygonRasterConverter(const B2DPolyPolygonRasterConverter&); + B2DPolyPolygonRasterConverter& operator=( const B2DPolyPolygonRasterConverter& ); + + void init(); + + typedef ::std::vector<Vertex> VectorOfVertices; + typedef ::std::vector<VectorOfVertices> VectorOfVertexVectors; + + /// The poly-polygon to raster-convert + B2DPolyPolygon maPolyPolygon; + /// Total bound rect of the poly-polygon + const B2DRectangle maPolyPolyRectangle; + + /** Vector containing for each scanline a vector which in turn + contains all vertices that start on the specific scanline + */ + VectorOfVertexVectors maScanlines; + }; +} + +#endif /* _BGFX_POLYGON_B2DPOLYPOLYGONRASTERCONVERTER_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx b/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx new file mode 100644 index 000000000000..c4687b3cfc5f --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx @@ -0,0 +1,282 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b2dpolypolygontools.hxx,v $ + * $Revision: 1.20 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX +#define _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> +#include <basegfx/polygon/b3dpolypolygon.hxx> +#include <vector> + +namespace rtl +{ + class OUString; +} + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B2DPolyPolygon; + class B2DRange; + + namespace tools + { + // B2DPolyPolygon tools + + // Check and evtl. correct orientations of all contained Polygons so that + // the orientations of contained polygons will variate to express areas and + // holes + B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate); + + // make sure polygon with index 0L is not a hole. This may evtl. change the + // sequence of polygons, but allows to use polygon with index 0L to + // get the correct normal for the whole polyPolygon + B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate); + + // Subdivide all contained curves. Use distanceBound value if given. + B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound = 0.0); + + // Subdivide all contained curves. Use distanceBound value if given. Else, a convenient one + // is created. + B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound = 0.0); + + // Subdivide all contained curves. Use nCount divisions if given. Else, a convenient one + // is created. + B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount = 0L); + + // isInside test for B2dPoint. On border is not inside as long as not true is given + // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct. + bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder = false); + + /** get range of PolyPolygon. Control points are included. + + For detailed description look at getRangeWithControlPoints(const B2DPolygon&). + This method just expands by the range of every sub-Polygon. + + @param rCandidate + The B2DPolyPolygon eventually containing bezier segments + + @return + The outer range including control points + */ + B2DRange getRangeWithControlPoints(const B2DPolyPolygon& rCandidate); + + /** Get the range of a polyPolygon + + For detailed description look at getRange(const B2DPolygon&). + This method just expands by the range of every sub-Polygon. + + @param rCandidate + The B2DPolyPolygon eventually containing bezier segments + + @return + The outer range of the polygon + */ + B2DRange getRange(const B2DPolyPolygon& rCandidate); + + /** Apply given LineDashing to given polyPolygon + + For a description see applyLineDashing in b2dpolygontoos.hxx + */ + void applyLineDashing( + const B2DPolyPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B2DPolyPolygon* pLineTarget, + B2DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + // test if point is inside epsilon-range around the given PolyPolygon. Can be used + // for HitTesting. The epsilon-range is defined to be the tube around the PolyPolygon + // with distance fDistance and rounded edges (start and end point). + bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance); + + /** Read poly-polygon from SVG. + + This function imports a poly-polygon from an SVG-D + attribute. Currently, elliptical arc elements are not yet + supported (and ignored during parsing). + + @param o_rPolyPoly + The output poly-polygon + + @param rSvgDAttribute + A valid SVG-D attribute string + + @return true, if the string was successfully parsed + */ + bool importFromSvgD( B2DPolyPolygon& o_rPolyPoly, + const ::rtl::OUString& rSvgDAttribute ); + + /** Read poly-polygon from SVG. + + This function imports a poly-polygon from an SVG points + attribute (a plain list of coordinate pairs). + + @param o_rPoly + The output polygon. Note that svg:points can only define a + single polygon + + @param rSvgPointsAttribute + A valid SVG points attribute string + + @return true, if the string was successfully parsed + */ + bool importFromSvgPoints( B2DPolygon& o_rPoly, + const ::rtl::OUString& rSvgPointsAttribute ); + + + // grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point + // with the given amount. Value may be negative. + B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue); + + // This method will correct a pair of polyPolygons where the goal is to keep same point count + // to allow direct point association and also to remove self-intersections produced by shrinks. + // This method will eventually change both polyPolygons to reach that goal because there are cases + // where it is necessary to add new cut points to the original + void correctGrowShrinkPolygonPair(B2DPolyPolygon& rOriginal, B2DPolyPolygon& rGrown); + + // force all sub-polygons to a point count of nSegments + B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments); + + // create polygon state at t from 0.0 to 1.0 between the two polygons. Both polygons must have the same + // organisation, e.g. same amount of polygons + B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t); + + // create 3d PolyPolygon from given 2d PolyPolygon. The given fZCoordinate is used to expand the + // third coordinate. + B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate = 0.0); + + // create 2d PolyPolygon from given 3d PolyPolygon. All coordinates are transformed using the given + // matrix and the resulting x,y is used to form the new polygon. + B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat); + + // for each contained edge in each contained polygon calculate the smallest distance. Return the index to the smallest + // edge in rEdgeIndex and the index to the polygon in rPolygonIndex. The relative position on the edge is returned in rCut. + // If nothing was found (e.g. empty input plygon), DBL_MAX is returned. + double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut); + + // distort PolyPolygon. rOriginal describes the original range, where the given points describe the distorted + // corresponding points. + B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight); + + // rotate PolyPolygon around given point with given angle. + B2DPolyPolygon rotateAroundPoint(const B2DPolyPolygon& rCandidate, const B2DPoint& rCenter, double fAngle); + + // expand all segments (which are not yet) to curve segments. This is done with setting the control + // vectors on the 1/3 resp. 2/3 distances on each segment. + B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate); + + // set continuity for the whole curve. If not a curve, nothing will change. Non-curve points are not changed, too. + B2DPolyPolygon setContinuity(const B2DPolyPolygon& rCandidate, B2VectorContinuity eContinuity); + + /** Predicate whether a given poly-polygon is a rectangle. + + @param rPoly + PolyPolygon to check + + @return true, if the poly-polygon describes a rectangle + (contains exactly one polygon, polygon is closed, and the + points are either cw or ccw enumerations of a rectangle's + vertices). Note that intermediate points and duplicate + points are ignored. + */ + bool isRectangle( const B2DPolyPolygon& rPoly ); + + /** Export poly-polygon to SVG. + + This function exports a poly-polygon into an SVG-D + statement. Currently, output of relative point sequences + is not yet supported (might cause slightly larger output) + + @param rPolyPoly + The poly-polygon to export + + @param bUseRelativeCoordinates + When true, all coordinate values are exported as relative + to the current position. This tends to save some space, + since fewer digits needs to be written. + + @param bDetectQuadraticBeziers + When true, the export tries to detect cubic bezier + segments in the input polygon, which can be represented by + quadratic bezier segments. Note that the generated string + causes versions prior to OOo2.0 to crash. + + @return the generated SVG-D statement (the XML d attribute + value alone, without any "<path ...>" or "d="...") + */ + ::rtl::OUString exportToSvgD( const B2DPolyPolygon& rPolyPoly, + bool bUseRelativeCoordinates=true, + bool bDetectQuadraticBeziers=true ); + + // #i76891# Try to remove existing curve segments if they are simply edges + B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate); + + /** split each edge of a polyPolygon in exactly nSubEdges equidistant edges + + @param rCandidate + The source polyPolygon. If too small (no edges), nSubEdges too small (<2) + or neither bHandleCurvedEdgesnor bHandleStraightEdges it will just be returned. + Else for each edge nSubEdges will be created. Closed state is preserved. + + @param nSubEdges + @param bHandleCurvedEdges + @param bHandleStraightEdges + Please take a look at reSegmentPolygonEdges description, these are the same. + */ + B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges); + + ////////////////////////////////////////////////////////////////////// + // comparators with tolerance for 2D PolyPolygons + bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue); + bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dgeometry.hxx b/basegfx/inc/basegfx/polygon/b3dgeometry.hxx new file mode 100644 index 000000000000..024c7e695b68 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dgeometry.hxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dgeometry.hxx,v $ + * + * $Revision: 1.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B3DGEOMETRY_HXX +#define _BGFX_POLYGON_B3DGEOMETRY_HXX + +////////////////////////////////////////////////////////////////////////////// +// predeclarations + +namespace basegfx +{ +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B3DGeometry + { + private: + B2DPolyPolygon maPolyPolygon; // the PolyPolygon geometry data, defines point number + B3DHomMatrix maPolygonTo3D; // transformation to create 3D PolyPolygon + B3DPolyPolygon maPolyNormal; // normal for each point or empty -> unified normal + B2DPolyPolygon maPolyTexture; // texture coordinate for each point or empty -> unified coordinate + B3DVector maUnifiedVector; // used when maNormal is empty + + // bitfield + unsigned mbUnifiedVectorValid : 1; // flag to know if uvec is calculated yet + + public: + B3DGeometry(); + ~B3DGeometry(); + + // compare operators + bool operator==(const B3DGeometry& rGeometry) const; + bool operator!=(const B3DGeometry& rGeometry) const { return (!operator==(rGeometry)); } + + // member count + sal_uInt32 count() const { return maPolyPolygon.count(); } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + + +#endif /* _BGFX_POLYGON_B3DPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dpolygon.hxx b/basegfx/inc/basegfx/polygon/b3dpolygon.hxx new file mode 100644 index 000000000000..4ac904b7aa8c --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dpolygon.hxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dpolygon.hxx,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B3DPOLYGON_HXX +#define _BGFX_POLYGON_B3DPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> + +////////////////////////////////////////////////////////////////////////////// +// predeclarations +class ImplB3DPolygon; + +namespace basegfx +{ + class B3DPolygon; + class B3DPoint; + class B3DHomMatrix; + class B3DVector; + class B2DPoint; + class B2DHomMatrix; + class BColor; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B3DPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB3DPolygon > ImplType; + + private: + // internal data. + ImplType mpPolygon; + + public: + B3DPolygon(); + B3DPolygon(const B3DPolygon& rPolygon); + B3DPolygon(const B3DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount); + ~B3DPolygon(); + + // assignment operator + B3DPolygon& operator=(const B3DPolygon& rPolygon); + + /// unshare this polygon with all internally shared instances + void makeUnique(); + + // compare operators + bool operator==(const B3DPolygon& rPolygon) const; + bool operator!=(const B3DPolygon& rPolygon) const; + + // member count + sal_uInt32 count() const; + + // Coordinate interface + B3DPoint getB3DPoint(sal_uInt32 nIndex) const; + void setB3DPoint(sal_uInt32 nIndex, const B3DPoint& rValue); + + // Coordinate insert/append + void insert(sal_uInt32 nIndex, const B3DPoint& rPoint, sal_uInt32 nCount = 1); + void append(const B3DPoint& rPoint, sal_uInt32 nCount = 1); + + // BColor interface + BColor getBColor(sal_uInt32 nIndex) const; + void setBColor(sal_uInt32 nIndex, const BColor& rValue); + bool areBColorsUsed() const; + void clearBColors(); + + // Normals interface + B3DVector getNormal() const; // plane normal + B3DVector getNormal(sal_uInt32 nIndex) const; // normal in each point + void setNormal(sal_uInt32 nIndex, const B3DVector& rValue); + void transformNormals(const B3DHomMatrix& rMatrix); + bool areNormalsUsed() const; + void clearNormals(); + + // TextureCoordinate interface + B2DPoint getTextureCoordinate(sal_uInt32 nIndex) const; + void setTextureCoordinate(sal_uInt32 nIndex, const B2DPoint& rValue); + void transformTextureCoordiantes(const B2DHomMatrix& rMatrix); + bool areTextureCoordinatesUsed() const; + void clearTextureCoordinates(); + + // insert/append other 2D polygons + void insert(sal_uInt32 nIndex, const B3DPolygon& rPoly, sal_uInt32 nIndex2 = 0, sal_uInt32 nCount = 0); + void append(const B3DPolygon& rPoly, sal_uInt32 nIndex = 0, sal_uInt32 nCount = 0); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // clear all points + void clear(); + + // closed state + bool isClosed() const; + void setClosed(bool bNew); + + // flip polygon direction + void flip(); + + // test if Polygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const B3DHomMatrix& rMatrix); + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + + +#endif /* _BGFX_POLYGON_B3DPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dpolygonclipper.hxx b/basegfx/inc/basegfx/polygon/b3dpolygonclipper.hxx new file mode 100644 index 000000000000..c33f703424ff --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dpolygonclipper.hxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dpolygonclipper.hxx,v $ + * + * $Revision: 1.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONCLIPPER_HXX +#define _BGFX_POLYPOLYGON_B3DPOLYGONCLIPPER_HXX + +#include <basegfx/polygon/b3dpolypolygon.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B3DRange; + class B2DRange; + + namespace tools + { + /** define for deciding one of X,Y,Z directions + */ + enum B3DOrientation + { + B3DORIENTATION_X, // X-Axis + B3DORIENTATION_Y, // Y-Axis + B3DORIENTATION_Z // Z-Axis + }; + + // Clip given 3D polygon against a plane orthogonal to X,Y or Z axis. The plane is defined using the + // enum ePlaneOrthogonal which names the vector orthogonal to the plane, the fPlaneOffset gives the distance + // of the plane from the center (0.0). + // The value bClipPositive defines on which side the return value will be (true -> on positive side of plane). + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B3DPolyPolygon clipPolyPolygonOnOrthogonalPlane(const B3DPolyPolygon& rCandidate, B3DOrientation ePlaneOrthogonal, bool bClipPositive, double fPlaneOffset, bool bStroke); + + // version for Polygons + B3DPolyPolygon clipPolygonOnOrthogonalPlane(const B3DPolygon& rCandidate, B3DOrientation ePlaneOrthogonal, bool bClipPositive, double fPlaneOffset, bool bStroke); + + // Clip the given PolyPolygon against the given range. bInside defines if the result will contain the + // parts which are contained in the range or vice versa. + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B3DPolyPolygon clipPolyPolygonOnRange(const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bInside, bool bStroke); + + // version for Polygons + B3DPolyPolygon clipPolygonOnRange(const B3DPolygon& rCandidate, const B3DRange& rRange, bool bInside, bool bStroke); + + // versions for B2DRange, clips only against X,Y + B3DPolyPolygon clipPolyPolygonOnRange(const B3DPolyPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + B3DPolyPolygon clipPolygonOnRange(const B3DPolygon& rCandidate, const B2DRange& rRange, bool bInside, bool bStroke); + + // Clip the given PolyPolygon against given plane in 3D. The plane is defined by a plane normal and a point on the plane. + // The value bClipPositive defines on which side the return value will be (true -> on positive side of plane). + // The switch bStroke decides if the polygon is interpreted as area (false) or strokes (true). + B3DPolyPolygon clipPolyPolygonOnPlane(const B3DPolyPolygon& rCandidate, const B3DPoint& rPointOnPlane, const B3DVector& rPlaneNormal, bool bClipPositive, bool bStroke); + + // version for Polygons + B3DPolyPolygon clipPolygonOnPlane(const B3DPolygon& rCandidate, const B3DPoint& rPointOnPlane, const B3DVector& rPlaneNormal, bool bClipPositive, bool bStroke); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B3DPOLYGONCLIPPER_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dpolygontools.hxx b/basegfx/inc/basegfx/polygon/b3dpolygontools.hxx new file mode 100644 index 000000000000..a29204eadc3f --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dpolygontools.hxx @@ -0,0 +1,194 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dpolygontools.hxx,v $ + * $Revision: 1.10.4.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX +#define _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX + +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <basegfx/polygon/b3dpolypolygon.hxx> +#include <basegfx/vector/b2enums.hxx> +#include <vector> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B3DPolygon; + class B3DRange; + + namespace tools + { + // B3DPolygon tools + + /** Check if given polygon is closed. This is kind of a + 'classic' method to support old polygon definitions. + Those old polygon definitions define the closed state + of the polygon using identical start and endpoints. This + method corrects this (removes double start/end points) + and sets the Closed()-state of the polygon correctly. + */ + void checkClosed(B3DPolygon& rCandidate); + + // Get successor and predecessor indices. Returning the same index means there + // is none. Same for successor. + sal_uInt32 getIndexOfPredecessor(sal_uInt32 nIndex, const B3DPolygon& rCandidate); + sal_uInt32 getIndexOfSuccessor(sal_uInt32 nIndex, const B3DPolygon& rCandidate); + + // Get orientation of Polygon + B2VectorOrientation getOrientation(const B3DPolygon& rCandidate); + + // get size of polygon. Control vectors are included in that ranges. + B3DRange getRange(const B3DPolygon& rCandidate); + + // get normal vector of polygon + B3DVector getNormal(const B3DPolygon& rCandidate); + + // get normal vector of positive oriented polygon + B3DVector getPositiveOrientedNormal(const B3DPolygon& rCandidate); + + // get signed area of polygon + double getSignedArea(const B3DPolygon& rCandidate); + + // get area of polygon + double getArea(const B3DPolygon& rCandidate); + + // get signed area of polygon + double getSignedArea(const B3DPolygon& rCandidate); + + // get area of polygon + double getArea(const ::basegfx::B3DPolygon& rCandidate); + + // get length of polygon edge from point nIndex to nIndex + 1 + double getEdgeLength(const B3DPolygon& rCandidate, sal_uInt32 nIndex); + + // get length of polygon + double getLength(const B3DPolygon& rCandidate); + + // get position on polygon for absolute given distance. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + B3DPoint getPositionAbsolute(const B3DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + // get position on polygon for relative given distance in range [0.0 .. 1.0]. If + // length is given, it is assumed the correct polygon length, if 0.0 it is calculated + // using getLength(...) + B3DPoint getPositionRelative(const B3DPolygon& rCandidate, double fDistance, double fLength = 0.0); + + /** Apply given LineDashing to given polygon + + For a description see applyLineDashing in b2dpolygontoos.hxx + */ + void applyLineDashing( + const B3DPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B3DPolyPolygon* pLineTarget, + B3DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + /** Create/replace normals for given 3d geometry with default normals from given center to outside. + rCandidate: the 3d geometry to change + rCenter: the center of the 3d geometry + */ + B3DPolygon applyDefaultNormalsSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter); + + /** invert normals for given 3d geometry. + */ + B3DPolygon invertNormals( const B3DPolygon& rCandidate); + + /** Create/replace texture coordinates for given 3d geometry with parallel projected one + rRange: the full range of the 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + B3DPolygon applyDefaultTextureCoordinatesParallel( const B3DPolygon& rCandidate, const B3DRange& rRange, bool bChangeX = true, bool bChangeY = true); + + /** Create/replace texture coordinates for given 3d geometry with spherical one + rCenter: the centre of the used 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + B3DPolygon applyDefaultTextureCoordinatesSphere( const B3DPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX = true, bool bChangeY = true); + + // test if point is inside epsilon-range around an edge defined + // by the two given points. Can be used for HitTesting. The epsilon-range + // is defined to be the cylinder centered to the given edge, using radius + // fDistance, and the sphere around both points with radius fDistance. + bool isInEpsilonRange(const B3DPoint& rEdgeStart, const B3DPoint& rEdgeEnd, const B3DPoint& rTestPosition, double fDistance); + + // test if point is inside epsilon-range around the given Polygon. Can be used + // for HitTesting. The epsilon-range is defined to be the cylinder centered to + // the given edge, using radius fDistance, and the sphere around both points with radius fDistance. + bool isInEpsilonRange(const B3DPolygon& rCandidate, const B3DPoint& rTestPosition, double fDistance); + + // isInside tests for B3DPoint and other B3DPolygon. On border is not inside as long as + // not true is given in bWithBorder flag. + bool isInside(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder = false); + bool isInside(const B3DPolygon& rCandidate, const B3DPolygon& rPolygon, bool bWithBorder = false); + + // calculates if given point is on given line, taking care of the numerical epsilon + bool isPointOnLine(const B3DPoint& rStart, const B3DPoint& rEnd, const B3DPoint& rCandidate, bool bWithPoints = false); + + // calculates if given point is on given polygon, taking care of the numerical epsilon. Uses + // isPointOnLine internally + bool isPointOnPolygon(const B3DPolygon& rCandidate, const B3DPoint& rPoint, bool bWithPoints = true); + + // helper to get a fCut position between a plane (given with normal and a point) + // and a line given by start and end point + bool getCutBetweenLineAndPlane(const B3DVector& rPlaneNormal, const B3DPoint& rPlanePoint, const B3DPoint& rEdgeStart, const B3DPoint& rEdgeEnd, double& fCut); + + // helper to get a fCut position between a 3d Polygon + // and a line given by start and end point + bool getCutBetweenLineAndPolygon(const B3DPolygon& rCandidate, const B3DPoint& rEdgeStart, const B3DPoint& rEdgeEnd, double& fCut); + + ////////////////////////////////////////////////////////////////////// + // comparators with tolerance for 3D Polygons + bool equal(const B3DPolygon& rCandidateA, const B3DPolygon& rCandidateB, const double& rfSmallValue); + bool equal(const B3DPolygon& rCandidateA, const B3DPolygon& rCandidateB); + + /** snap some polygon coordinates to discrete coordinates + + This method allows to snap some polygon points to discrete (integer) values + which equals e.g. a snap to discrete coordinates. It will snap points of + horizontal and vertical edges + + @param rCandidate + The source polygon + + @return + The modified version of the source polygon + */ + B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dpolypolygon.hxx b/basegfx/inc/basegfx/polygon/b3dpolypolygon.hxx new file mode 100644 index 000000000000..01a053883499 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dpolypolygon.hxx @@ -0,0 +1,128 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dpolypolygon.hxx,v $ + * $Revision: 1.10 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYGON_B3DPOLYPOLYGON_HXX +#define _BGFX_POLYGON_B3DPOLYPOLYGON_HXX + +#include <sal/types.h> +#include <o3tl/cow_wrapper.hxx> + +// predeclarations +class ImplB3DPolyPolygon; + +namespace basegfx +{ + class B3DPolygon; + class B3DHomMatrix; + class B2DHomMatrix; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B3DPolyPolygon + { + public: + typedef o3tl::cow_wrapper< ImplB3DPolyPolygon > ImplType; + + private: + ImplType mpPolyPolygon; + + public: + B3DPolyPolygon(); + B3DPolyPolygon(const B3DPolyPolygon& rPolyPolygon); + explicit B3DPolyPolygon(const B3DPolygon& rPolygon); + ~B3DPolyPolygon(); + + // assignment operator + B3DPolyPolygon& operator=(const B3DPolyPolygon& rPolyPolygon); + + /// unshare this poly-polygon (and all included polygons) with all internally shared instances + void makeUnique(); + + // compare operators + bool operator==(const B3DPolyPolygon& rPolyPolygon) const; + bool operator!=(const B3DPolyPolygon& rPolyPolygon) const; + + // polygon interface + sal_uInt32 count() const; + + // B3DPolygon interface + B3DPolygon getB3DPolygon(sal_uInt32 nIndex) const; + void setB3DPolygon(sal_uInt32 nIndex, const B3DPolygon& rPolygon); + + // BColor interface + bool areBColorsUsed() const; + void clearBColors(); + + // Normals interface + void transformNormals(const B3DHomMatrix& rMatrix); + bool areNormalsUsed() const; + void clearNormals(); + + // TextureCoordinate interface + void transformTextureCoordiantes(const B2DHomMatrix& rMatrix); + bool areTextureCoordinatesUsed() const; + void clearTextureCoordinates(); + + // insert/append single polygon + void insert(sal_uInt32 nIndex, const B3DPolygon& rPolygon, sal_uInt32 nCount = 1); + void append(const B3DPolygon& rPolygon, sal_uInt32 nCount = 1); + + // insert/append multiple polygons + void insert(sal_uInt32 nIndex, const B3DPolyPolygon& rPolyPolygon); + void append(const B3DPolyPolygon& rPolyPolygon); + + // remove + void remove(sal_uInt32 nIndex, sal_uInt32 nCount = 1); + + // reset to empty state + void clear(); + + // closed state + bool isClosed() const; + void setClosed(bool bNew); + + // flip polygon direction + void flip(); + + // test if PolyPolygon has double points + bool hasDoublePoints() const; + + // remove double points, at the begin/end and follow-ups, too + void removeDoublePoints(); + + // apply transformation given in matrix form to the polygon + void transform(const basegfx::B3DHomMatrix& rMatrix); + }; +} // end of namespace basegfx + +#endif /* _BGFX_POLYGON_B3DPOLYPOLYGON_HXX */ diff --git a/basegfx/inc/basegfx/polygon/b3dpolypolygontools.hxx b/basegfx/inc/basegfx/polygon/b3dpolypolygontools.hxx new file mode 100644 index 000000000000..466aa25edd96 --- /dev/null +++ b/basegfx/inc/basegfx/polygon/b3dpolypolygontools.hxx @@ -0,0 +1,157 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: b3dpolypolygontools.hxx,v $ + * $Revision: 1.8.4.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX +#define _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <vector> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/point/b3dpoint.hxx> + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + // predefinitions + class B3DPolyPolygon; + class B3DRange; + + namespace tools + { + // B3DPolyPolygon tools + + // get size of PolyPolygon. Control vectors are included in that ranges. + B3DRange getRange(const B3DPolyPolygon& rCandidate); + + /** Apply given LineDashing to given polyPolygon + + For a description see applyLineDashing in b2dpolygontoos.hxx + */ + void applyLineDashing( + const B3DPolyPolygon& rCandidate, + const ::std::vector<double>& rDotDashArray, + B3DPolyPolygon* pLineTarget, + B3DPolyPolygon* pGapTarget = 0, + double fFullDashDotLen = 0.0); + + /** Create a unit 3D line polyPolygon which defines a cube. + */ + B3DPolyPolygon createUnitCubePolyPolygon(); + + /** Create a unit 3D fill polyPolygon which defines a cube. + */ + B3DPolyPolygon createUnitCubeFillPolyPolygon(); + + /** Create a 3D line polyPolygon from a B3DRange which defines a cube. + */ + B3DPolyPolygon createCubePolyPolygonFromB3DRange( const B3DRange& rRange); + + /** Create a 3D fill polyPolygon from a B3DRange which defines a cube. + */ + B3DPolyPolygon createCubeFillPolyPolygonFromB3DRange( const B3DRange& rRange); + + /** Create a unit 3D line polyPolygon which defines a sphere with the given count of hor and ver segments. + Result will be centered at (0.0, 0.0, 0.0) and sized [-1.0 .. 1.0] in all dimensions. + If nHorSeg == 0 and/or nVerSeg == 0, a default will be calculated to have a step at least each 15 degrees. + With VerStart, VerStop and hor range in cartesian may be specified to create a partial sphere only. + */ + B3DPolyPolygon createUnitSpherePolyPolygon( + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** Create a 3D line polyPolygon from a B3DRange which defines a sphere with the given count of hor and ver segments. + If nHorSeg == 0 and/or nVerSeg == 0, a default will be calculated to have a step at least each 15 degrees. + With VerStart, VerStop and hor range in cartesian may be specified to create a partial sphere only. + */ + B3DPolyPolygon createSpherePolyPolygonFromB3DRange( + const B3DRange& rRange, + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** same as createUnitSpherePolyPolygon, but creates filled polygons (closed and oriented) + There is one extra, the bool bNormals defines if normals will be set, default is false + */ + B3DPolyPolygon createUnitSphereFillPolyPolygon( + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + bool bNormals = false, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** same as createSpherePolyPolygonFromB3DRange, but creates filled polygons (closed and oriented) + There is one extra, the bool bNormals defines if normals will be set, default is false + */ + B3DPolyPolygon createSphereFillPolyPolygonFromB3DRange( + const B3DRange& rRange, + sal_uInt32 nHorSeg = 0L, sal_uInt32 nVerSeg = 0L, + bool bNormals = false, + double fVerStart = F_PI2, double fVerStop = -F_PI2, + double fHorStart = 0.0, double fHorStop = F_2PI); + + /** Create/replace normals for given 3d geometry with default normals from given center to outside. + rCandidate: the 3d geometry to change + rCenter: the center of the 3d geometry + */ + B3DPolyPolygon applyDefaultNormalsSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter); + + /** invert normals for given 3d geometry. + */ + B3DPolyPolygon invertNormals( const B3DPolyPolygon& rCandidate); + + /** Create/replace texture coordinates for given 3d geometry with parallel projected one + rRange: the full range of the 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + B3DPolyPolygon applyDefaultTextureCoordinatesParallel( const B3DPolyPolygon& rCandidate, const B3DRange& rRange, bool bChangeX = true, bool bChangeY = true); + + /** Create/replace texture coordinates for given 3d geometry with spherical one + rCenter: the centre of the used 3d geometry + If bChangeX, x texture coordinate will be recalculated. + If bChangeY, y texture coordinate will be recalculated. + */ + B3DPolyPolygon applyDefaultTextureCoordinatesSphere( const B3DPolyPolygon& rCandidate, const B3DPoint& rCenter, bool bChangeX = true, bool bChangeY = true); + + // isInside test for B3DPoint. On border is not inside as long as not true is given + // in bWithBorder flag. It is assumed that the orientations of the given polygon are correct. + bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder = false); + + ////////////////////////////////////////////////////////////////////// + // comparators with tolerance for 3D PolyPolygons + bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue); + bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB); + + } // end of namespace tools +} // end of namespace basegfx + +#endif /* _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX */ |