Commit eb22bf42 authored by jean-pierre charras's avatar jean-pierre charras

Pcbnew: very minor fixes and update: update clipper version. uncrustify...

Pcbnew: very minor fixes and update:  update clipper version. uncrustify polytri/* and fix some warning compil.
parent 6e56aa2f
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
#ifndef DRW_BASE_H #ifndef DRW_BASE_H
#define DRW_BASE_H #define DRW_BASE_H
#define DRW_VERSION "0.5.10" #define DRW_VERSION "0.5.11"
#include <string> #include <string>
#include <cmath> #include <cmath>
......
...@@ -27,7 +27,7 @@ class dxfRW ...@@ -27,7 +27,7 @@ class dxfRW
public: public:
dxfRW( const char* name ); dxfRW( const char* name );
~dxfRW(); ~dxfRW();
// / reads the file specified in constructor /// reads the file specified in constructor
/*! /*!
* An interface must be provided. It is used by the class to signal various * An interface must be provided. It is used by the class to signal various
* components being added. * components being added.
...@@ -71,7 +71,7 @@ public: ...@@ -71,7 +71,7 @@ public:
void setEllipseParts( int parts ) { elParts = parts; } /*!< set parts munber when convert ellipse to polyline */ void setEllipseParts( int parts ) { elParts = parts; } /*!< set parts munber when convert ellipse to polyline */
private: private:
// / used by read() to parse the content of the file /// used by read() to parse the content of the file
bool processDxf(); bool processDxf();
bool processHeader(); bool processHeader();
bool processTables(); bool processTables();
......
...@@ -88,8 +88,8 @@ CPolyLine::~CPolyLine() ...@@ -88,8 +88,8 @@ CPolyLine::~CPolyLine()
#include "clipper.hpp" #include "clipper.hpp"
int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList ) int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList )
{ {
ClipperLib::Polygon raw_polygon; ClipperLib::Path raw_polygon;
ClipperLib::Polygons normalized_polygons; ClipperLib::Paths normalized_polygons;
unsigned corners_count = m_CornersList.GetCornersCount(); unsigned corners_count = m_CornersList.GetCornersCount();
...@@ -115,7 +115,7 @@ int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList ) ...@@ -115,7 +115,7 @@ int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList )
// enter main outline // enter main outline
for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ ) for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ )
{ {
ClipperLib::Polygon& polygon = normalized_polygons[ii]; ClipperLib::Path& polygon = normalized_polygons[ii];
cornerslist.clear(); cornerslist.clear();
for( unsigned jj = 0; jj < polygon.size(); jj++ ) for( unsigned jj = 0; jj < polygon.size(); jj++ )
cornerslist.push_back( KI_POLY_POINT( KiROUND( polygon[jj].X ), cornerslist.push_back( KI_POLY_POINT( KiROUND( polygon[jj].X ),
...@@ -142,7 +142,7 @@ int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList ) ...@@ -142,7 +142,7 @@ int CPolyLine::NormalizeAreaOutlines( std::vector<CPolyLine*>* aNewPolygonList )
ClipperLib::SimplifyPolygon( raw_polygon, normalized_polygons ); ClipperLib::SimplifyPolygon( raw_polygon, normalized_polygons );
for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ ) for( unsigned ii = 0; ii < normalized_polygons.size(); ii++ )
{ {
ClipperLib::Polygon& polygon = normalized_polygons[ii]; ClipperLib::Path& polygon = normalized_polygons[ii];
cornerslist.clear(); cornerslist.clear();
for( unsigned jj = 0; jj < polygon.size(); jj++ ) for( unsigned jj = 0; jj < polygon.size(); jj++ )
cornerslist.push_back( KI_POLY_POINT( KiROUND( polygon[jj].X ), cornerslist.push_back( KI_POLY_POINT( KiROUND( polygon[jj].X ),
......
This source diff could not be displayed because it is too large. You can view the blob instead.
/******************************************************************************* /*******************************************************************************
* * * *
* Author : Angus Johnson * * Author : Angus Johnson *
* Version : 5.1.4 * * Version : 6.1.2 *
* Date : 24 March 2013 * * Date : 15 December 2013 *
* Website : http://www.angusj.com * * Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2013 * * Copyright : Angus Johnson 2010-2013 *
* * * *
...@@ -34,11 +34,29 @@ ...@@ -34,11 +34,29 @@
#ifndef clipper_hpp #ifndef clipper_hpp
#define clipper_hpp #define clipper_hpp
#define CLIPPER_VERSION "6.1.2"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//#define use_int32
//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.
//#define use_lines
//use_deprecated: Enables support for the obsolete OffsetPaths() function
//which has been replace with the ClipperOffset class.
#define use_deprecated
#include <vector> #include <vector>
#include <set>
#include <stdexcept> #include <stdexcept>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <ostream> #include <ostream>
#include <functional>
namespace ClipperLib { namespace ClipperLib {
...@@ -50,23 +68,64 @@ enum PolyType { ptSubject, ptClip }; ...@@ -50,23 +68,64 @@ enum PolyType { ptSubject, ptClip };
//see http://glprogramming.com/red/chapter11.html //see http://glprogramming.com/red/chapter11.html
enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative }; enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
typedef signed long long long64; #ifdef use_int32
typedef unsigned long long ulong64; typedef int cInt;
typedef unsigned int cUInt;
#else
typedef signed long long cInt;
typedef unsigned long long cUInt;
#endif
struct IntPoint { struct IntPoint {
public: cInt X;
long64 X; cInt Y;
long64 Y; #ifdef use_xyz
IntPoint(long64 x = 0, long64 y = 0): X(x), Y(y) {}; cInt Z;
friend std::ostream& operator <<(std::ostream &s, IntPoint &p); 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 > Polygon; typedef std::vector< IntPoint > Path;
typedef std::vector< Polygon > Polygons; 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) {}
};
//------------------------------------------------------------------------------
std::ostream& operator <<(std::ostream &s, Polygon &p); #ifdef use_xyz
std::ostream& operator <<(std::ostream &s, Polygons &p); typedef void (*TZFillCallback)(IntPoint& z1, IntPoint& z2, IntPoint& pt);
#endif
enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
enum JoinType {jtSquare, jtRound, jtMiter};
enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
#ifdef use_deprecated
enum EndType_ {etClosed, etButt = 2, etSquare, etRound};
#endif
class PolyNode; class PolyNode;
typedef std::vector< PolyNode* > PolyNodes; typedef std::vector< PolyNode* > PolyNodes;
...@@ -75,17 +134,22 @@ class PolyNode ...@@ -75,17 +134,22 @@ class PolyNode
{ {
public: public:
PolyNode(); PolyNode();
Polygon Contour; Path Contour;
PolyNodes Childs; PolyNodes Childs;
PolyNode* Parent; PolyNode* Parent;
PolyNode* GetNext() const; PolyNode* GetNext() const;
bool IsHole() const; bool IsHole() const;
bool IsOpen() const;
int ChildCount() const; int ChildCount() const;
private: private:
PolyNode* GetNextSiblingUp() const;
unsigned Index; //node index in Parent.Childs unsigned Index; //node index in Parent.Childs
bool m_IsOpen;
JoinType m_jointype;
EndType m_endtype;
PolyNode* GetNextSiblingUp() const;
void AddChild(PolyNode& child); void AddChild(PolyNode& child);
friend class Clipper; //to access Index friend class Clipper; //to access Index
friend class ClipperOffset;
}; };
class PolyTree: public PolyNode class PolyTree: public PolyNode
...@@ -99,113 +163,55 @@ private: ...@@ -99,113 +163,55 @@ private:
PolyNodes AllNodes; PolyNodes AllNodes;
friend class Clipper; //to access AllNodes friend class Clipper; //to access AllNodes
}; };
enum JoinType { jtSquare, jtRound, jtMiter };
bool Orientation(const Polygon &poly);
double Area(const Polygon &poly);
void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys,
double delta, JoinType jointype = jtSquare, double limit = 0, bool autoFix = true);
void SimplifyPolygon(const Polygon &in_poly, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); bool Orientation(const Path &poly);
void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd); double Area(const Path &poly);
void SimplifyPolygons(Polygons &polys, PolyFillType fillType = pftEvenOdd);
void CleanPolygon(Polygon& in_poly, Polygon& out_poly, double distance = 1.415); #ifdef use_deprecated
void CleanPolygons(Polygons& in_polys, Polygons& out_polys, double distance = 1.415); void OffsetPaths(const Paths &in_polys, Paths &out_polys,
double delta, JoinType jointype, EndType_ endtype, double limit = 0);
#endif
void PolyTreeToPolygons(PolyTree& polytree, Polygons& polygons); 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 ReversePolygon(Polygon& p); void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
void ReversePolygons(Polygons& p); 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);
//used internally ... void MinkowskiSum(const Path& poly, const Path& path, Paths& solution, bool isClosed);
enum EdgeSide { esLeft = 1, esRight = 2}; void MinkowskiDiff(const Path& poly, const Path& path, Paths& solution, bool isClosed);
enum IntersectProtects { ipNone = 0, ipLeft = 1, ipRight = 2, ipBoth = 3 };
struct TEdge {
long64 xbot;
long64 ybot;
long64 xcurr;
long64 ycurr;
long64 xtop;
long64 ytop;
double dx;
long64 deltaX;
long64 deltaY;
PolyType polyType;
EdgeSide side;
int windDelta; //1 or -1 depending on winding direction
int windCnt;
int windCnt2; //winding count of the opposite polytype
int outIdx;
TEdge *next;
TEdge *prev;
TEdge *nextInLML;
TEdge *nextInAEL;
TEdge *prevInAEL;
TEdge *nextInSEL;
TEdge *prevInSEL;
};
struct IntersectNode { void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
TEdge *edge1; void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
TEdge *edge2; void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
IntPoint pt;
IntersectNode *next;
};
struct LocalMinima { void ReversePath(Path& p);
long64 Y; void ReversePaths(Paths& p);
TEdge *leftBound;
TEdge *rightBound;
LocalMinima *next;
};
struct Scanbeam { struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
long64 Y;
Scanbeam *next;
};
struct OutPt; //forward declaration //enums that are used internally ...
enum EdgeSide { esLeft = 1, esRight = 2};
struct OutRec {
int idx;
bool isHole;
OutRec *FirstLeft; //see comments in clipper.pas
PolyNode *polyNode;
OutPt *pts;
OutPt *bottomPt;
};
struct OutPt {
int idx;
IntPoint pt;
OutPt *next;
OutPt *prev;
};
struct JoinRec {
IntPoint pt1a;
IntPoint pt1b;
int poly1Idx;
IntPoint pt2a;
IntPoint pt2b;
int poly2Idx;
};
struct HorzJoinRec {
TEdge *edge;
int savedIdx;
};
struct IntRect { long64 left; long64 top; long64 right; long64 bottom; }; //forward declarations (for stuff used internally) ...
struct TEdge;
struct IntersectNode;
struct LocalMinima;
struct Scanbeam;
struct OutPt;
struct OutRec;
struct Join;
typedef std::vector < OutRec* > PolyOutList; typedef std::vector < OutRec* > PolyOutList;
typedef std::vector < TEdge* > EdgeList; typedef std::vector < TEdge* > EdgeList;
typedef std::vector < JoinRec* > JoinList; typedef std::vector < Join* > JoinList;
typedef std::vector < HorzJoinRec* > HorzJoinList; typedef std::vector < IntersectNode* > IntersectList;
//------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be //ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of //instantiated directly. This class simply abstracts the conversion of sets of
...@@ -215,29 +221,38 @@ class ClipperBase ...@@ -215,29 +221,38 @@ class ClipperBase
public: public:
ClipperBase(); ClipperBase();
virtual ~ClipperBase(); virtual ~ClipperBase();
bool AddPolygon(const Polygon &pg, PolyType polyType); bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
bool AddPolygons( const Polygons &ppg, PolyType polyType); bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
virtual void Clear(); virtual void Clear();
IntRect GetBounds(); IntRect GetBounds();
bool PreserveCollinear() {return m_PreserveCollinear;};
void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
protected: protected:
void DisposeLocalMinimaList(); void DisposeLocalMinimaList();
TEdge* AddBoundsToLML(TEdge *e); TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
void PopLocalMinima(); void PopLocalMinima();
virtual void Reset(); virtual void Reset();
TEdge* ProcessBound(TEdge* E, bool IsClockwise);
void InsertLocalMinima(LocalMinima *newLm); void InsertLocalMinima(LocalMinima *newLm);
void DoMinimaLML(TEdge* E1, TEdge* E2, bool IsClosed);
TEdge* DescendToMin(TEdge *&E);
void AscendToMax(TEdge *&E, bool Appending, bool IsClosed);
LocalMinima *m_CurrentLM; LocalMinima *m_CurrentLM;
LocalMinima *m_MinimaList; LocalMinima *m_MinimaList;
bool m_UseFullRange; bool m_UseFullRange;
EdgeList m_edges; EdgeList m_edges;
bool m_PreserveCollinear;
bool m_HasOpenPaths;
}; };
//------------------------------------------------------------------------------
class Clipper : public virtual ClipperBase class Clipper : public virtual ClipperBase
{ {
public: public:
Clipper(); Clipper(int initOptions = 0);
~Clipper(); ~Clipper();
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
Polygons &solution, Paths &solution,
PolyFillType subjFillType = pftEvenOdd, PolyFillType subjFillType = pftEvenOdd,
PolyFillType clipFillType = pftEvenOdd); PolyFillType clipFillType = pftEvenOdd);
bool Execute(ClipType clipType, bool Execute(ClipType clipType,
...@@ -247,31 +262,40 @@ public: ...@@ -247,31 +262,40 @@ public:
void Clear(); void Clear();
bool ReverseSolution() {return m_ReverseOutput;}; bool ReverseSolution() {return m_ReverseOutput;};
void ReverseSolution(bool value) {m_ReverseOutput = value;}; void ReverseSolution(bool value) {m_ReverseOutput = value;};
bool StrictlySimple() {return m_StrictSimple;};
void StrictlySimple(bool value) {m_StrictSimple = value;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void ZFillFunction(TZFillCallback zFillFunc);
#endif
protected: protected:
void Reset(); void Reset();
virtual bool ExecuteInternal(); virtual bool ExecuteInternal();
private: private:
PolyOutList m_PolyOuts; PolyOutList m_PolyOuts;
JoinList m_Joins; JoinList m_Joins;
HorzJoinList m_HorizJoins; JoinList m_GhostJoins;
IntersectList m_IntersectList;
ClipType m_ClipType; ClipType m_ClipType;
Scanbeam *m_Scanbeam; std::set< cInt, std::greater<cInt> > m_Scanbeam;
TEdge *m_ActiveEdges; TEdge *m_ActiveEdges;
TEdge *m_SortedEdges; TEdge *m_SortedEdges;
IntersectNode *m_IntersectNodes;
bool m_ExecuteLocked; bool m_ExecuteLocked;
PolyFillType m_ClipFillType; PolyFillType m_ClipFillType;
PolyFillType m_SubjFillType; PolyFillType m_SubjFillType;
bool m_ReverseOutput; bool m_ReverseOutput;
bool m_UsingPolyTree; bool m_UsingPolyTree;
void DisposeScanbeamList(); bool m_StrictSimple;
#ifdef use_xyz
TZFillCallback m_ZFill; //custom callback
#endif
void SetWindingCount(TEdge& edge); void SetWindingCount(TEdge& edge);
bool IsEvenOddFillType(const TEdge& edge) const; bool IsEvenOddFillType(const TEdge& edge) const;
bool IsEvenOddAltFillType(const TEdge& edge) const; bool IsEvenOddAltFillType(const TEdge& edge) const;
void InsertScanbeam(const long64 Y); void InsertScanbeam(const cInt Y);
long64 PopScanbeam(); cInt PopScanbeam();
void InsertLocalMinimaIntoAEL(const long64 botY); void InsertLocalMinimaIntoAEL(const cInt botY);
void InsertEdgeIntoAEL(TEdge *edge); void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
void AddEdgeToSEL(TEdge *edge); void AddEdgeToSEL(TEdge *edge);
void CopyAELToSEL(); void CopyAELToSEL();
void DeleteFromSEL(TEdge *e); void DeleteFromSEL(TEdge *e);
...@@ -279,48 +303,79 @@ private: ...@@ -279,48 +303,79 @@ private:
void UpdateEdgeIntoAEL(TEdge *&e); void UpdateEdgeIntoAEL(TEdge *&e);
void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2); void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
bool IsContributing(const TEdge& edge) const; bool IsContributing(const TEdge& edge) const;
bool IsTopHorz(const long64 XPos); bool IsTopHorz(const cInt XPos);
void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2); void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
void DoMaxima(TEdge *e, long64 topY); void DoMaxima(TEdge *e);
void ProcessHorizontals(); void PrepareHorzJoins(TEdge* horzEdge, bool isTopOfScanbeam);
void ProcessHorizontal(TEdge *horzEdge); void ProcessHorizontals(bool IsTopOfScanbeam);
void ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam);
void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt); void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
void AddLocalMinPoly(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 AppendPolygon(TEdge *e1, TEdge *e2);
void DoEdge1(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void DoEdge2(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt);
void IntersectEdges(TEdge *e1, TEdge *e2, void IntersectEdges(TEdge *e1, TEdge *e2,
const IntPoint &pt, const IntersectProtects protects); const IntPoint &pt, bool protect = false);
OutRec* CreateOutRec(); OutRec* CreateOutRec();
void AddOutPt(TEdge *e, const IntPoint &pt); OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
void DisposeAllPolyPts(); void DisposeAllOutRecs();
void DisposeOutRec(PolyOutList::size_type index); void DisposeOutRec(PolyOutList::size_type index);
bool ProcessIntersections(const long64 botY, const long64 topY); bool ProcessIntersections(const cInt botY, const cInt topY);
void AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt); void BuildIntersectList(const cInt botY, const cInt topY);
void BuildIntersectList(const long64 botY, const long64 topY);
void ProcessIntersectList(); void ProcessIntersectList();
void ProcessEdgesAtTopOfScanbeam(const long64 topY); void ProcessEdgesAtTopOfScanbeam(const cInt topY);
void BuildResult(Polygons& polys); void BuildResult(Paths& polys);
void BuildResult2(PolyTree& polytree); void BuildResult2(PolyTree& polytree);
void SetHoleState(TEdge *e, OutRec *OutRec); void SetHoleState(TEdge *e, OutRec *outrec);
void DisposeIntersectNodes(); void DisposeIntersectNodes();
bool FixupIntersectionOrder(); bool FixupIntersectionOrder();
void FixupOutPolygon(OutRec &outRec); void FixupOutPolygon(OutRec &outrec);
bool IsHole(TEdge *e); bool IsHole(TEdge *e);
void FixHoleLinkage(OutRec &outRec); bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
void AddJoin(TEdge *e1, TEdge *e2, int e1OutIdx = -1, int e2OutIdx = -1); void FixHoleLinkage(OutRec &outrec);
void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
void ClearJoins(); void ClearJoins();
void AddHorzJoin(TEdge *e, int idx); void ClearGhostJoins();
void ClearHorzJoins(); void AddGhostJoin(OutPt *op, const IntPoint offPt);
bool JoinPoints(const JoinRec *j, OutPt *&p1, OutPt *&p2); bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
void FixupJoinRecs(JoinRec *j, OutPt *pt, unsigned startIdx);
void JoinCommonEdges(); void JoinCommonEdges();
void DoSimplePolygons();
void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec); void FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec);
#ifdef use_xyz
void SetZ(IntPoint& pt, TEdge& e);
#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 class clipperException : public std::exception
......
...@@ -32,63 +32,74 @@ ...@@ -32,63 +32,74 @@
#include <iostream> #include <iostream>
namespace p2t { namespace p2t {
Triangle::Triangle( Point& a, Point& b, Point& c )
Triangle::Triangle(Point& a, Point& b, Point& c)
{ {
points_[0] = &a; points_[1] = &b; points_[2] = &c; points_[0] = &a; points_[1] = &b; points_[2] = &c;
neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;
constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
interior_ = false; interior_ = false;
} }
// Update neighbor pointers // Update neighbor pointers
void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) void Triangle::MarkNeighbor( Point* p1, Point* p2, Triangle* t )
{ {
if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) if( (p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2]) )
neighbors_[0] = t; neighbors_[0] = t;
else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) else if( (p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0]) )
neighbors_[1] = t; neighbors_[1] = t;
else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) else if( (p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0]) )
neighbors_[2] = t; neighbors_[2] = t;
else else
assert(0); assert( 0 );
} }
// Exhaustive search to update neighbor pointers // Exhaustive search to update neighbor pointers
void Triangle::MarkNeighbor(Triangle& t) void Triangle::MarkNeighbor( Triangle& t )
{ {
if (t.Contains(points_[1], points_[2])) { if( t.Contains( points_[1], points_[2] ) )
neighbors_[0] = &t; {
t.MarkNeighbor(points_[1], points_[2], this); neighbors_[0] = &t;
} else if (t.Contains(points_[0], points_[2])) { t.MarkNeighbor( points_[1], points_[2], this );
neighbors_[1] = &t; }
t.MarkNeighbor(points_[0], points_[2], this); else if( t.Contains( points_[0], points_[2] ) )
} else if (t.Contains(points_[0], points_[1])) { {
neighbors_[2] = &t; neighbors_[1] = &t;
t.MarkNeighbor(points_[0], points_[1], this); t.MarkNeighbor( points_[0], points_[2], this );
} }
else if( t.Contains( points_[0], points_[1] ) )
{
neighbors_[2] = &t;
t.MarkNeighbor( points_[0], points_[1], this );
}
} }
/** /**
* Clears all references to all other triangles and points * Clears all references to all other triangles and points
*/ */
void Triangle::Clear() void Triangle::Clear()
{ {
Triangle *t; Triangle* t;
for( int i=0; i<3; i++ )
for( int i = 0; i<3; i++ )
{ {
t = neighbors_[i]; t = neighbors_[i];
if( t != NULL ) if( t != NULL )
{ {
t->ClearNeighbor( this ); t->ClearNeighbor( this );
} }
} }
ClearNeighbors(); ClearNeighbors();
points_[0]=points_[1]=points_[2] = NULL; points_[0] = points_[1] = points_[2] = NULL;
} }
void Triangle::ClearNeighbor(Triangle *triangle )
void Triangle::ClearNeighbor( Triangle* triangle )
{ {
if( neighbors_[0] == triangle ) if( neighbors_[0] == triangle )
{ {
...@@ -104,263 +115,379 @@ void Triangle::ClearNeighbor(Triangle *triangle ) ...@@ -104,263 +115,379 @@ void Triangle::ClearNeighbor(Triangle *triangle )
} }
} }
void Triangle::ClearNeighbors() void Triangle::ClearNeighbors()
{ {
neighbors_[0] = NULL; neighbors_[0] = NULL;
neighbors_[1] = NULL; neighbors_[1] = NULL;
neighbors_[2] = NULL; neighbors_[2] = NULL;
} }
void Triangle::ClearDelunayEdges() void Triangle::ClearDelunayEdges()
{ {
delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;
} }
Point* Triangle::OppositePoint(Triangle& t, Point& p)
Point* Triangle::OppositePoint( Triangle& t, Point& p )
{ {
Point *cw = t.PointCW(p); Point* cw = t.PointCW( p );
double x = cw->x; double x = cw->x;
double y = cw->y; double y = cw->y;
x = p.x;
y = p.y; x = p.x;
return PointCW(*cw); y = p.y;
return PointCW( *cw );
} }
// Legalized triangle by rotating clockwise around point(0) // Legalized triangle by rotating clockwise around point(0)
void Triangle::Legalize(Point& point) void Triangle::Legalize( Point& point )
{ {
points_[1] = points_[0]; points_[1] = points_[0];
points_[0] = points_[2]; points_[0] = points_[2];
points_[2] = &point; points_[2] = &point;
} }
// Legalize triagnle by rotating clockwise around oPoint // Legalize triagnle by rotating clockwise around oPoint
void Triangle::Legalize(Point& opoint, Point& npoint) void Triangle::Legalize( Point& opoint, Point& npoint )
{ {
if (&opoint == points_[0]) { if( &opoint == points_[0] )
points_[1] = points_[0]; {
points_[0] = points_[2]; points_[1] = points_[0];
points_[2] = &npoint; points_[0] = points_[2];
} else if (&opoint == points_[1]) { points_[2] = &npoint;
points_[2] = points_[1]; }
points_[1] = points_[0]; else if( &opoint == points_[1] )
points_[0] = &npoint; {
} else if (&opoint == points_[2]) { points_[2] = points_[1];
points_[0] = points_[2]; points_[1] = points_[0];
points_[2] = points_[1]; points_[0] = &npoint;
points_[1] = &npoint; }
} else { else if( &opoint == points_[2] )
assert(0); {
} points_[0] = points_[2];
points_[2] = points_[1];
points_[1] = &npoint;
}
else
{
assert( 0 );
}
} }
int Triangle::Index(const Point* p)
int Triangle::Index( const Point* p )
{ {
if (p == points_[0]) { if( p == points_[0] )
return 0; {
} else if (p == points_[1]) { return 0;
return 1; }
} else if (p == points_[2]) { else if( p == points_[1] )
return 2; {
} return 1;
assert(0); }
else if( p == points_[2] )
{
return 2;
}
assert( 0 );
} }
int Triangle::EdgeIndex(const Point* p1, const Point* p2)
int Triangle::EdgeIndex( const Point* p1, const Point* p2 )
{ {
if (points_[0] == p1) { if( points_[0] == p1 )
if (points_[1] == p2) { {
return 2; if( points_[1] == p2 )
} else if (points_[2] == p2) { {
return 1; return 2;
} }
} else if (points_[1] == p1) { else if( points_[2] == p2 )
if (points_[2] == p2) { {
return 0; return 1;
} else if (points_[0] == p2) { }
return 2; }
} else if( points_[1] == p1 )
} else if (points_[2] == p1) { {
if (points_[0] == p2) { if( points_[2] == p2 )
return 1; {
} else if (points_[1] == p2) { return 0;
return 0; }
} else if( points_[0] == p2 )
} {
return -1; return 2;
}
}
else if( points_[2] == p1 )
{
if( points_[0] == p2 )
{
return 1;
}
else if( points_[1] == p2 )
{
return 0;
}
}
return -1;
} }
void Triangle::MarkConstrainedEdge(const int index)
void Triangle::MarkConstrainedEdge( const int index )
{ {
constrained_edge[index] = true; constrained_edge[index] = true;
} }
void Triangle::MarkConstrainedEdge(Edge& edge)
void Triangle::MarkConstrainedEdge( Edge& edge )
{ {
MarkConstrainedEdge(edge.p, edge.q); MarkConstrainedEdge( edge.p, edge.q );
} }
// Mark edge as constrained // Mark edge as constrained
void Triangle::MarkConstrainedEdge(Point* p, Point* q) void Triangle::MarkConstrainedEdge( Point* p, Point* q )
{ {
if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { if( (q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0]) )
constrained_edge[2] = true; {
} else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { constrained_edge[2] = true;
constrained_edge[1] = true; }
} else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { else if( (q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0]) )
constrained_edge[0] = true; {
} constrained_edge[1] = true;
}
else if( (q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1]) )
{
constrained_edge[0] = true;
}
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
Point* Triangle::PointCW(Point& point) Point* Triangle::PointCW( Point& point )
{ {
if (&point == points_[0]) { if( &point == points_[0] )
return points_[2]; {
} else if (&point == points_[1]) { return points_[2];
return points_[0]; }
} else if (&point == points_[2]) { else if( &point == points_[1] )
return points_[1]; {
} return points_[0];
assert(0); }
else if( &point == points_[2] )
{
return points_[1];
}
assert( 0 );
} }
// The point counter-clockwise to given point // The point counter-clockwise to given point
Point* Triangle::PointCCW(Point& point) Point* Triangle::PointCCW( Point& point )
{ {
if (&point == points_[0]) { if( &point == points_[0] )
return points_[1]; {
} else if (&point == points_[1]) { return points_[1];
return points_[2]; }
} else if (&point == points_[2]) { else if( &point == points_[1] )
return points_[0]; {
} return points_[2];
assert(0); }
else if( &point == points_[2] )
{
return points_[0];
}
assert( 0 );
} }
// The neighbor clockwise to given point // The neighbor clockwise to given point
Triangle* Triangle::NeighborCW(Point& point) Triangle* Triangle::NeighborCW( Point& point )
{ {
if (&point == points_[0]) { if( &point == points_[0] )
return neighbors_[1]; {
} else if (&point == points_[1]) { return neighbors_[1];
return neighbors_[2]; }
} else if( &point == points_[1] )
return neighbors_[0]; {
} return neighbors_[2];
}
// The neighbor counter-clockwise to given point
Triangle* Triangle::NeighborCCW(Point& point)
{
if (&point == points_[0]) {
return neighbors_[2];
} else if (&point == points_[1]) {
return neighbors_[0]; return neighbors_[0];
}
return neighbors_[1];
} }
bool Triangle::GetConstrainedEdgeCCW(Point& p)
// The neighbor counter-clockwise to given point
Triangle* Triangle::NeighborCCW( Point& point )
{ {
if (&p == points_[0]) { if( &point == points_[0] )
return constrained_edge[2]; {
} else if (&p == points_[1]) { return neighbors_[2];
return constrained_edge[0]; }
} else if( &point == points_[1] )
return constrained_edge[1]; {
return neighbors_[0];
}
return neighbors_[1];
} }
bool Triangle::GetConstrainedEdgeCW(Point& p)
bool Triangle::GetConstrainedEdgeCCW( Point& p )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
{
return constrained_edge[2];
}
else if( &p == points_[1] )
{
return constrained_edge[0];
}
return constrained_edge[1]; return constrained_edge[1];
} else if (&p == points_[1]) {
return constrained_edge[2];
}
return constrained_edge[0];
} }
void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)
bool Triangle::GetConstrainedEdgeCW( Point& p )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
constrained_edge[2] = ce; {
} else if (&p == points_[1]) { return constrained_edge[1];
constrained_edge[0] = ce; }
} else { else if( &p == points_[1] )
constrained_edge[1] = ce; {
} return constrained_edge[2];
}
return constrained_edge[0];
} }
void Triangle::SetConstrainedEdgeCW(Point& p, bool ce)
void Triangle::SetConstrainedEdgeCCW( Point& p, bool ce )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
constrained_edge[1] = ce; {
} else if (&p == points_[1]) { constrained_edge[2] = ce;
constrained_edge[2] = ce; }
} else { else if( &p == points_[1] )
constrained_edge[0] = ce; {
} constrained_edge[0] = ce;
}
else
{
constrained_edge[1] = ce;
}
} }
bool Triangle::GetDelunayEdgeCCW(Point& p)
void Triangle::SetConstrainedEdgeCW( Point& p, bool ce )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
return delaunay_edge[2]; {
} else if (&p == points_[1]) { constrained_edge[1] = ce;
return delaunay_edge[0]; }
} else if( &p == points_[1] )
return delaunay_edge[1]; {
constrained_edge[2] = ce;
}
else
{
constrained_edge[0] = ce;
}
} }
bool Triangle::GetDelunayEdgeCW(Point& p)
bool Triangle::GetDelunayEdgeCCW( Point& p )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
{
return delaunay_edge[2];
}
else if( &p == points_[1] )
{
return delaunay_edge[0];
}
return delaunay_edge[1]; return delaunay_edge[1];
} else if (&p == points_[1]) {
return delaunay_edge[2];
}
return delaunay_edge[0];
} }
void Triangle::SetDelunayEdgeCCW(Point& p, bool e)
bool Triangle::GetDelunayEdgeCW( Point& p )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
delaunay_edge[2] = e; {
} else if (&p == points_[1]) { return delaunay_edge[1];
delaunay_edge[0] = e; }
} else { else if( &p == points_[1] )
delaunay_edge[1] = e; {
} return delaunay_edge[2];
}
return delaunay_edge[0];
} }
void Triangle::SetDelunayEdgeCW(Point& p, bool e)
void Triangle::SetDelunayEdgeCCW( Point& p, bool e )
{ {
if (&p == points_[0]) { if( &p == points_[0] )
delaunay_edge[1] = e; {
} else if (&p == points_[1]) { delaunay_edge[2] = e;
delaunay_edge[2] = e; }
} else { else if( &p == points_[1] )
delaunay_edge[0] = e; {
} delaunay_edge[0] = e;
}
else
{
delaunay_edge[1] = e;
}
} }
void Triangle::SetDelunayEdgeCW( Point& p, bool e )
{
if( &p == points_[0] )
{
delaunay_edge[1] = e;
}
else if( &p == points_[1] )
{
delaunay_edge[2] = e;
}
else
{
delaunay_edge[0] = e;
}
}
// The neighbor across to given point // The neighbor across to given point
Triangle& Triangle::NeighborAcross(Point& opoint) Triangle& Triangle::NeighborAcross( Point& opoint )
{ {
if (&opoint == points_[0]) { if( &opoint == points_[0] )
return *neighbors_[0]; {
} else if (&opoint == points_[1]) { return *neighbors_[0];
return *neighbors_[1]; }
} else if( &opoint == points_[1] )
return *neighbors_[2]; {
return *neighbors_[1];
}
return *neighbors_[2];
} }
void Triangle::DebugPrint() void Triangle::DebugPrint()
{ {
std::cout << points_[0]->x << "," << points_[0]->y << " "; std::cout << points_[0]->x << "," << points_[0]->y << " ";
std::cout << points_[1]->x << "," << points_[1]->y << " "; std::cout << points_[1]->x << "," << points_[1]->y << " ";
std::cout << points_[2]->x << "," << points_[2]->y << "\n"; std::cout << points_[2]->x << "," << points_[2]->y << "\n";
} }
} }
...@@ -39,287 +39,313 @@ ...@@ -39,287 +39,313 @@
#include <cmath> #include <cmath>
namespace p2t { namespace p2t {
struct Edge; struct Edge;
struct Point { struct Point
{
double x, y; double x, y;
/// Default constructor does nothing (for performance). /// Default constructor does nothing (for performance).
Point() Point()
{ {
x = 0.0; x = 0.0;
y = 0.0; y = 0.0;
} }
/// The edges this point constitutes an upper ending point /// The edges this point constitutes an upper ending point
std::vector<Edge*> edge_list; std::vector<Edge*> edge_list;
/// Construct using coordinates. /// Construct using coordinates.
Point(double x, double y) : x(x), y(y) {} Point( double x, double y ) : x( x ), y( y ) {}
/// Set this point to all zeros. /// Set this point to all zeros.
void set_zero() void set_zero()
{ {
x = 0.0; x = 0.0;
y = 0.0; y = 0.0;
} }
/// Set this point to some specified coordinates. /// Set this point to some specified coordinates.
void set(double x_, double y_) void set( double x_, double y_ )
{ {
x = x_; x = x_;
y = y_; y = y_;
} }
/// Negate this point. /// Negate this point.
Point operator -() const Point operator -() const
{ {
Point v; Point v;
v.set(-x, -y);
return v; v.set( -x, -y );
} return v;
}
/// Add a point to this point.
void operator +=(const Point& v) /// Add a point to this point.
{ void operator +=( const Point& v )
x += v.x; {
y += v.y; x += v.x;
} y += v.y;
}
/// Subtract a point from this point.
void operator -=(const Point& v) /// Subtract a point from this point.
{ void operator -=( const Point& v )
x -= v.x; {
y -= v.y; x -= v.x;
} y -= v.y;
}
/// Multiply this point by a scalar.
void operator *=(double a) /// Multiply this point by a scalar.
{ void operator *=( double a )
x *= a; {
y *= a; x *= a;
} y *= a;
}
/// Get the length of this point (the norm).
double Length() const /// Get the length of this point (the norm).
{ double Length() const
return sqrt(x * x + y * y); {
} return sqrt( x * x + y * y );
}
/// Convert this point into a unit point. Returns the Length.
double Normalize()
{
double len = Length();
x /= len;
y /= len;
return len;
}
/// Convert this point into a unit point. Returns the Length.
double Normalize()
{
double len = Length();
x /= len;
y /= len;
return len;
}
}; };
// Represents a simple polygon's edge // Represents a simple polygon's edge
struct Edge { struct Edge
{
Point* p, *q; Point* p, * q;
/// Constructor /// Constructor
Edge(Point& p1, Point& p2) : p(&p1), q(&p2) Edge( Point& p1, Point& p2 ) : p( &p1 ), q( &p2 )
{ {
if (p1.y > p2.y) { if( p1.y > p2.y )
q = &p1; {
p = &p2; q = &p1;
} else if (p1.y == p2.y) { p = &p2;
if (p1.x > p2.x) { }
q = &p1; else if( p1.y == p2.y )
p = &p2; {
} else if (p1.x == p2.x) { if( p1.x > p2.x )
// Repeat points {
assert(false); q = &p1;
} p = &p2;
}
else if( p1.x == p2.x )
{
// Repeat points
assert( false );
}
}
q->edge_list.push_back( this );
} }
q->edge_list.push_back(this);
}
}; };
// Triangle-based data structures are know to have better performance than quad-edge structures // Triangle-based data structures are know to have better performance than quad-edge structures
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL" // "Triangulations in CGAL"
class Triangle { class Triangle
{
public: public:
/// Constructor /// Constructor
Triangle(Point& a, Point& b, Point& c); Triangle( Point& a, Point& b, Point& c );
/// Flags to determine if an edge is a Constrained edge /// Flags to determine if an edge is a Constrained edge
bool constrained_edge[3]; bool constrained_edge[3];
/// Flags to determine if an edge is a Delauney edge /// Flags to determine if an edge is a Delauney edge
bool delaunay_edge[3]; bool delaunay_edge[3];
Point* GetPoint(const int& index); Point* GetPoint( const int& index );
Point* PointCW(Point& point); Point* PointCW( Point& point );
Point* PointCCW(Point& point); Point* PointCCW( Point& point );
Point* OppositePoint(Triangle& t, Point& p); Point* OppositePoint( Triangle& t, Point& p );
Triangle* GetNeighbor(const int& index); Triangle* GetNeighbor( const int& index );
void MarkNeighbor(Point* p1, Point* p2, Triangle* t); void MarkNeighbor( Point* p1, Point* p2, Triangle* t );
void MarkNeighbor(Triangle& t); void MarkNeighbor( Triangle& t );
void MarkConstrainedEdge(const int index); void MarkConstrainedEdge( const int index );
void MarkConstrainedEdge(Edge& edge); void MarkConstrainedEdge( Edge& edge );
void MarkConstrainedEdge(Point* p, Point* q); void MarkConstrainedEdge( Point* p, Point* q );
int Index(const Point* p); int Index( const Point* p );
int EdgeIndex(const Point* p1, const Point* p2); int EdgeIndex( const Point* p1, const Point* p2 );
Triangle* NeighborCW(Point& point); Triangle* NeighborCW( Point& point );
Triangle* NeighborCCW(Point& point); Triangle* NeighborCCW( Point& point );
bool GetConstrainedEdgeCCW(Point& p); bool GetConstrainedEdgeCCW( Point& p );
bool GetConstrainedEdgeCW(Point& p); bool GetConstrainedEdgeCW( Point& p );
void SetConstrainedEdgeCCW(Point& p, bool ce); void SetConstrainedEdgeCCW( Point& p, bool ce );
void SetConstrainedEdgeCW(Point& p, bool ce); void SetConstrainedEdgeCW( Point& p, bool ce );
bool GetDelunayEdgeCCW(Point& p); bool GetDelunayEdgeCCW( Point& p );
bool GetDelunayEdgeCW(Point& p); bool GetDelunayEdgeCW( Point& p );
void SetDelunayEdgeCCW(Point& p, bool e); void SetDelunayEdgeCCW( Point& p, bool e );
void SetDelunayEdgeCW(Point& p, bool e); void SetDelunayEdgeCW( Point& p, bool e );
bool Contains(Point* p); bool Contains( Point* p );
bool Contains(const Edge& e); bool Contains( const Edge& e );
bool Contains(Point* p, Point* q); bool Contains( Point* p, Point* q );
void Legalize(Point& point); void Legalize( Point& point );
void Legalize(Point& opoint, Point& npoint); void Legalize( Point& opoint, Point& npoint );
/** /**
* Clears all references to all other triangles and points * Clears all references to all other triangles and points
*/ */
void Clear(); void Clear();
void ClearNeighbor(Triangle *triangle ); void ClearNeighbor( Triangle* triangle );
void ClearNeighbors(); void ClearNeighbors();
void ClearDelunayEdges(); void ClearDelunayEdges();
inline bool IsInterior(); inline bool IsInterior();
inline void IsInterior(bool b); inline void IsInterior( bool b );
Triangle& NeighborAcross(Point& opoint); Triangle& NeighborAcross( Point& opoint );
void DebugPrint(); void DebugPrint();
private: private:
/// Triangle points /// Triangle points
Point* points_[3]; Point* points_[3];
/// Neighbor list /// Neighbor list
Triangle* neighbors_[3]; Triangle* neighbors_[3];
/// Has this triangle been marked as an interior triangle? /// Has this triangle been marked as an interior triangle?
bool interior_; bool interior_;
}; };
inline bool cmp(const Point* a, const Point* b) inline bool cmp( const Point* a, const Point* b )
{ {
if (a->y < b->y) { if( a->y < b->y )
return true; {
} else if (a->y == b->y) { return true;
// Make sure q is point with greater x value
if (a->x < b->x) {
return true;
} }
} else if( a->y == b->y )
return false; {
// Make sure q is point with greater x value
if( a->x < b->x )
{
return true;
}
}
return false;
} }
/// Add two points_ component-wise. /// Add two points_ component-wise.
inline Point operator +(const Point& a, const Point& b) inline Point operator +( const Point& a, const Point& b )
{ {
return Point(a.x + b.x, a.y + b.y); return Point( a.x + b.x, a.y + b.y );
} }
/// Subtract two points_ component-wise. /// Subtract two points_ component-wise.
inline Point operator -(const Point& a, const Point& b) inline Point operator -( const Point& a, const Point& b )
{ {
return Point(a.x - b.x, a.y - b.y); return Point( a.x - b.x, a.y - b.y );
} }
/// Multiply point by scalar /// Multiply point by scalar
inline Point operator *(double s, const Point& a) inline Point operator *( double s, const Point& a )
{ {
return Point(s * a.x, s * a.y); return Point( s * a.x, s * a.y );
} }
inline bool operator ==(const Point& a, const Point& b)
inline bool operator ==( const Point& a, const Point& b )
{ {
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
inline bool operator !=(const Point& a, const Point& b)
inline bool operator !=( const Point& a, const Point& b )
{ {
return !(a.x == b.x) && !(a.y == b.y); return !(a.x == b.x) && !(a.y == b.y);
} }
/// Peform the dot product on two vectors. /// Peform the dot product on two vectors.
inline double Dot(const Point& a, const Point& b) inline double Dot( const Point& a, const Point& b )
{ {
return a.x * b.x + a.y * b.y; return a.x * b.x + a.y * b.y;
} }
/// Perform the cross product on two vectors. In 2D this produces a scalar. /// Perform the cross product on two vectors. In 2D this produces a scalar.
inline double Cross(const Point& a, const Point& b) inline double Cross( const Point& a, const Point& b )
{ {
return a.x * b.y - a.y * b.x; return a.x * b.y - a.y * b.x;
} }
/// Perform the cross product on a point and a scalar. In 2D this produces /// Perform the cross product on a point and a scalar. In 2D this produces
/// a point. /// a point.
inline Point Cross(const Point& a, double s) inline Point Cross( const Point& a, double s )
{ {
return Point(s * a.y, -s * a.x); return Point( s * a.y, -s * a.x );
} }
/// Perform the cross product on a scalar and a point. In 2D this produces /// Perform the cross product on a scalar and a point. In 2D this produces
/// a point. /// a point.
inline Point Cross(const double s, const Point& a) inline Point Cross( const double s, const Point& a )
{ {
return Point(-s * a.y, s * a.x); return Point( -s * a.y, s * a.x );
} }
inline Point* Triangle::GetPoint(const int& index)
inline Point* Triangle::GetPoint( const int& index )
{ {
return points_[index]; return points_[index];
} }
inline Triangle* Triangle::GetNeighbor(const int& index)
inline Triangle* Triangle::GetNeighbor( const int& index )
{ {
return neighbors_[index]; return neighbors_[index];
} }
inline bool Triangle::Contains(Point* p)
inline bool Triangle::Contains( Point* p )
{ {
return p == points_[0] || p == points_[1] || p == points_[2]; return p == points_[0] || p == points_[1] || p == points_[2];
} }
inline bool Triangle::Contains(const Edge& e)
inline bool Triangle::Contains( const Edge& e )
{ {
return Contains(e.p) && Contains(e.q); return Contains( e.p ) && Contains( e.q );
} }
inline bool Triangle::Contains(Point* p, Point* q)
inline bool Triangle::Contains( Point* p, Point* q )
{ {
return Contains(p) && Contains(q); return Contains( p ) && Contains( q );
} }
inline bool Triangle::IsInterior() inline bool Triangle::IsInterior()
{ {
return interior_; return interior_;
} }
inline void Triangle::IsInterior(bool b)
inline void Triangle::IsInterior( bool b )
{ {
interior_ = b; interior_ = b;
} }
} }
#endif #endif
/* /*
* Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
* http://code.google.com/p/poly2tri/ * http://code.google.com/p/poly2tri/
* *
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef UTILS_H #ifndef UTILS_H
#define UTILS_H #define UTILS_H
...@@ -39,12 +39,13 @@ ...@@ -39,12 +39,13 @@
#include <math.h> #include <math.h>
namespace p2t { namespace p2t {
const double PI_3div4 = 3 * M_PI / 4;
const double PI_div2 = 1.57079632679489661923;
const double EPSILON = 1e-12;
const double PI_3div4 = 3 * M_PI / 4; enum Orientation {
const double PI_div2 = 1.57079632679489661923; CW, CCW, COLLINEAR
const double EPSILON = 1e-12; };
enum Orientation { CW, CCW, COLLINEAR };
/** /**
* Forumla to calculate signed area<br> * Forumla to calculate signed area<br>
...@@ -56,68 +57,77 @@ enum Orientation { CW, CCW, COLLINEAR }; ...@@ -56,68 +57,77 @@ enum Orientation { CW, CCW, COLLINEAR };
* = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3) * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
* </pre> * </pre>
*/ */
Orientation Orient2d(Point& pa, Point& pb, Point& pc) Orientation Orient2d( Point& pa, Point& pb, Point& pc )
{ {
double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detleft = (pa.x - pc.x) * (pb.y - pc.y);
double detright = (pa.y - pc.y) * (pb.x - pc.x); double detright = (pa.y - pc.y) * (pb.x - pc.x);
double val = detleft - detright; double val = detleft - detright;
if (val > -EPSILON && val < EPSILON) {
return COLLINEAR; if( val > -EPSILON && val < EPSILON )
} else if (val > 0) { {
return CCW; return COLLINEAR;
} }
return CW; else if( val > 0 )
{
return CCW;
}
return CW;
} }
/*
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
{
double pdx = pd.x;
double pdy = pd.y;
double adx = pa.x - pdx;
double ady = pa.y - pdy;
double bdx = pb.x - pdx;
double bdy = pb.y - pdy;
double adxbdy = adx * bdy;
double bdxady = bdx * ady;
double oabd = adxbdy - bdxady;
if (oabd <= EPSILON) { /*
return false; * bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
} * {
* double pdx = pd.x;
double cdx = pc.x - pdx; * double pdy = pd.y;
double cdy = pc.y - pdy; * double adx = pa.x - pdx;
* double ady = pa.y - pdy;
* double bdx = pb.x - pdx;
* double bdy = pb.y - pdy;
*
* double adxbdy = adx * bdy;
* double bdxady = bdx * ady;
* double oabd = adxbdy - bdxady;
*
* if (oabd <= EPSILON) {
* return false;
* }
*
* double cdx = pc.x - pdx;
* double cdy = pc.y - pdy;
*
* double cdxady = cdx * ady;
* double adxcdy = adx * cdy;
* double ocad = cdxady - adxcdy;
*
* if (ocad <= EPSILON) {
* return false;
* }
*
* return true;
* }
*
*/
double cdxady = cdx * ady; bool InScanArea( Point& pa, Point& pb, Point& pc, Point& pd )
double adxcdy = adx * cdy; {
double ocad = cdxady - adxcdy; double oadb = (pa.x - pb.x) * (pd.y - pb.y) - (pd.x - pb.x) * (pa.y - pb.y);
if (ocad <= EPSILON) { if( oadb >= -EPSILON )
return false; {
} return false;
}
return true; double oadc = (pa.x - pc.x) * (pd.y - pc.y) - (pd.x - pc.x) * (pa.y - pc.y);
}
*/ if( oadc <= EPSILON )
{
return false;
}
bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) return true;
{
double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);
if (oadb >= -EPSILON) {
return false;
}
double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);
if (oadc <= EPSILON) {
return false;
}
return true;
} }
} }
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment