2013-07-16 20:09:53 +02:00
/*******************************************************************************
* *
* Author : Angus Johnson *
2015-02-22 15:13:52 +01:00
* Version : 6.2.9 *
* Date : 16 February 2015 *
2013-07-16 20:09:53 +02:00
* Website : http://www.angusj.com *
2015-02-15 16:10:04 +01:00
* Copyright : Angus Johnson 2010-2015 *
2013-07-16 20:09:53 +02:00
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
* Attributions: *
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
* "A generic solution to polygon clipping" *
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
* http://portal.acm.org/citation.cfm?id=129906 *
* *
* Computer graphics and geometric modeling: implementation and algorithms *
* By Max K. Agoston *
* Springer; 1 edition (January 4, 2005) *
* http://books.google.com/books?q=vatti+clipping+agoston *
* *
* See also: *
* "Polygon Offsetting by Computing Winding Numbers" *
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 24-28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
#ifndef clipper_hpp
#define clipper_hpp
2017-07-13 15:52:19 +02:00
#include <inttypes.h>
2013-11-20 11:35:58 +01:00
2017-07-13 15:52:19 +02:00
#define CLIPPER_VERSION "6.2.6"
2013-11-20 11:35:58 +01:00
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
2013-11-21 14:15:38 +01:00
#define use_lines
2013-11-20 11:35:58 +01:00
2014-11-08 12:05:27 +01:00
//use_deprecated: Enables temporary support for the obsolete functions
2013-11-20 15:59:19 +01:00
//#define use_deprecated
2013-11-20 11:35:58 +01:00
2013-07-16 20:09:53 +02:00
#include <vector>
2017-03-02 17:11:46 +01:00
#include <deque>
2013-07-16 20:09:53 +02:00
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include <ostream>
2013-11-20 11:35:58 +01:00
#include <functional>
2014-11-08 12:05:27 +01:00
#include <queue>
2013-07-16 20:09:53 +02:00
namespace ClipperLib {
enum ClipType { ctIntersection , ctUnion , ctDifference , ctXor };
enum PolyType { ptSubject , ptClip };
//By far the most widely used winding rules for polygon filling are
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
//see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd , pftNonZero , pftPositive , pftNegative };
2017-07-13 15:52:19 +02:00
// Point coordinate type
typedef int64_t cInt ;
// Maximum cInt value to allow a cross product calculation using 32bit expressions.
static cInt const loRange = 0x3FFFFFFF ;
// Maximum allowed cInt value.
static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL ;
2013-07-16 20:09:53 +02:00
struct IntPoint {
2013-11-20 11:35:58 +01:00
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 ;
}
2013-07-16 20:09:53 +02:00
};
2013-11-20 11:35:58 +01:00
//------------------------------------------------------------------------------
2013-07-16 20:09:53 +02:00
2013-11-20 11:35:58 +01:00
typedef std :: vector < IntPoint > Path ;
typedef std :: vector < Path > Paths ;
2013-07-16 20:09:53 +02:00
2013-11-20 11:35:58 +01:00
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 ;}
2013-07-16 20:09:53 +02:00
2013-11-20 11:35:58 +01:00
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
2014-11-08 12:05:27 +01:00
typedef void ( * ZFillCallback )( IntPoint & e1bot , IntPoint & e1top , IntPoint & e2bot , IntPoint & e2top , IntPoint & pt );
2013-11-20 11:35:58 +01:00
#endif
2013-07-16 20:09:53 +02:00
2013-12-24 12:40:46 +01:00
enum InitOptions { ioReverseSolution = 1 , ioStrictlySimple = 2 , ioPreserveCollinear = 4 };
enum JoinType { jtSquare , jtRound , jtMiter };
enum EndType { etClosedPolygon , etClosedLine , etOpenButt , etOpenSquare , etOpenRound };
2013-07-16 20:09:53 +02:00
class PolyNode ;
typedef std :: vector < PolyNode * > PolyNodes ;
class PolyNode
{
public :
2017-03-02 17:11:46 +01:00
PolyNode () : Childs (), Parent ( 0 ), Index ( 0 ), m_IsOpen ( false ) {}
2014-11-08 12:05:27 +01:00
virtual ~ PolyNode (){};
2013-11-20 11:35:58 +01:00
Path Contour ;
2013-07-16 20:09:53 +02:00
PolyNodes Childs ;
PolyNode * Parent ;
2017-03-02 17:11:46 +01:00
// Traversal of the polygon tree in a depth first fashion.
PolyNode * GetNext () const { return Childs . empty () ? GetNextSiblingUp () : Childs . front (); }
2013-07-16 20:09:53 +02:00
bool IsHole () const ;
2017-03-02 17:11:46 +01:00
bool IsOpen () const { return m_IsOpen ; }
int ChildCount () const { return ( int ) Childs . size (); }
2013-07-16 20:09:53 +02:00
private :
unsigned Index ; //node index in Parent.Childs
2013-12-24 12:40:46 +01:00
bool m_IsOpen ;
JoinType m_jointype ;
EndType m_endtype ;
2017-03-02 17:11:46 +01:00
PolyNode * GetNextSiblingUp () const { return Parent ? (( Index == Parent -> Childs . size () - 1 ) ? Parent -> GetNextSiblingUp () : Parent -> Childs [ Index + 1 ]) : nullptr ; }
2013-07-16 20:09:53 +02:00
void AddChild ( PolyNode & child );
friend class Clipper ; //to access Index
2016-12-13 18:59:18 +01:00
friend class ClipperOffset ;
friend class PolyTree ; //to implement the PolyTree::move operator
2013-07-16 20:09:53 +02:00
};
class PolyTree : public PolyNode
{
public :
2016-12-13 18:59:18 +01:00
PolyTree () {}
PolyTree ( PolyTree && src ) { * this = std :: move ( src ); }
virtual ~ PolyTree (){ Clear ();};
PolyTree & operator = ( PolyTree && src ) {
AllNodes = std :: move ( src . AllNodes );
Contour = std :: move ( src . Contour );
Childs = std :: move ( src . Childs );
Parent = nullptr ;
Index = src . Index ;
m_IsOpen = src . m_IsOpen ;
m_jointype = src . m_jointype ;
m_endtype = src . m_endtype ;
for ( size_t i = 0 ; i < Childs . size (); ++ i )
Childs [ i ] -> Parent = this ;
return * this ;
}
2017-03-02 17:11:46 +01:00
PolyNode * GetFirst () const { return Childs . empty () ? nullptr : Childs . front (); }
void Clear () { AllNodes . clear (); Childs . clear (); }
2013-07-16 20:09:53 +02:00
int Total () const ;
private :
2016-12-13 18:59:18 +01:00
PolyTree ( const PolyTree & src ) = delete ;
PolyTree & operator = ( const PolyTree & src ) = delete ;
2017-03-02 17:11:46 +01:00
std :: vector < PolyNode > AllNodes ;
2013-07-16 20:09:53 +02:00
friend class Clipper ; //to access AllNodes
};
2013-11-20 11:35:58 +01:00
double Area ( const Path & poly );
2017-03-02 17:34:53 +01:00
inline bool Orientation ( const Path & poly ) { return Area ( poly ) >= 0 ; }
2014-03-23 21:40:35 +01:00
int PointInPolygon ( const IntPoint & pt , const Path & path );
2013-07-16 20:09:53 +02:00
2013-11-20 11:35:58 +01:00
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 );
2013-07-16 20:09:53 +02:00
2013-11-20 11:35:58 +01:00
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 );
2013-07-16 20:09:53 +02:00
2014-03-23 21:40:35 +01:00
void MinkowskiSum ( const Path & pattern , const Path & path , Paths & solution , bool pathIsClosed );
2014-05-23 23:58:43 +02:00
void MinkowskiSum ( const Path & pattern , const Paths & paths , Paths & solution , bool pathIsClosed );
2014-03-23 21:40:35 +01:00
void MinkowskiDiff ( const Path & poly1 , const Path & poly2 , Paths & solution );
2013-11-20 11:35:58 +01:00
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 ; };
//enums that are used internally ...
2013-07-16 20:09:53 +02:00
enum EdgeSide { esLeft = 1 , esRight = 2 };
2017-03-02 17:11:46 +01:00
// namespace Internal {
//forward declarations (for stuff used internally) ...
struct TEdge {
// Bottom point of this edge (with minimum Y).
IntPoint Bot ;
// Current position.
IntPoint Curr ;
// Top point of this edge (with maximum Y).
IntPoint Top ;
// Vector from Bot to Top.
IntPoint Delta ;
// Slope (dx/dy). For horiontal edges, the slope is set to HORIZONTAL (-1.0E+40).
double Dx ;
PolyType PolyTyp ;
EdgeSide Side ;
// Winding number delta. 1 or -1 depending on winding direction, 0 for open paths and flat closed paths.
int WindDelta ;
int WindCnt ;
int WindCnt2 ; //winding count of the opposite polytype
int OutIdx ;
// Next edge in the input path.
TEdge * Next ;
// Previous edge in the input path.
TEdge * Prev ;
// Next edge in the Local Minima List chain.
TEdge * NextInLML ;
TEdge * NextInAEL ;
TEdge * PrevInAEL ;
TEdge * NextInSEL ;
TEdge * PrevInSEL ;
};
2013-07-16 20:09:53 +02:00
2017-03-02 17:11:46 +01:00
struct IntersectNode {
IntersectNode ( TEdge * Edge1 , TEdge * Edge2 , IntPoint Pt ) :
Edge1 ( Edge1 ), Edge2 ( Edge2 ), Pt ( Pt ) {}
TEdge * Edge1 ;
TEdge * Edge2 ;
IntPoint Pt ;
};
struct LocalMinimum {
cInt Y ;
TEdge * LeftBound ;
TEdge * RightBound ;
};
2017-03-03 23:06:51 +01:00
// Point of an output polygon.
2017-07-13 15:52:19 +02:00
// 36B on 64bit system without use_xyz.
2017-03-03 23:06:51 +01:00
struct OutPt {
// 4B
int Idx ;
2017-07-13 15:52:19 +02:00
// 16B without use_xyz / 24B with use_xyz
2017-03-03 23:06:51 +01:00
IntPoint Pt ;
// 4B on 32bit system, 8B on 64bit system
OutPt * Next ;
// 4B on 32bit system, 8B on 64bit system
OutPt * Prev ;
};
2017-03-02 17:11:46 +01:00
struct OutRec ;
struct Join {
Join ( OutPt * OutPt1 , OutPt * OutPt2 , IntPoint OffPt ) :
OutPt1 ( OutPt1 ), OutPt2 ( OutPt2 ), OffPt ( OffPt ) {}
OutPt * OutPt1 ;
OutPt * OutPt2 ;
IntPoint OffPt ;
};
// }; // namespace Internal
2013-12-24 12:40:46 +01:00
2013-11-20 11:35:58 +01:00
//------------------------------------------------------------------------------
2013-07-16 20:09:53 +02:00
//ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of
//polygon coordinates into edge objects that are stored in a LocalMinima list.
class ClipperBase
{
public :
2017-03-02 17:11:46 +01:00
ClipperBase () : m_UseFullRange ( false ), m_HasOpenPaths ( false ) {}
2017-03-08 20:27:03 +01:00
~ ClipperBase () { Clear (); }
2013-11-20 11:35:58 +01:00
bool AddPath ( const Path & pg , PolyType PolyTyp , bool Closed );
bool AddPaths ( const Paths & ppg , PolyType PolyTyp , bool Closed );
2017-03-08 20:27:03 +01:00
void Clear ();
2013-07-16 20:09:53 +02:00
IntRect GetBounds ();
2017-03-01 14:27:08 +01:00
// By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping.
// When enabled the PreserveCollinear property prevents this default behavior to allow these inner vertices to appear in the solution.
2015-07-28 02:26:01 +03:00
bool PreserveCollinear () const { return m_PreserveCollinear ;};
2013-11-20 11:35:58 +01:00
void PreserveCollinear ( bool value ) { m_PreserveCollinear = value ;};
2013-07-16 20:09:53 +02:00
protected :
2017-03-03 21:40:40 +01:00
bool AddPathInternal ( const Path & pg , int highI , PolyType PolyTyp , bool Closed , TEdge * edges );
2013-11-20 11:35:58 +01:00
TEdge * AddBoundsToLML ( TEdge * e , bool IsClosed );
2017-03-08 20:27:03 +01:00
void Reset ();
2013-12-24 12:40:46 +01:00
TEdge * ProcessBound ( TEdge * E , bool IsClockwise );
2013-11-20 11:35:58 +01:00
TEdge * DescendToMin ( TEdge *& E );
void AscendToMax ( TEdge *& E , bool Appending , bool IsClosed );
2014-11-08 12:05:27 +01:00
2017-03-01 14:27:08 +01:00
// Local minima (Y, left edge, right edge) sorted by ascending Y.
std :: vector < LocalMinimum > m_MinimaList ;
2014-11-08 12:05:27 +01:00
2017-03-01 14:27:08 +01:00
// True if the input polygons have abs values higher than loRange, but lower than hiRange.
// False if the input polygons have abs values lower or equal to loRange.
2013-07-16 20:09:53 +02:00
bool m_UseFullRange ;
2017-03-01 14:27:08 +01:00
// A vector of edges per each input path.
2017-03-02 17:11:46 +01:00
std :: vector < std :: vector < TEdge >> m_edges ;
2017-03-01 14:27:08 +01:00
// Don't remove intermediate vertices of a collinear sequence of points.
2013-11-20 11:35:58 +01:00
bool m_PreserveCollinear ;
2017-03-01 14:27:08 +01:00
// Is any of the paths inserted by AddPath() or AddPaths() open?
2013-11-20 11:35:58 +01:00
bool m_HasOpenPaths ;
2013-07-16 20:09:53 +02:00
};
2013-11-20 11:35:58 +01:00
//------------------------------------------------------------------------------
2013-07-16 20:09:53 +02:00
2017-03-08 20:27:03 +01:00
class Clipper : public ClipperBase
2013-07-16 20:09:53 +02:00
{
public :
2013-11-20 11:35:58 +01:00
Clipper ( int initOptions = 0 );
2017-03-02 17:11:46 +01:00
~ Clipper () { Clear (); }
2017-03-03 23:06:51 +01:00
void Clear () { ClipperBase :: Clear (); DisposeAllOutRecs (); }
2013-07-16 20:09:53 +02:00
bool Execute ( ClipType clipType ,
2015-02-15 16:10:04 +01:00
Paths & solution ,
2017-03-02 17:11:46 +01:00
PolyFillType fillType = pftEvenOdd )
{ return Execute ( clipType , solution , fillType , fillType ); }
2013-07-16 20:09:53 +02:00
bool Execute ( ClipType clipType ,
2015-02-15 16:10:04 +01:00
Paths & solution ,
PolyFillType subjFillType ,
PolyFillType clipFillType );
bool Execute ( ClipType clipType ,
PolyTree & polytree ,
2017-03-02 17:11:46 +01:00
PolyFillType fillType = pftEvenOdd )
{ return Execute ( clipType , polytree , fillType , fillType ); }
2015-02-15 16:10:04 +01:00
bool Execute ( ClipType clipType ,
PolyTree & polytree ,
PolyFillType subjFillType ,
PolyFillType clipFillType );
2015-07-28 02:26:01 +03:00
bool ReverseSolution () const { return m_ReverseOutput ; };
2013-07-16 20:09:53 +02:00
void ReverseSolution ( bool value ) { m_ReverseOutput = value ;};
2015-07-28 02:26:01 +03:00
bool StrictlySimple () const { return m_StrictSimple ;};
2013-11-20 11:35:58 +01:00
void StrictlySimple ( bool value ) { m_StrictSimple = value ;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
2017-03-02 17:11:46 +01:00
void ZFillFunction ( ZFillCallback zFillFunc ) { m_ZFill = zFillFunc ; }
2013-11-20 11:35:58 +01:00
#endif
2013-07-16 20:09:53 +02:00
protected :
void Reset ();
virtual bool ExecuteInternal ();
private :
2017-03-03 23:06:51 +01:00
// Output polygons.
std :: vector < OutRec *> m_PolyOuts ;
// Output points, allocated by a continuous sets of m_OutPtsChunkSize.
std :: vector < OutPt *> m_OutPts ;
// List of free output points, to be used before taking a point from m_OutPts or allocating a new chunk.
OutPt * m_OutPtsFree ;
size_t m_OutPtsChunkSize ;
size_t m_OutPtsChunkLast ;
std :: vector < Join > m_Joins ;
std :: vector < Join > m_GhostJoins ;
2017-03-02 17:11:46 +01:00
std :: vector < IntersectNode > m_IntersectList ;
2017-03-03 23:06:51 +01:00
ClipType m_ClipType ;
2017-03-01 14:27:08 +01:00
// A priority queue (a binary heap) of Y coordinates.
std :: priority_queue < cInt > m_Scanbeam ;
2017-03-02 17:11:46 +01:00
// Maxima are collected by ProcessEdgesAtTopOfScanbeam(), consumed by ProcessHorizontal().
2017-03-03 23:06:51 +01:00
std :: vector < cInt > m_Maxima ;
TEdge * m_ActiveEdges ;
TEdge * m_SortedEdges ;
PolyFillType m_ClipFillType ;
PolyFillType m_SubjFillType ;
bool m_ReverseOutput ;
2017-03-01 14:27:08 +01:00
// Does the result go to a PolyTree or Paths?
2017-03-03 23:06:51 +01:00
bool m_UsingPolyTree ;
bool m_StrictSimple ;
2013-11-20 11:35:58 +01:00
#ifdef use_xyz
2017-03-03 23:06:51 +01:00
ZFillCallback m_ZFill ; //custom callback
2013-11-20 11:35:58 +01:00
#endif
2015-07-28 02:26:01 +03:00
void SetWindingCount ( TEdge & edge ) const ;
2017-03-02 17:11:46 +01:00
bool IsEvenOddFillType ( const TEdge & edge ) const
{ return ( edge . PolyTyp == ptSubject ) ? m_SubjFillType == pftEvenOdd : m_ClipFillType == pftEvenOdd ; }
bool IsEvenOddAltFillType ( const TEdge & edge ) const
{ return ( edge . PolyTyp == ptSubject ) ? m_ClipFillType == pftEvenOdd : m_SubjFillType == pftEvenOdd ; }
2013-11-20 11:35:58 +01:00
void InsertLocalMinimaIntoAEL ( const cInt botY );
void InsertEdgeIntoAEL ( TEdge * edge , TEdge * startEdge );
2013-07-16 20:09:53 +02:00
void AddEdgeToSEL ( TEdge * edge );
void CopyAELToSEL ();
void DeleteFromSEL ( TEdge * e );
void DeleteFromAEL ( TEdge * e );
void UpdateEdgeIntoAEL ( TEdge *& e );
void SwapPositionsInSEL ( TEdge * edge1 , TEdge * edge2 );
bool IsContributing ( const TEdge & edge ) const ;
2013-11-20 11:35:58 +01:00
bool IsTopHorz ( const cInt XPos );
2013-07-16 20:09:53 +02:00
void SwapPositionsInAEL ( TEdge * edge1 , TEdge * edge2 );
2013-11-20 11:35:58 +01:00
void DoMaxima ( TEdge * e );
2015-02-15 16:10:04 +01:00
void ProcessHorizontals ();
void ProcessHorizontal ( TEdge * horzEdge );
2013-07-16 20:09:53 +02:00
void AddLocalMaxPoly ( TEdge * e1 , TEdge * e2 , const IntPoint & pt );
2013-11-20 11:35:58 +01:00
OutPt * AddLocalMinPoly ( TEdge * e1 , TEdge * e2 , const IntPoint & pt );
2013-07-16 20:09:53 +02:00
OutRec * GetOutRec ( int idx );
2015-07-28 02:26:01 +03:00
void AppendPolygon ( TEdge * e1 , TEdge * e2 ) const ;
2014-05-23 23:58:43 +02:00
void IntersectEdges ( TEdge * e1 , TEdge * e2 , IntPoint & pt );
2013-07-16 20:09:53 +02:00
OutRec * CreateOutRec ();
2013-11-20 11:35:58 +01:00
OutPt * AddOutPt ( TEdge * e , const IntPoint & pt );
2015-02-15 16:10:04 +01:00
OutPt * GetLastOutPt ( TEdge * e );
2017-03-03 23:06:51 +01:00
OutPt * AllocateOutPt ();
OutPt * DupOutPt ( OutPt * outPt , bool InsertAfter );
// Add the point to a list of free points.
void DisposeOutPt ( OutPt * pt ) { pt -> Next = m_OutPtsFree ; m_OutPtsFree = pt ; }
void DisposeOutPts ( OutPt *& pp ) { if ( pp != nullptr ) { pp -> Prev -> Next = m_OutPtsFree ; m_OutPtsFree = pp ; } }
2013-11-20 11:35:58 +01:00
void DisposeAllOutRecs ();
2014-11-08 12:05:27 +01:00
bool ProcessIntersections ( const cInt topY );
void BuildIntersectList ( const cInt topY );
2013-11-20 11:35:58 +01:00
void ProcessEdgesAtTopOfScanbeam ( const cInt topY );
void BuildResult ( Paths & polys );
2013-07-16 20:09:53 +02:00
void BuildResult2 ( PolyTree & polytree );
2015-07-28 02:26:01 +03:00
void SetHoleState ( TEdge * e , OutRec * outrec ) const ;
2013-07-16 20:09:53 +02:00
bool FixupIntersectionOrder ();
void FixupOutPolygon ( OutRec & outrec );
2015-02-15 16:10:04 +01:00
void FixupOutPolyline ( OutRec & outrec );
2013-12-24 12:40:46 +01:00
bool FindOwnerFromSplitRecs ( OutRec & outRec , OutRec *& currOrfl );
2013-07-16 20:09:53 +02:00
void FixHoleLinkage ( OutRec & outrec );
2013-12-24 12:40:46 +01:00
bool JoinPoints ( Join * j , OutRec * outRec1 , OutRec * outRec2 );
2017-03-03 23:06:51 +01:00
bool JoinHorz ( OutPt * op1 , OutPt * op1b , OutPt * op2 , OutPt * op2b , const IntPoint & Pt , bool DiscardLeft );
2013-07-16 20:09:53 +02:00
void JoinCommonEdges ();
void DoSimplePolygons ();
2015-07-28 02:26:01 +03:00
void FixupFirstLefts1 ( OutRec * OldOutRec , OutRec * NewOutRec ) const ;
void FixupFirstLefts2 ( OutRec * OldOutRec , OutRec * NewOutRec ) const ;
2013-11-20 11:35:58 +01:00
#ifdef use_xyz
2014-05-23 23:58:43 +02:00
void SetZ ( IntPoint & pt , TEdge & e1 , TEdge & e2 );
2013-11-20 11:35:58 +01:00
#endif
2013-07-16 20:09:53 +02:00
};
//------------------------------------------------------------------------------
2013-12-24 12:40:46 +01:00
class ClipperOffset
{
public :
2017-04-04 11:17:25 +02:00
ClipperOffset ( double miterLimit = 2.0 , double roundPrecision = 0.25 , double shortestEdgeLength = 0. ) :
MiterLimit ( miterLimit ), ArcTolerance ( roundPrecision ), ShortestEdgeLength ( shortestEdgeLength ), m_lowest ( - 1 , 0 ) {}
2017-03-02 17:11:46 +01:00
~ ClipperOffset () { Clear (); }
2013-12-24 12:40:46 +01:00
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 ;
2017-04-04 11:17:25 +02:00
double ShortestEdgeLength ;
2013-12-24 12:40:46 +01:00
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 );
};
//------------------------------------------------------------------------------
2013-07-16 20:09:53 +02:00
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 ;
};
//------------------------------------------------------------------------------
} //ClipperLib namespace
#endif //clipper_hpp