| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #ifndef clipper_hpp
|
| | #define clipper_hpp
|
| |
|
| | #define CLIPPER_VERSION "6.4.2"
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | #define use_lines
|
| |
|
| |
|
| |
|
| |
|
| | #include <vector>
|
| | #include <list>
|
| | #include <set>
|
| | #include <stdexcept>
|
| | #include <cstring>
|
| | #include <cstdlib>
|
| | #include <ostream>
|
| | #include <functional>
|
| | #include <queue>
|
| |
|
| | namespace ClipperLib
|
| | {
|
| |
|
| | enum ClipType
|
| | {
|
| | ctIntersection,
|
| | ctUnion,
|
| | ctDifference,
|
| | ctXor
|
| | };
|
| | enum PolyType
|
| | {
|
| | ptSubject,
|
| | ptClip
|
| | };
|
| |
|
| |
|
| |
|
| |
|
| | enum PolyFillType
|
| | {
|
| | pftEvenOdd,
|
| | pftNonZero,
|
| | pftPositive,
|
| | pftNegative
|
| | };
|
| |
|
| | #ifdef use_int32
|
| | typedef int cInt;
|
| | static cInt const loRange = 0x7FFF;
|
| | static cInt const hiRange = 0x7FFF;
|
| | #else
|
| | typedef signed long long cInt;
|
| | static cInt const loRange = 0x3FFFFFFF;
|
| | static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
|
| | typedef signed long long long64;
|
| | typedef unsigned long long ulong64;
|
| |
|
| | #endif
|
| |
|
| | struct IntPoint
|
| | {
|
| | cInt X;
|
| | cInt Y;
|
| | #ifdef use_xyz
|
| | cInt Z;
|
| | IntPoint(cInt x = 0, cInt y = 0, cInt z = 0)
|
| | : X(x)
|
| | , Y(y)
|
| | , Z(z) {};
|
| | #else
|
| | IntPoint(cInt x = 0, cInt y = 0)
|
| | : X(x)
|
| | , Y(y) {};
|
| | #endif
|
| |
|
| | friend inline bool operator==(const IntPoint& a, const IntPoint& b)
|
| | {
|
| | return a.X == b.X && a.Y == b.Y;
|
| | }
|
| | friend inline bool operator!=(const IntPoint& a, const IntPoint& b)
|
| | {
|
| | return a.X != b.X || a.Y != b.Y;
|
| | }
|
| | };
|
| |
|
| |
|
| | typedef std::vector<IntPoint> Path;
|
| | typedef std::vector<Path> Paths;
|
| |
|
| | inline Path& operator<<(Path& poly, const IntPoint& p)
|
| | {
|
| | poly.push_back(p);
|
| | return poly;
|
| | }
|
| | inline Paths& operator<<(Paths& polys, const Path& p)
|
| | {
|
| | polys.push_back(p);
|
| | return polys;
|
| | }
|
| |
|
| | std::ostream& operator<<(std::ostream& s, const IntPoint& p);
|
| | std::ostream& operator<<(std::ostream& s, const Path& p);
|
| | std::ostream& operator<<(std::ostream& s, const Paths& p);
|
| |
|
| | struct DoublePoint
|
| | {
|
| | double X;
|
| | double Y;
|
| | DoublePoint(double x = 0, double y = 0)
|
| | : X(x)
|
| | , Y(y)
|
| | {}
|
| | DoublePoint(IntPoint ip)
|
| | : X((double)ip.X)
|
| | , Y((double)ip.Y)
|
| | {}
|
| | };
|
| |
|
| |
|
| | #ifdef use_xyz
|
| | typedef void (*ZFillCallback)(
|
| | IntPoint& e1bot,
|
| | IntPoint& e1top,
|
| | IntPoint& e2bot,
|
| | IntPoint& e2top,
|
| | IntPoint& pt
|
| | );
|
| | #endif
|
| |
|
| | enum InitOptions
|
| | {
|
| | ioReverseSolution = 1,
|
| | ioStrictlySimple = 2,
|
| | ioPreserveCollinear = 4
|
| | };
|
| | enum JoinType
|
| | {
|
| | jtSquare,
|
| | jtRound,
|
| | jtMiter
|
| | };
|
| | enum EndType
|
| | {
|
| | etClosedPolygon,
|
| | etClosedLine,
|
| | etOpenButt,
|
| | etOpenSquare,
|
| | etOpenRound
|
| | };
|
| |
|
| | class PolyNode;
|
| | typedef std::vector<PolyNode*> PolyNodes;
|
| |
|
| | class PolyNode
|
| | {
|
| | public:
|
| | PolyNode();
|
| | virtual ~PolyNode() {};
|
| | Path Contour;
|
| | PolyNodes Childs;
|
| | PolyNode* Parent;
|
| | PolyNode* GetNext() const;
|
| | bool IsHole() const;
|
| | bool IsOpen() const;
|
| | int ChildCount() const;
|
| |
|
| | private:
|
| |
|
| | unsigned Index;
|
| | bool m_IsOpen;
|
| | JoinType m_jointype;
|
| | EndType m_endtype;
|
| | PolyNode* GetNextSiblingUp() const;
|
| | void AddChild(PolyNode& child);
|
| | friend class Clipper;
|
| | friend class ClipperOffset;
|
| | };
|
| |
|
| | class PolyTree: public PolyNode
|
| | {
|
| | public:
|
| | ~PolyTree()
|
| | {
|
| | Clear();
|
| | };
|
| | PolyNode* GetFirst() const;
|
| | void Clear();
|
| | int Total() const;
|
| |
|
| | private:
|
| |
|
| | PolyNodes AllNodes;
|
| | friend class Clipper;
|
| | };
|
| |
|
| | bool Orientation(const Path& poly);
|
| | double Area(const Path& poly);
|
| | int PointInPolygon(const IntPoint& pt, const Path& path);
|
| |
|
| | void SimplifyPolygon(const Path& in_poly, Paths& out_polys, PolyFillType fillType = pftEvenOdd);
|
| | void SimplifyPolygons(const Paths& in_polys, Paths& out_polys, PolyFillType fillType = pftEvenOdd);
|
| | void SimplifyPolygons(Paths& polys, PolyFillType fillType = pftEvenOdd);
|
| |
|
| | void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
|
| | void CleanPolygon(Path& poly, double distance = 1.415);
|
| | void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
|
| | void CleanPolygons(Paths& polys, double distance = 1.415);
|
| |
|
| | void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
|
| | void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
|
| | void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
|
| |
|
| | void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
|
| | void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
|
| | void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
|
| |
|
| | void ReversePath(Path& p);
|
| | void ReversePaths(Paths& p);
|
| |
|
| | struct IntRect
|
| | {
|
| | cInt left;
|
| | cInt top;
|
| | cInt right;
|
| | cInt bottom;
|
| | };
|
| |
|
| |
|
| | enum EdgeSide
|
| | {
|
| | esLeft = 1,
|
| | esRight = 2
|
| | };
|
| |
|
| |
|
| | struct TEdge;
|
| | struct IntersectNode;
|
| | struct LocalMinimum;
|
| | struct OutPt;
|
| | struct OutRec;
|
| | struct Join;
|
| |
|
| | typedef std::vector<OutRec*> PolyOutList;
|
| | typedef std::vector<TEdge*> EdgeList;
|
| | typedef std::vector<Join*> JoinList;
|
| | typedef std::vector<IntersectNode*> IntersectList;
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | class ClipperBase
|
| | {
|
| | public:
|
| | ClipperBase();
|
| | virtual ~ClipperBase();
|
| | virtual bool AddPath(const Path& pg, PolyType PolyTyp, bool Closed);
|
| | bool AddPaths(const Paths& ppg, PolyType PolyTyp, bool Closed);
|
| | virtual void Clear();
|
| | IntRect GetBounds();
|
| | bool PreserveCollinear()
|
| | {
|
| | return m_PreserveCollinear;
|
| | };
|
| | void PreserveCollinear(bool value)
|
| | {
|
| | m_PreserveCollinear = value;
|
| | };
|
| |
|
| | protected:
|
| | void DisposeLocalMinimaList();
|
| | TEdge* AddBoundsToLML(TEdge* e, bool IsClosed);
|
| | virtual void Reset();
|
| | TEdge* ProcessBound(TEdge* E, bool IsClockwise);
|
| | void InsertScanbeam(const cInt Y);
|
| | bool PopScanbeam(cInt& Y);
|
| | bool LocalMinimaPending();
|
| | bool PopLocalMinima(cInt Y, const LocalMinimum*& locMin);
|
| | OutRec* CreateOutRec();
|
| | void DisposeAllOutRecs();
|
| | void DisposeOutRec(PolyOutList::size_type index);
|
| | void SwapPositionsInAEL(TEdge* edge1, TEdge* edge2);
|
| | void DeleteFromAEL(TEdge* e);
|
| | void UpdateEdgeIntoAEL(TEdge*& e);
|
| |
|
| | typedef std::vector<LocalMinimum> MinimaList;
|
| | MinimaList::iterator m_CurrentLM;
|
| | MinimaList m_MinimaList;
|
| |
|
| | bool m_UseFullRange;
|
| | EdgeList m_edges;
|
| | bool m_PreserveCollinear;
|
| | bool m_HasOpenPaths;
|
| | PolyOutList m_PolyOuts;
|
| | TEdge* m_ActiveEdges;
|
| |
|
| | typedef std::priority_queue<cInt> ScanbeamList;
|
| | ScanbeamList m_Scanbeam;
|
| | };
|
| |
|
| |
|
| | class Clipper: public virtual ClipperBase
|
| | {
|
| | public:
|
| | Clipper(int initOptions = 0);
|
| | bool Execute(ClipType clipType, Paths& solution, PolyFillType fillType = pftEvenOdd);
|
| | bool Execute(ClipType clipType, Paths& solution, PolyFillType subjFillType, PolyFillType clipFillType);
|
| | bool Execute(ClipType clipType, PolyTree& polytree, PolyFillType fillType = pftEvenOdd);
|
| | bool Execute(
|
| | ClipType clipType,
|
| | PolyTree& polytree,
|
| | PolyFillType subjFillType,
|
| | PolyFillType clipFillType
|
| | );
|
| | bool ReverseSolution()
|
| | {
|
| | return m_ReverseOutput;
|
| | };
|
| | void ReverseSolution(bool value)
|
| | {
|
| | m_ReverseOutput = value;
|
| | };
|
| | bool StrictlySimple()
|
| | {
|
| | return m_StrictSimple;
|
| | };
|
| | void StrictlySimple(bool value)
|
| | {
|
| | m_StrictSimple = value;
|
| | };
|
| |
|
| | #ifdef use_xyz
|
| | void ZFillFunction(ZFillCallback zFillFunc);
|
| | #endif
|
| | protected:
|
| | virtual bool ExecuteInternal();
|
| |
|
| | private:
|
| | JoinList m_Joins;
|
| | JoinList m_GhostJoins;
|
| | IntersectList m_IntersectList;
|
| | ClipType m_ClipType;
|
| | typedef std::list<cInt> MaximaList;
|
| | MaximaList m_Maxima;
|
| | TEdge* m_SortedEdges;
|
| | bool m_ExecuteLocked;
|
| | PolyFillType m_ClipFillType;
|
| | PolyFillType m_SubjFillType;
|
| | bool m_ReverseOutput;
|
| | bool m_UsingPolyTree;
|
| | bool m_StrictSimple;
|
| | #ifdef use_xyz
|
| | ZFillCallback m_ZFill;
|
| | #endif
|
| | void SetWindingCount(TEdge& edge);
|
| | bool IsEvenOddFillType(const TEdge& edge) const;
|
| | bool IsEvenOddAltFillType(const TEdge& edge) const;
|
| | void InsertLocalMinimaIntoAEL(const cInt botY);
|
| | void InsertEdgeIntoAEL(TEdge* edge, TEdge* startEdge);
|
| | void AddEdgeToSEL(TEdge* edge);
|
| | bool PopEdgeFromSEL(TEdge*& edge);
|
| | void CopyAELToSEL();
|
| | void DeleteFromSEL(TEdge* e);
|
| | void SwapPositionsInSEL(TEdge* edge1, TEdge* edge2);
|
| | bool IsContributing(const TEdge& edge) const;
|
| | bool IsTopHorz(const cInt XPos);
|
| | void DoMaxima(TEdge* e);
|
| | void ProcessHorizontals();
|
| | void ProcessHorizontal(TEdge* horzEdge);
|
| | void AddLocalMaxPoly(TEdge* e1, TEdge* e2, const IntPoint& pt);
|
| | OutPt* AddLocalMinPoly(TEdge* e1, TEdge* e2, const IntPoint& pt);
|
| | OutRec* GetOutRec(int idx);
|
| | void AppendPolygon(TEdge* e1, TEdge* e2);
|
| | void IntersectEdges(TEdge* e1, TEdge* e2, IntPoint& pt);
|
| | OutPt* AddOutPt(TEdge* e, const IntPoint& pt);
|
| | OutPt* GetLastOutPt(TEdge* e);
|
| | bool ProcessIntersections(const cInt topY);
|
| | void BuildIntersectList(const cInt topY);
|
| | void ProcessIntersectList();
|
| | void ProcessEdgesAtTopOfScanbeam(const cInt topY);
|
| | void BuildResult(Paths& polys);
|
| | void BuildResult2(PolyTree& polytree);
|
| | void SetHoleState(TEdge* e, OutRec* outrec);
|
| | void DisposeIntersectNodes();
|
| | bool FixupIntersectionOrder();
|
| | void FixupOutPolygon(OutRec& outrec);
|
| | void FixupOutPolyline(OutRec& outrec);
|
| | bool IsHole(TEdge* e);
|
| | bool FindOwnerFromSplitRecs(OutRec& outRec, OutRec*& currOrfl);
|
| | void FixHoleLinkage(OutRec& outrec);
|
| | void AddJoin(OutPt* op1, OutPt* op2, const IntPoint offPt);
|
| | void ClearJoins();
|
| | void ClearGhostJoins();
|
| | void AddGhostJoin(OutPt* op, const IntPoint offPt);
|
| | bool JoinPoints(Join* j, OutRec* outRec1, OutRec* outRec2);
|
| | void JoinCommonEdges();
|
| | void DoSimplePolygons();
|
| | void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
|
| | void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
|
| | void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
|
| | #ifdef use_xyz
|
| | void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
|
| | #endif
|
| | };
|
| |
|
| |
|
| | class ClipperOffset
|
| | {
|
| | public:
|
| | ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
|
| | ~ClipperOffset();
|
| | void AddPath(const Path& path, JoinType joinType, EndType endType);
|
| | void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
|
| | void Execute(Paths& solution, double delta);
|
| | void Execute(PolyTree& solution, double delta);
|
| | void Clear();
|
| | double MiterLimit;
|
| | double ArcTolerance;
|
| |
|
| | private:
|
| | Paths m_destPolys;
|
| | Path m_srcPoly;
|
| | Path m_destPoly;
|
| | std::vector<DoublePoint> m_normals;
|
| | double m_delta, m_sinA, m_sin, m_cos;
|
| | double m_miterLim, m_StepsPerRad;
|
| | IntPoint m_lowest;
|
| | PolyNode m_polyNodes;
|
| |
|
| | void FixOrientations();
|
| | void DoOffset(double delta);
|
| | void OffsetPoint(int j, int& k, JoinType jointype);
|
| | void DoSquare(int j, int k);
|
| | void DoMiter(int j, int k, double r);
|
| | void DoRound(int j, int k);
|
| | };
|
| |
|
| |
|
| | class clipperException: public std::exception
|
| | {
|
| | public:
|
| | clipperException(const char* description)
|
| | : m_descr(description)
|
| | {}
|
| | virtual ~clipperException() throw()
|
| | {}
|
| | virtual const char* what() const throw()
|
| | {
|
| | return m_descr.c_str();
|
| | }
|
| |
|
| | private:
|
| | std::string m_descr;
|
| | };
|
| |
|
| |
|
| | }
|
| |
|
| | #endif
|
| |
|