Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
31332c39
Commit
31332c39
authored
Nov 20, 2012
by
jean-pierre charras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
polygon: update clipper lib.
parent
1dd0adf7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
320 additions
and
214 deletions
+320
-214
clipper.cpp
polygon/clipper.cpp
+307
-203
clipper.hpp
polygon/clipper.hpp
+13
-11
No files found.
polygon/clipper.cpp
View file @
31332c39
/*******************************************************************************
/*******************************************************************************
* *
* *
* Author : Angus Johnson *
* Author : Angus Johnson *
* Version : 4.
8.5
*
* Version : 4.
9.6
*
* Date :
15 July 2012
*
* Date :
9 November 2012
*
* Website : http://www.angusj.com *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2012 *
* Copyright : Angus Johnson 2010-2012 *
* *
* *
...
@@ -49,8 +49,8 @@
...
@@ -49,8 +49,8 @@
namespace
ClipperLib
{
namespace
ClipperLib
{
static
long64
const
loRange
=
1518500249
;
//sqrt(2^63 -1)/2
static
long64
const
loRange
=
0x3FFFFFFF
;
static
long64
const
hiRange
=
6521908912666391106LL
;
//sqrt(2^127 -1)/2
static
long64
const
hiRange
=
0x3FFFFFFFFFFFFFFFLL
;
static
double
const
pi
=
3.141592653589793238
;
static
double
const
pi
=
3.141592653589793238
;
enum
Direction
{
dRightToLeft
,
dLeftToRight
};
enum
Direction
{
dRightToLeft
,
dLeftToRight
};
...
@@ -103,7 +103,7 @@ class Int128
...
@@ -103,7 +103,7 @@ class Int128
if
(
hi
!=
val
.
hi
)
if
(
hi
!=
val
.
hi
)
return
hi
>
val
.
hi
;
return
hi
>
val
.
hi
;
else
else
return
lo
>
val
.
lo
;
return
ulong64
(
lo
)
>
ulong64
(
val
.
lo
)
;
}
}
bool
operator
<
(
const
Int128
&
val
)
const
bool
operator
<
(
const
Int128
&
val
)
const
...
@@ -111,9 +111,15 @@ class Int128
...
@@ -111,9 +111,15 @@ class Int128
if
(
hi
!=
val
.
hi
)
if
(
hi
!=
val
.
hi
)
return
hi
<
val
.
hi
;
return
hi
<
val
.
hi
;
else
else
return
lo
<
val
.
lo
;
return
ulong64
(
lo
)
<
ulong64
(
val
.
lo
)
;
}
}
bool
operator
>=
(
const
Int128
&
val
)
const
{
return
!
(
*
this
<
val
);}
bool
operator
<=
(
const
Int128
&
val
)
const
{
return
!
(
*
this
>
val
);}
Int128
&
operator
+=
(
const
Int128
&
rhs
)
Int128
&
operator
+=
(
const
Int128
&
rhs
)
{
{
hi
+=
rhs
.
hi
;
hi
+=
rhs
.
hi
;
...
@@ -219,20 +225,15 @@ class Int128
...
@@ -219,20 +225,15 @@ class Int128
double
AsDouble
()
const
double
AsDouble
()
const
{
{
const
double
shift64
=
18446744073709551616.0
;
//2^64
const
double
shift64
=
18446744073709551616.0
;
//2^64
const
double
bit64
=
9223372036854775808.0
;
if
(
hi
<
0
)
if
(
hi
<
0
)
{
{
Int128
tmp
(
*
this
);
if
(
lo
==
0
)
Negate
(
tmp
);
return
(
double
)
hi
*
shift64
;
if
(
tmp
.
lo
<
0
)
return
(
double
)
tmp
.
lo
-
bit64
-
tmp
.
hi
*
shift64
;
else
else
return
-
(
double
)
tmp
.
lo
-
tmp
.
hi
*
shift64
;
return
-
(
double
)
(
ulong64
(
-
lo
)
+
~
hi
*
shift64
)
;
}
}
else
if
(
lo
<
0
)
return
-
(
double
)
lo
+
bit64
+
hi
*
shift64
;
else
else
return
(
double
)
lo
+
(
double
)
hi
*
shift64
;
return
(
double
)
(
ulong64
(
lo
)
+
hi
*
shift64
)
;
}
}
//for bug testing ...
//for bug testing ...
...
@@ -317,7 +318,7 @@ bool FullRangeNeeded(const Polygon &pts)
...
@@ -317,7 +318,7 @@ bool FullRangeNeeded(const Polygon &pts)
return
result
;
return
result
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
Orientation
(
const
Polygon
&
poly
)
bool
Orientation
(
const
Polygon
&
poly
)
{
{
int
highI
=
(
int
)
poly
.
size
()
-
1
;
int
highI
=
(
int
)
poly
.
size
()
-
1
;
...
@@ -349,10 +350,10 @@ bool Orientation(const Polygon &poly)
...
@@ -349,10 +350,10 @@ bool Orientation(const Polygon &poly)
throw
"Coordinate exceeds range bounds."
;
throw
"Coordinate exceeds range bounds."
;
Int128
cross
=
Int128
(
vec1
.
X
)
*
Int128
(
vec2
.
Y
)
-
Int128
cross
=
Int128
(
vec1
.
X
)
*
Int128
(
vec2
.
Y
)
-
Int128
(
vec2
.
X
)
*
Int128
(
vec1
.
Y
);
Int128
(
vec2
.
X
)
*
Int128
(
vec1
.
Y
);
return
cross
>
0
;
return
(
cross
>=
0
)
;
}
}
else
else
return
(
vec1
.
X
*
vec2
.
Y
-
vec2
.
X
*
vec1
.
Y
)
>
0
;
return
(
vec1
.
X
*
vec2
.
Y
-
vec2
.
X
*
vec1
.
Y
)
>
=
0
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -365,7 +366,9 @@ inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2)
...
@@ -365,7 +366,9 @@ inline bool PointsEqual( const IntPoint &pt1, const IntPoint &pt2)
bool
Orientation
(
OutRec
*
outRec
,
bool
UseFullInt64Range
)
bool
Orientation
(
OutRec
*
outRec
,
bool
UseFullInt64Range
)
{
{
//first make sure bottomPt is correctly assigned ...
//first make sure bottomPt is correctly assigned ...
OutPt
*
opBottom
=
outRec
->
pts
,
*
op
=
outRec
->
pts
->
next
;
OutPt
*
opBottom
=
outRec
->
pts
;
if
(
!
opBottom
)
return
true
;
OutPt
*
op
=
outRec
->
pts
->
next
;
while
(
op
!=
outRec
->
pts
)
while
(
op
!=
outRec
->
pts
)
{
{
if
(
op
->
pt
.
Y
>=
opBottom
->
pt
.
Y
)
if
(
op
->
pt
.
Y
>=
opBottom
->
pt
.
Y
)
...
@@ -394,9 +397,9 @@ bool Orientation(OutRec *outRec, bool UseFullInt64Range)
...
@@ -394,9 +397,9 @@ bool Orientation(OutRec *outRec, bool UseFullInt64Range)
ip2
.
Y
=
opNext
->
pt
.
Y
-
op
->
pt
.
Y
;
ip2
.
Y
=
opNext
->
pt
.
Y
-
op
->
pt
.
Y
;
if
(
UseFullInt64Range
)
if
(
UseFullInt64Range
)
return
Int128
(
ip1
.
X
)
*
Int128
(
ip2
.
Y
)
-
Int128
(
ip2
.
X
)
*
Int128
(
ip1
.
Y
)
>
0
;
return
Int128
(
ip1
.
X
)
*
Int128
(
ip2
.
Y
)
-
Int128
(
ip2
.
X
)
*
Int128
(
ip1
.
Y
)
>
=
0
;
else
else
return
(
ip1
.
X
*
ip2
.
Y
-
ip2
.
X
*
ip1
.
Y
)
>
0
;
return
(
ip1
.
X
*
ip2
.
Y
-
ip2
.
X
*
ip1
.
Y
)
>
=
0
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -428,6 +431,7 @@ double Area(const Polygon &poly)
...
@@ -428,6 +431,7 @@ double Area(const Polygon &poly)
double
Area
(
const
OutRec
&
outRec
,
bool
UseFullInt64Range
)
double
Area
(
const
OutRec
&
outRec
,
bool
UseFullInt64Range
)
{
{
OutPt
*
op
=
outRec
.
pts
;
OutPt
*
op
=
outRec
.
pts
;
if
(
!
op
)
return
0
;
if
(
UseFullInt64Range
)
{
if
(
UseFullInt64Range
)
{
Int128
a
(
0
);
Int128
a
(
0
);
do
{
do
{
...
@@ -497,10 +501,9 @@ bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range)
...
@@ -497,10 +501,9 @@ bool PointInPolygon(const IntPoint &pt, OutPt *pp, bool UseFullInt64Range)
bool
SlopesEqual
(
TEdge
&
e1
,
TEdge
&
e2
,
bool
UseFullInt64Range
)
bool
SlopesEqual
(
TEdge
&
e1
,
TEdge
&
e2
,
bool
UseFullInt64Range
)
{
{
if
(
UseFullInt64Range
)
if
(
UseFullInt64Range
)
return
Int128
(
e1
.
ytop
-
e1
.
ybot
)
*
Int128
(
e2
.
xtop
-
e2
.
xbot
)
==
return
Int128
(
e1
.
deltaY
)
*
Int128
(
e2
.
deltaX
)
==
Int128
(
e1
.
xtop
-
e1
.
xbot
)
*
Int128
(
e2
.
ytop
-
e2
.
ybot
);
Int128
(
e1
.
deltaX
)
*
Int128
(
e2
.
deltaY
);
else
return
(
e1
.
ytop
-
e1
.
ybot
)
*
(
e2
.
xtop
-
e2
.
xbot
)
==
else
return
e1
.
deltaY
*
e2
.
deltaX
==
e1
.
deltaX
*
e2
.
deltaY
;
(
e1
.
xtop
-
e1
.
xbot
)
*
(
e2
.
ytop
-
e2
.
ybot
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -533,8 +536,11 @@ double GetDx(const IntPoint pt1, const IntPoint pt2)
...
@@ -533,8 +536,11 @@ double GetDx(const IntPoint pt1, const IntPoint pt2)
void
SetDx
(
TEdge
&
e
)
void
SetDx
(
TEdge
&
e
)
{
{
if
(
e
.
ybot
==
e
.
ytop
)
e
.
dx
=
HORIZONTAL
;
e
.
deltaX
=
(
e
.
xtop
-
e
.
xbot
);
else
e
.
dx
=
(
double
)(
e
.
xtop
-
e
.
xbot
)
/
(
double
)(
e
.
ytop
-
e
.
ybot
);
e
.
deltaY
=
(
e
.
ytop
-
e
.
ybot
);
if
(
e
.
deltaY
==
0
)
e
.
dx
=
HORIZONTAL
;
else
e
.
dx
=
(
double
)(
e
.
deltaX
)
/
(
double
)(
e
.
deltaY
);
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
...
@@ -556,8 +562,7 @@ void SwapPolyIndexes(TEdge &edge1, TEdge &edge2)
...
@@ -556,8 +562,7 @@ void SwapPolyIndexes(TEdge &edge1, TEdge &edge2)
inline
long64
Round
(
double
val
)
inline
long64
Round
(
double
val
)
{
{
return
(
val
<
0
)
?
return
(
val
<
0
)
?
static_cast
<
long64
>
(
val
-
0.5
)
:
static_cast
<
long64
>
(
val
+
0.5
);
static_cast
<
long64
>
(
val
-
0.5
)
:
static_cast
<
long64
>
(
val
+
0.5
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -610,33 +615,48 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
...
@@ -610,33 +615,48 @@ bool IntersectPoint(TEdge &edge1, TEdge &edge2,
b1
=
edge1
.
ybot
-
(
edge1
.
xbot
/
edge1
.
dx
);
b1
=
edge1
.
ybot
-
(
edge1
.
xbot
/
edge1
.
dx
);
ip
.
Y
=
Round
(
ip
.
X
/
edge1
.
dx
+
b1
);
ip
.
Y
=
Round
(
ip
.
X
/
edge1
.
dx
+
b1
);
}
}
}
else
}
else
{
{
b1
=
edge1
.
xbot
-
edge1
.
ybot
*
edge1
.
dx
;
b1
=
edge1
.
xbot
-
edge1
.
ybot
*
edge1
.
dx
;
b2
=
edge2
.
xbot
-
edge2
.
ybot
*
edge2
.
dx
;
b2
=
edge2
.
xbot
-
edge2
.
ybot
*
edge2
.
dx
;
b2
=
(
b2
-
b1
)
/
(
edge1
.
dx
-
edge2
.
dx
);
double
q
=
(
b2
-
b1
)
/
(
edge1
.
dx
-
edge2
.
dx
);
ip
.
Y
=
Round
(
b2
);
ip
.
Y
=
Round
(
q
);
ip
.
X
=
Round
(
edge1
.
dx
*
b2
+
b1
);
if
(
std
::
fabs
(
edge1
.
dx
)
<
std
::
fabs
(
edge2
.
dx
))
ip
.
X
=
Round
(
edge1
.
dx
*
q
+
b1
);
else
ip
.
X
=
Round
(
edge2
.
dx
*
q
+
b2
);
}
}
return
if
(
ip
.
Y
<
edge1
.
ytop
||
ip
.
Y
<
edge2
.
ytop
)
//can be *so close* to the top of one edge that the rounded Y equals one ytop ...
{
(
ip
.
Y
==
edge1
.
ytop
&&
ip
.
Y
>=
edge2
.
ytop
&&
edge1
.
tmpX
>
edge2
.
tmpX
)
||
if
(
edge1
.
ytop
>
edge2
.
ytop
)
(
ip
.
Y
==
edge2
.
ytop
&&
ip
.
Y
>=
edge1
.
ytop
&&
edge1
.
tmpX
>
edge2
.
tmpX
)
||
{
(
ip
.
Y
>
edge1
.
ytop
&&
ip
.
Y
>
edge2
.
ytop
);
ip
.
X
=
edge1
.
xtop
;
ip
.
Y
=
edge1
.
ytop
;
return
TopX
(
edge2
,
edge1
.
ytop
)
<
edge1
.
xtop
;
}
else
{
ip
.
X
=
edge2
.
xtop
;
ip
.
Y
=
edge2
.
ytop
;
return
TopX
(
edge1
,
edge2
.
ytop
)
>
edge2
.
xtop
;
}
}
else
return
true
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ReversePolyPtLinks
(
OutPt
&
pp
)
void
ReversePolyPtLinks
(
OutPt
*
pp
)
{
{
if
(
!
pp
)
return
;
OutPt
*
pp1
,
*
pp2
;
OutPt
*
pp1
,
*
pp2
;
pp1
=
&
pp
;
pp1
=
pp
;
do
{
do
{
pp2
=
pp1
->
next
;
pp2
=
pp1
->
next
;
pp1
->
next
=
pp1
->
prev
;
pp1
->
next
=
pp1
->
prev
;
pp1
->
prev
=
pp2
;
pp1
->
prev
=
pp2
;
pp1
=
pp2
;
pp1
=
pp2
;
}
while
(
pp1
!=
&
pp
);
}
while
(
pp1
!=
pp
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -852,6 +872,7 @@ bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType)
...
@@ -852,6 +872,7 @@ bool ClipperBase::AddPolygon( const Polygon &pg, PolyType polyType)
{
{
int
len
=
(
int
)
pg
.
size
();
int
len
=
(
int
)
pg
.
size
();
if
(
len
<
3
)
return
false
;
if
(
len
<
3
)
return
false
;
Polygon
p
(
len
);
Polygon
p
(
len
);
p
[
0
]
=
pg
[
0
];
p
[
0
]
=
pg
[
0
];
int
j
=
0
;
int
j
=
0
;
...
@@ -1308,14 +1329,11 @@ bool Clipper::ExecuteInternal(bool fixHoleLinkages)
...
@@ -1308,14 +1329,11 @@ bool Clipper::ExecuteInternal(bool fixHoleLinkages)
if
(
outRec
->
bottomPt
==
outRec
->
bottomFlag
&&
if
(
outRec
->
bottomPt
==
outRec
->
bottomFlag
&&
(
Orientation
(
outRec
,
m_UseFullRange
)
!=
(
Area
(
*
outRec
,
m_UseFullRange
)
>
0
)))
(
Orientation
(
outRec
,
m_UseFullRange
)
!=
(
Area
(
*
outRec
,
m_UseFullRange
)
>
0
)))
{
DisposeBottomPt
(
*
outRec
);
DisposeBottomPt
(
*
outRec
);
FixupOutPolygon
(
*
outRec
);
};
if
(
outRec
->
isHole
==
if
(
outRec
->
isHole
==
(
m_ReverseOutput
^
Orientation
(
outRec
,
m_UseFullRange
)))
(
m_ReverseOutput
^
Orientation
(
outRec
,
m_UseFullRange
)))
ReversePolyPtLinks
(
*
outRec
->
pts
);
ReversePolyPtLinks
(
outRec
->
pts
);
}
}
JoinCommonEdges
(
fixHoleLinkages
);
JoinCommonEdges
(
fixHoleLinkages
);
...
@@ -1473,11 +1491,11 @@ bool Clipper::IsContributing(const TEdge& edge) const
...
@@ -1473,11 +1491,11 @@ bool Clipper::IsContributing(const TEdge& edge) const
switch
(
pft
)
switch
(
pft
)
{
{
case
pftEvenOdd
:
case
pftEvenOdd
:
case
pftNonZero
:
case
pftNonZero
:
if
(
Abs
(
edge
.
windCnt
)
!=
1
)
return
false
;
if
(
Abs
(
edge
.
windCnt
)
!=
1
)
return
false
;
break
;
break
;
case
pftPositive
:
case
pftPositive
:
if
(
edge
.
windCnt
!=
1
)
return
false
;
if
(
edge
.
windCnt
!=
1
)
return
false
;
break
;
break
;
default
:
//pftNegative
default
:
//pftNegative
...
@@ -1489,46 +1507,46 @@ bool Clipper::IsContributing(const TEdge& edge) const
...
@@ -1489,46 +1507,46 @@ bool Clipper::IsContributing(const TEdge& edge) const
case
ctIntersection
:
case
ctIntersection
:
switch
(
pft2
)
switch
(
pft2
)
{
{
case
pftEvenOdd
:
case
pftEvenOdd
:
case
pftNonZero
:
case
pftNonZero
:
return
(
edge
.
windCnt2
!=
0
);
return
(
edge
.
windCnt2
!=
0
);
case
pftPositive
:
case
pftPositive
:
return
(
edge
.
windCnt2
>
0
);
return
(
edge
.
windCnt2
>
0
);
default
:
default
:
return
(
edge
.
windCnt2
<
0
);
return
(
edge
.
windCnt2
<
0
);
}
}
case
ctUnion
:
case
ctUnion
:
switch
(
pft2
)
switch
(
pft2
)
{
{
case
pftEvenOdd
:
case
pftEvenOdd
:
case
pftNonZero
:
case
pftNonZero
:
return
(
edge
.
windCnt2
==
0
);
return
(
edge
.
windCnt2
==
0
);
case
pftPositive
:
case
pftPositive
:
return
(
edge
.
windCnt2
<=
0
);
return
(
edge
.
windCnt2
<=
0
);
default
:
default
:
return
(
edge
.
windCnt2
>=
0
);
return
(
edge
.
windCnt2
>=
0
);
}
}
case
ctDifference
:
case
ctDifference
:
if
(
edge
.
polyType
==
ptSubject
)
if
(
edge
.
polyType
==
ptSubject
)
switch
(
pft2
)
switch
(
pft2
)
{
{
case
pftEvenOdd
:
case
pftEvenOdd
:
case
pftNonZero
:
case
pftNonZero
:
return
(
edge
.
windCnt2
==
0
);
return
(
edge
.
windCnt2
==
0
);
case
pftPositive
:
case
pftPositive
:
return
(
edge
.
windCnt2
<=
0
);
return
(
edge
.
windCnt2
<=
0
);
default
:
default
:
return
(
edge
.
windCnt2
>=
0
);
return
(
edge
.
windCnt2
>=
0
);
}
}
else
else
switch
(
pft2
)
switch
(
pft2
)
{
{
case
pftEvenOdd
:
case
pftEvenOdd
:
case
pftNonZero
:
case
pftNonZero
:
return
(
edge
.
windCnt2
!=
0
);
return
(
edge
.
windCnt2
!=
0
);
case
pftPositive
:
case
pftPositive
:
return
(
edge
.
windCnt2
>
0
);
return
(
edge
.
windCnt2
>
0
);
default
:
default
:
return
(
edge
.
windCnt2
<
0
);
return
(
edge
.
windCnt2
<
0
);
}
}
default
:
default
:
...
@@ -1548,7 +1566,7 @@ void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
...
@@ -1548,7 +1566,7 @@ void Clipper::AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
e2
->
side
=
esRight
;
e2
->
side
=
esRight
;
e
=
e1
;
e
=
e1
;
if
(
e
->
prevInAEL
==
e2
)
if
(
e
->
prevInAEL
==
e2
)
prevE
=
e2
->
prevInAEL
;
prevE
=
e2
->
prevInAEL
;
else
else
prevE
=
e
->
prevInAEL
;
prevE
=
e
->
prevInAEL
;
}
else
}
else
...
@@ -1578,9 +1596,9 @@ void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
...
@@ -1578,9 +1596,9 @@ void Clipper::AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt)
e1
->
outIdx
=
-
1
;
e1
->
outIdx
=
-
1
;
e2
->
outIdx
=
-
1
;
e2
->
outIdx
=
-
1
;
}
}
else
if
(
e1
->
outIdx
<
e2
->
outIdx
)
else
if
(
e1
->
outIdx
<
e2
->
outIdx
)
AppendPolygon
(
e1
,
e2
);
AppendPolygon
(
e1
,
e2
);
else
else
AppendPolygon
(
e2
,
e1
);
AppendPolygon
(
e2
,
e1
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1664,7 +1682,7 @@ void Clipper::ClearHorzJoins()
...
@@ -1664,7 +1682,7 @@ void Clipper::ClearHorzJoins()
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
Clipper
::
InsertLocalMinimaIntoAEL
(
const
long64
botY
)
void
Clipper
::
InsertLocalMinimaIntoAEL
(
const
long64
botY
)
{
{
while
(
m_CurrentLM
&&
(
m_CurrentLM
->
Y
==
botY
)
)
while
(
m_CurrentLM
&&
(
m_CurrentLM
->
Y
==
botY
)
)
{
{
...
@@ -1768,7 +1786,7 @@ void Clipper::DeleteFromSEL(TEdge *e)
...
@@ -1768,7 +1786,7 @@ void Clipper::DeleteFromSEL(TEdge *e)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
Clipper
::
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
void
Clipper
::
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
,
IntersectProtects
protects
)
const
IntPoint
&
pt
,
const
IntersectProtects
protects
)
{
{
//e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before
//e1 will be to the left of e2 BELOW the intersection. Therefore e1 is before
//e2 in AEL except when e1 is being inserted at the intersection point ...
//e2 in AEL except when e1 is being inserted at the intersection point ...
...
@@ -1839,28 +1857,28 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -1839,28 +1857,28 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
if
(
e1Contributing
&&
e2contributing
)
if
(
e1Contributing
&&
e2contributing
)
{
{
if
(
e1stops
||
e2stops
||
if
(
e1stops
||
e2stops
||
(
e1Wc
!=
0
&&
e1Wc
!=
1
)
||
(
e2Wc
!=
0
&&
e2Wc
!=
1
)
||
(
e1Wc
!=
0
&&
e1Wc
!=
1
)
||
(
e2Wc
!=
0
&&
e2Wc
!=
1
)
||
(
e1
->
polyType
!=
e2
->
polyType
&&
m_ClipType
!=
ctXor
)
)
(
e1
->
polyType
!=
e2
->
polyType
&&
m_ClipType
!=
ctXor
)
)
AddLocalMaxPoly
(
e1
,
e2
,
pt
);
AddLocalMaxPoly
(
e1
,
e2
,
pt
);
else
else
DoBothEdges
(
e1
,
e2
,
pt
);
DoBothEdges
(
e1
,
e2
,
pt
);
}
}
else
if
(
e1Contributing
)
else
if
(
e1Contributing
)
{
{
if
((
e2Wc
==
0
||
e2Wc
==
1
)
&&
if
((
e2Wc
==
0
||
e2Wc
==
1
)
&&
(
m_ClipType
!=
ctIntersection
||
(
m_ClipType
!=
ctIntersection
||
e2
->
polyType
==
ptSubject
||
(
e2
->
windCnt2
!=
0
)))
e2
->
polyType
==
ptSubject
||
(
e2
->
windCnt2
!=
0
)))
DoEdge1
(
e1
,
e2
,
pt
);
DoEdge1
(
e1
,
e2
,
pt
);
}
}
else
if
(
e2contributing
)
else
if
(
e2contributing
)
{
{
if
((
e1Wc
==
0
||
e1Wc
==
1
)
&&
if
((
e1Wc
==
0
||
e1Wc
==
1
)
&&
(
m_ClipType
!=
ctIntersection
||
(
m_ClipType
!=
ctIntersection
||
e1
->
polyType
==
ptSubject
||
(
e1
->
windCnt2
!=
0
)))
e1
->
polyType
==
ptSubject
||
(
e1
->
windCnt2
!=
0
)))
DoEdge2
(
e1
,
e2
,
pt
);
DoEdge2
(
e1
,
e2
,
pt
);
}
}
else
if
(
(
e1Wc
==
0
||
e1Wc
==
1
)
&&
else
if
(
(
e1Wc
==
0
||
e1Wc
==
1
)
&&
(
e2Wc
==
0
||
e2Wc
==
1
)
&&
!
e1stops
&&
!
e2stops
)
(
e2Wc
==
0
||
e2Wc
==
1
)
&&
!
e1stops
&&
!
e2stops
)
{
{
//neither edge is currently contributing ...
//neither edge is currently contributing ...
...
@@ -1950,6 +1968,17 @@ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
...
@@ -1950,6 +1968,17 @@ OutRec* GetLowermostRec(OutRec *outRec1, OutRec *outRec2)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
Param1RightOfParam2
(
OutRec
*
outRec1
,
OutRec
*
outRec2
)
{
do
{
outRec1
=
outRec1
->
FirstLeft
;
if
(
outRec1
==
outRec2
)
return
true
;
}
while
(
outRec1
);
return
false
;
}
//------------------------------------------------------------------------------
void
Clipper
::
AppendPolygon
(
TEdge
*
e1
,
TEdge
*
e2
)
void
Clipper
::
AppendPolygon
(
TEdge
*
e1
,
TEdge
*
e2
)
{
{
//get the start and ends of both output polygons ...
//get the start and ends of both output polygons ...
...
@@ -1957,8 +1986,8 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
...
@@ -1957,8 +1986,8 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
OutRec
*
outRec2
=
m_PolyOuts
[
e2
->
outIdx
];
OutRec
*
outRec2
=
m_PolyOuts
[
e2
->
outIdx
];
OutRec
*
holeStateRec
;
OutRec
*
holeStateRec
;
if
(
outRec1
->
FirstLeft
==
outRec2
)
holeStateRec
=
outRec2
;
if
(
Param1RightOfParam2
(
outRec1
,
outRec2
)
)
holeStateRec
=
outRec2
;
else
if
(
outRec2
->
FirstLeft
==
outRec1
)
holeStateRec
=
outRec1
;
else
if
(
Param1RightOfParam2
(
outRec2
,
outRec1
)
)
holeStateRec
=
outRec1
;
else
holeStateRec
=
GetLowermostRec
(
outRec1
,
outRec2
);
else
holeStateRec
=
GetLowermostRec
(
outRec1
,
outRec2
);
OutPt
*
p1_lft
=
outRec1
->
pts
;
OutPt
*
p1_lft
=
outRec1
->
pts
;
...
@@ -1973,7 +2002,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
...
@@ -1973,7 +2002,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
if
(
e2
->
side
==
esLeft
)
if
(
e2
->
side
==
esLeft
)
{
{
//z y x a b c
//z y x a b c
ReversePolyPtLinks
(
*
p2_lft
);
ReversePolyPtLinks
(
p2_lft
);
p2_lft
->
next
=
p1_lft
;
p2_lft
->
next
=
p1_lft
;
p1_lft
->
prev
=
p2_lft
;
p1_lft
->
prev
=
p2_lft
;
p1_rt
->
next
=
p2_rt
;
p1_rt
->
next
=
p2_rt
;
...
@@ -1994,7 +2023,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
...
@@ -1994,7 +2023,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
if
(
e2
->
side
==
esRight
)
if
(
e2
->
side
==
esRight
)
{
{
//a b c z y x
//a b c z y x
ReversePolyPtLinks
(
*
p2_lft
);
ReversePolyPtLinks
(
p2_lft
);
p1_rt
->
next
=
p2_rt
;
p1_rt
->
next
=
p2_rt
;
p2_rt
->
prev
=
p1_rt
;
p2_rt
->
prev
=
p1_rt
;
p2_lft
->
next
=
p1_lft
;
p2_lft
->
next
=
p1_lft
;
...
@@ -2078,6 +2107,7 @@ void Clipper::DisposeBottomPt(OutRec &outRec)
...
@@ -2078,6 +2107,7 @@ void Clipper::DisposeBottomPt(OutRec &outRec)
next
->
prev
=
prev
;
next
->
prev
=
prev
;
prev
->
next
=
next
;
prev
->
next
=
next
;
outRec
.
bottomPt
=
next
;
outRec
.
bottomPt
=
next
;
FixupOutPolygon
(
outRec
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -2116,7 +2146,6 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
...
@@ -2116,7 +2146,6 @@ void Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
}
}
else
if
(
pt
.
X
==
op
->
pt
.
X
-
1
)
return
;
//ie wrong side of bottomPt
else
if
(
pt
.
X
==
op
->
pt
.
X
-
1
)
return
;
//ie wrong side of bottomPt
}
}
outRec
->
sides
=
(
EdgeSide
)(
outRec
->
sides
|
e
->
side
);
outRec
->
sides
=
(
EdgeSide
)(
outRec
->
sides
|
e
->
side
);
if
(
outRec
->
sides
==
esBoth
)
if
(
outRec
->
sides
==
esBoth
)
{
{
...
@@ -2522,7 +2551,7 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
...
@@ -2522,7 +2551,7 @@ void Clipper::BuildIntersectList(const long64 botY, const long64 topY)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
Process
1Before2
(
IntersectNode
&
node1
,
IntersectNode
&
node2
)
bool
Process
Param1BeforeParam2
(
const
IntersectNode
&
node1
,
const
IntersectNode
&
node2
)
{
{
bool
result
;
bool
result
;
if
(
node1
.
pt
.
Y
==
node2
.
pt
.
Y
)
if
(
node1
.
pt
.
Y
==
node2
.
pt
.
Y
)
...
@@ -2551,7 +2580,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
...
@@ -2551,7 +2580,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
newNode
->
pt
=
pt
;
newNode
->
pt
=
pt
;
newNode
->
next
=
0
;
newNode
->
next
=
0
;
if
(
!
m_IntersectNodes
)
m_IntersectNodes
=
newNode
;
if
(
!
m_IntersectNodes
)
m_IntersectNodes
=
newNode
;
else
if
(
Process
1Before
2
(
*
newNode
,
*
m_IntersectNodes
)
)
else
if
(
Process
Param1BeforeParam
2
(
*
newNode
,
*
m_IntersectNodes
)
)
{
{
newNode
->
next
=
m_IntersectNodes
;
newNode
->
next
=
m_IntersectNodes
;
m_IntersectNodes
=
newNode
;
m_IntersectNodes
=
newNode
;
...
@@ -2559,7 +2588,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
...
@@ -2559,7 +2588,7 @@ void Clipper::AddIntersectNode(TEdge *e1, TEdge *e2, const IntPoint &pt)
else
else
{
{
IntersectNode
*
iNode
=
m_IntersectNodes
;
IntersectNode
*
iNode
=
m_IntersectNodes
;
while
(
iNode
->
next
&&
Process
1Before
2
(
*
iNode
->
next
,
*
newNode
)
)
while
(
iNode
->
next
&&
Process
Param1BeforeParam
2
(
*
iNode
->
next
,
*
newNode
)
)
iNode
=
iNode
->
next
;
iNode
=
iNode
->
next
;
newNode
->
next
=
iNode
->
next
;
newNode
->
next
=
iNode
->
next
;
iNode
->
next
=
newNode
;
iNode
->
next
=
newNode
;
...
@@ -2617,10 +2646,10 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
...
@@ -2617,10 +2646,10 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
if
(
IsMaxima
(
e
,
topY
)
&&
!
NEAR_EQUAL
(
GetMaximaPair
(
e
)
->
dx
,
HORIZONTAL
)
)
if
(
IsMaxima
(
e
,
topY
)
&&
!
NEAR_EQUAL
(
GetMaximaPair
(
e
)
->
dx
,
HORIZONTAL
)
)
{
{
//'e' might be removed from AEL, as may any following edges so ...
//'e' might be removed from AEL, as may any following edges so ...
TEdge
*
ePr
ior
=
e
->
prevInAEL
;
TEdge
*
ePr
ev
=
e
->
prevInAEL
;
DoMaxima
(
e
,
topY
);
DoMaxima
(
e
,
topY
);
if
(
!
ePr
ior
)
e
=
m_ActiveEdges
;
if
(
!
ePr
ev
)
e
=
m_ActiveEdges
;
else
e
=
ePr
ior
->
nextInAEL
;
else
e
=
ePr
ev
->
nextInAEL
;
}
}
else
else
{
{
...
@@ -2669,25 +2698,23 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
...
@@ -2669,25 +2698,23 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const long64 topY)
UpdateEdgeIntoAEL
(
e
);
UpdateEdgeIntoAEL
(
e
);
//if output polygons share an edge, they'll need joining later ...
//if output polygons share an edge, they'll need joining later ...
if
(
e
->
outIdx
>=
0
&&
e
->
prevInAEL
&&
e
->
prevInAEL
->
outIdx
>=
0
&&
TEdge
*
ePrev
=
e
->
prevInAEL
;
e
->
prevInAEL
->
xcurr
==
e
->
xbot
&&
e
->
prevInAEL
->
ycurr
==
e
->
ybot
&&
TEdge
*
eNext
=
e
->
nextInAEL
;
SlopesEqual
(
IntPoint
(
e
->
xbot
,
e
->
ybot
),
IntPoint
(
e
->
xtop
,
e
->
ytop
),
if
(
ePrev
&&
ePrev
->
xcurr
==
e
->
xbot
&&
IntPoint
(
e
->
xbot
,
e
->
ybot
),
ePrev
->
ycurr
==
e
->
ybot
&&
e
->
outIdx
>=
0
&&
IntPoint
(
e
->
prevInAEL
->
xtop
,
e
->
prevInAEL
->
ytop
),
m_UseFullRange
))
ePrev
->
outIdx
>=
0
&&
ePrev
->
ycurr
>
ePrev
->
ytop
&&
SlopesEqual
(
*
e
,
*
ePrev
,
m_UseFullRange
))
{
{
AddOutPt
(
e
->
prevInAEL
,
IntPoint
(
e
->
xbot
,
e
->
ybot
));
AddOutPt
(
e
Prev
,
IntPoint
(
e
->
xbot
,
e
->
ybot
));
AddJoin
(
e
,
e
->
prevInAEL
);
AddJoin
(
e
,
e
Prev
);
}
}
else
if
(
e
->
outIdx
>=
0
&&
e
->
nextInAEL
&&
e
->
nextInAEL
->
outIdx
>=
0
&&
else
if
(
eNext
&&
eNext
->
xcurr
==
e
->
xbot
&&
e
->
nextInAEL
->
ycurr
>
e
->
nextInAEL
->
ytop
&&
eNext
->
ycurr
==
e
->
ybot
&&
e
->
outIdx
>=
0
&&
e
->
nextInAEL
->
ycurr
<=
e
->
nextInAEL
->
ybot
&&
eNext
->
outIdx
>=
0
&&
eNext
->
ycurr
>
eNext
->
ytop
&&
e
->
nextInAEL
->
xcurr
==
e
->
xbot
&&
e
->
nextInAEL
->
ycurr
==
e
->
ybot
&&
SlopesEqual
(
*
e
,
*
eNext
,
m_UseFullRange
))
SlopesEqual
(
IntPoint
(
e
->
xbot
,
e
->
ybot
),
IntPoint
(
e
->
xtop
,
e
->
ytop
),
IntPoint
(
e
->
xbot
,
e
->
ybot
),
IntPoint
(
e
->
nextInAEL
->
xtop
,
e
->
nextInAEL
->
ytop
),
m_UseFullRange
))
{
{
AddOutPt
(
e
->
nextInAEL
,
IntPoint
(
e
->
xbot
,
e
->
ybot
));
AddOutPt
(
e
Next
,
IntPoint
(
e
->
xbot
,
e
->
ybot
));
AddJoin
(
e
,
e
->
nextInAEL
);
AddJoin
(
e
,
e
Next
);
}
}
}
}
e
=
e
->
nextInAEL
;
e
=
e
->
nextInAEL
;
...
@@ -2916,55 +2943,28 @@ void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt)
...
@@ -2916,55 +2943,28 @@ void Clipper::DoBothEdges(TEdge *edge1, TEdge *edge2, const IntPoint &pt)
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
Clipper
::
CheckHoleLinkages1
(
OutRec
*
outRec1
,
OutRec
*
outRec
2
)
bool
Clipper
::
JoinPoints
(
const
JoinRec
*
j
,
OutPt
*&
p1
,
OutPt
*&
p
2
)
{
{
//when a polygon is split into 2 polygons, make sure any holes the original
//polygon contained link to the correct polygon ...
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
{
OutRec
*
orec
=
m_PolyOuts
[
i
];
if
(
orec
->
isHole
&&
orec
->
bottomPt
&&
orec
->
FirstLeft
==
outRec1
&&
!
PointInPolygon
(
orec
->
bottomPt
->
pt
,
outRec1
->
pts
,
m_UseFullRange
))
orec
->
FirstLeft
=
outRec2
;
}
}
//----------------------------------------------------------------------
void
Clipper
::
CheckHoleLinkages2
(
OutRec
*
outRec1
,
OutRec
*
outRec2
)
{
//if a hole is owned by outRec2 then make it owned by outRec1 ...
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
if
(
m_PolyOuts
[
i
]
->
isHole
&&
m_PolyOuts
[
i
]
->
bottomPt
&&
m_PolyOuts
[
i
]
->
FirstLeft
==
outRec2
)
m_PolyOuts
[
i
]
->
FirstLeft
=
outRec1
;
}
//----------------------------------------------------------------------
void
Clipper
::
JoinCommonEdges
(
bool
fixHoleLinkages
)
{
for
(
JoinList
::
size_type
i
=
0
;
i
<
m_Joins
.
size
();
i
++
)
{
JoinRec
*
j
=
m_Joins
[
i
];
OutRec
*
outRec1
=
m_PolyOuts
[
j
->
poly1Idx
];
OutRec
*
outRec1
=
m_PolyOuts
[
j
->
poly1Idx
];
OutPt
*
pp1a
=
outRec1
->
pts
;
OutRec
*
outRec2
=
m_PolyOuts
[
j
->
poly2Idx
];
OutRec
*
outRec2
=
m_PolyOuts
[
j
->
poly2Idx
];
if
(
!
outRec1
||
!
outRec2
)
return
false
;
OutPt
*
pp1a
=
outRec1
->
pts
;
OutPt
*
pp2a
=
outRec2
->
pts
;
OutPt
*
pp2a
=
outRec2
->
pts
;
IntPoint
pt1
=
j
->
pt2a
,
pt2
=
j
->
pt2b
;
IntPoint
pt1
=
j
->
pt2a
,
pt2
=
j
->
pt2b
;
IntPoint
pt3
=
j
->
pt1a
,
pt4
=
j
->
pt1b
;
IntPoint
pt3
=
j
->
pt1a
,
pt4
=
j
->
pt1b
;
if
(
!
FindSegment
(
pp1a
,
pt1
,
pt2
))
continu
e
;
if
(
!
FindSegment
(
pp1a
,
pt1
,
pt2
))
return
fals
e
;
if
(
j
->
poly1Idx
==
j
->
poly2Idx
)
if
(
outRec1
==
outRec2
)
{
{
//we're searching the same polygon for overlapping segments so
//we're searching the same polygon for overlapping segments so
//segment 2 mustn't be the same as segment 1 ...
//segment 2 mustn't be the same as segment 1 ...
pp2a
=
pp1a
->
next
;
pp2a
=
pp1a
->
next
;
if
(
!
FindSegment
(
pp2a
,
pt3
,
pt4
)
||
(
pp2a
==
pp1a
))
continu
e
;
if
(
!
FindSegment
(
pp2a
,
pt3
,
pt4
)
||
(
pp2a
==
pp1a
))
return
fals
e
;
}
}
else
if
(
!
FindSegment
(
pp2a
,
pt3
,
pt4
))
continu
e
;
else
if
(
!
FindSegment
(
pp2a
,
pt3
,
pt4
))
return
fals
e
;
if
(
!
GetOverlapSegment
(
pt1
,
pt2
,
pt3
,
pt4
,
pt1
,
pt2
))
continu
e
;
if
(
!
GetOverlapSegment
(
pt1
,
pt2
,
pt3
,
pt4
,
pt1
,
pt2
))
return
fals
e
;
OutPt
*
p1
,
*
p2
,
*
p3
,
*
p4
;
OutPt
*
p3
,
*
p4
,
*
prev
=
pp1a
->
prev
;
OutPt
*
prev
=
pp1a
->
prev
;
//get p1 & p2 polypts - the overlap start & endpoints on poly1
//get p1 & p2 polypts - the overlap start & endpoints on poly1
if
(
PointsEqual
(
pp1a
->
pt
,
pt1
))
p1
=
pp1a
;
if
(
PointsEqual
(
pp1a
->
pt
,
pt1
))
p1
=
pp1a
;
else
if
(
PointsEqual
(
prev
->
pt
,
pt1
))
p1
=
prev
;
else
if
(
PointsEqual
(
prev
->
pt
,
pt1
))
p1
=
prev
;
...
@@ -2999,6 +2999,7 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
...
@@ -2999,6 +2999,7 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
p3
->
prev
=
p1
;
p3
->
prev
=
p1
;
p2
->
prev
=
p4
;
p2
->
prev
=
p4
;
p4
->
next
=
p2
;
p4
->
next
=
p2
;
return
true
;
}
}
else
if
(
p1
->
prev
==
p2
&&
p3
->
next
==
p4
)
else
if
(
p1
->
prev
==
p2
&&
p3
->
next
==
p4
)
{
{
...
@@ -3006,11 +3007,38 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
...
@@ -3006,11 +3007,38 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
p3
->
next
=
p1
;
p3
->
next
=
p1
;
p2
->
next
=
p4
;
p2
->
next
=
p4
;
p4
->
prev
=
p2
;
p4
->
prev
=
p2
;
return
true
;
}
}
else
else
continue
;
//an orientation is probably wrong
return
false
;
//an orientation is probably wrong
}
//----------------------------------------------------------------------
if
(
j
->
poly2Idx
==
j
->
poly1Idx
)
void
Clipper
::
FixupJoinRecs
(
JoinRec
*
j
,
OutPt
*
pt
,
unsigned
startIdx
)
{
for
(
JoinList
::
size_type
k
=
startIdx
;
k
<
m_Joins
.
size
();
k
++
)
{
JoinRec
*
j2
=
m_Joins
[
k
];
if
(
j2
->
poly1Idx
==
j
->
poly1Idx
&&
PointIsVertex
(
j2
->
pt1a
,
pt
))
j2
->
poly1Idx
=
j
->
poly2Idx
;
if
(
j2
->
poly2Idx
==
j
->
poly1Idx
&&
PointIsVertex
(
j2
->
pt2a
,
pt
))
j2
->
poly2Idx
=
j
->
poly2Idx
;
}
}
//----------------------------------------------------------------------
void
Clipper
::
JoinCommonEdges
(
bool
fixHoleLinkages
)
{
for
(
JoinList
::
size_type
i
=
0
;
i
<
m_Joins
.
size
();
i
++
)
{
JoinRec
*
j
=
m_Joins
[
i
];
OutPt
*
p1
,
*
p2
;
if
(
!
JoinPoints
(
j
,
p1
,
p2
))
return
;
OutRec
*
outRec1
=
m_PolyOuts
[
j
->
poly1Idx
];
OutRec
*
outRec2
=
m_PolyOuts
[
j
->
poly2Idx
];
if
(
outRec1
==
outRec2
)
{
{
//instead of joining two polygons, we've just created a new one by
//instead of joining two polygons, we've just created a new one by
//splitting one polygon into two.
//splitting one polygon into two.
...
@@ -3030,8 +3058,15 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
...
@@ -3030,8 +3058,15 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
//outRec2 is contained by outRec1 ...
//outRec2 is contained by outRec1 ...
outRec2
->
isHole
=
!
outRec1
->
isHole
;
outRec2
->
isHole
=
!
outRec1
->
isHole
;
outRec2
->
FirstLeft
=
outRec1
;
outRec2
->
FirstLeft
=
outRec1
;
if
(
outRec2
->
isHole
==
Orientation
(
outRec2
,
m_UseFullRange
))
ReversePolyPtLinks
(
*
outRec2
->
pts
);
FixupJoinRecs
(
j
,
p2
,
i
+
1
);
FixupOutPolygon
(
*
outRec1
);
//nb: do this BEFORE testing orientation
FixupOutPolygon
(
*
outRec2
);
// but AFTER calling FixupJoinRecs()
if
(
outRec2
->
pts
&&
outRec2
->
isHole
==
(
m_ReverseOutput
^
Orientation
(
outRec2
,
m_UseFullRange
)))
ReversePolyPtLinks
(
outRec2
->
pts
);
}
else
if
(
PointInPolygon
(
outRec1
->
pts
->
pt
,
outRec2
->
pts
,
m_UseFullRange
))
}
else
if
(
PointInPolygon
(
outRec1
->
pts
->
pt
,
outRec2
->
pts
,
m_UseFullRange
))
{
{
//outRec1 is contained by outRec2 ...
//outRec1 is contained by outRec2 ...
...
@@ -3039,39 +3074,61 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
...
@@ -3039,39 +3074,61 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
outRec1
->
isHole
=
!
outRec2
->
isHole
;
outRec1
->
isHole
=
!
outRec2
->
isHole
;
outRec2
->
FirstLeft
=
outRec1
->
FirstLeft
;
outRec2
->
FirstLeft
=
outRec1
->
FirstLeft
;
outRec1
->
FirstLeft
=
outRec2
;
outRec1
->
FirstLeft
=
outRec2
;
if
(
outRec1
->
isHole
==
Orientation
(
outRec1
,
m_UseFullRange
))
ReversePolyPtLinks
(
*
outRec1
->
pts
);
FixupJoinRecs
(
j
,
p2
,
i
+
1
);
FixupOutPolygon
(
*
outRec1
);
//nb: do this BEFORE testing orientation
FixupOutPolygon
(
*
outRec2
);
// but AFTER calling FixupJoinRecs()
if
(
outRec1
->
isHole
==
(
m_ReverseOutput
^
Orientation
(
outRec1
,
m_UseFullRange
)))
ReversePolyPtLinks
(
outRec1
->
pts
);
//make sure any contained holes now link to the correct polygon ...
//make sure any contained holes now link to the correct polygon ...
if
(
fixHoleLinkages
)
CheckHoleLinkages1
(
outRec1
,
outRec2
);
if
(
fixHoleLinkages
&&
outRec1
->
isHole
)
}
else
for
(
PolyOutList
::
size_type
k
=
0
;
k
<
m_PolyOuts
.
size
();
++
k
)
{
OutRec
*
orec
=
m_PolyOuts
[
k
];
if
(
orec
->
isHole
&&
orec
->
bottomPt
&&
orec
->
FirstLeft
==
outRec1
)
orec
->
FirstLeft
=
outRec2
;
}
}
else
{
{
//the 2 polygons are completely separate ...
outRec2
->
isHole
=
outRec1
->
isHole
;
outRec2
->
isHole
=
outRec1
->
isHole
;
outRec2
->
FirstLeft
=
outRec1
->
FirstLeft
;
outRec2
->
FirstLeft
=
outRec1
->
FirstLeft
;
//make sure any contained holes now link to the correct polygon ...
if
(
fixHoleLinkages
)
CheckHoleLinkages1
(
outRec1
,
outRec2
);
}
//now fixup any subsequent joins that match this polygon
FixupJoinRecs
(
j
,
p2
,
i
+
1
);
for
(
JoinList
::
size_type
k
=
i
+
1
;
k
<
m_Joins
.
size
();
k
++
)
FixupOutPolygon
(
*
outRec1
);
//nb: do this BEFORE testing orientation
{
FixupOutPolygon
(
*
outRec2
);
// but AFTER calling FixupJoinRecs()
JoinRec
*
j2
=
m_Joins
[
k
];
if
(
j2
->
poly1Idx
==
j
->
poly1Idx
&&
PointIsVertex
(
j2
->
pt1a
,
p2
))
if
(
fixHoleLinkages
&&
outRec2
->
pts
)
j2
->
poly1Idx
=
j
->
poly2Idx
;
for
(
PolyOutList
::
size_type
k
=
0
;
k
<
m_PolyOuts
.
size
();
++
k
)
if
(
j2
->
poly2Idx
==
j
->
poly1Idx
&&
PointIsVertex
(
j2
->
pt2a
,
p2
))
{
j2
->
poly2Idx
=
j
->
poly2Idx
;
OutRec
*
orec
=
m_PolyOuts
[
k
];
if
(
orec
->
isHole
&&
orec
->
bottomPt
&&
orec
->
FirstLeft
==
outRec1
&&
PointInPolygon
(
orec
->
bottomPt
->
pt
,
outRec2
->
pts
,
m_UseFullRange
))
orec
->
FirstLeft
=
outRec2
;
}
}
}
if
(
Orientation
(
outRec1
,
m_UseFullRange
)
!=
(
Area
(
*
outRec1
,
m_UseFullRange
)
>=
0
))
DisposeBottomPt
(
*
outRec1
);
if
(
Orientation
(
outRec2
,
m_UseFullRange
)
!=
(
Area
(
*
outRec2
,
m_UseFullRange
)
>=
0
))
DisposeBottomPt
(
*
outRec2
);
//now cleanup redundant edges too ...
FixupOutPolygon
(
*
outRec1
);
FixupOutPolygon
(
*
outRec2
);
}
else
}
else
{
{
//joined 2 polygons together ...
//joined 2 polygons together ...
//make sure any holes contained by outRec2 now link to outRec1 ...
//make sure any holes contained by outRec2 now link to outRec1 ...
if
(
fixHoleLinkages
)
CheckHoleLinkages2
(
outRec1
,
outRec2
);
if
(
fixHoleLinkages
)
for
(
PolyOutList
::
size_type
k
=
0
;
k
<
m_PolyOuts
.
size
();
++
k
)
if
(
m_PolyOuts
[
k
]
->
isHole
&&
m_PolyOuts
[
k
]
->
bottomPt
&&
m_PolyOuts
[
k
]
->
FirstLeft
==
outRec2
)
m_PolyOuts
[
k
]
->
FirstLeft
=
outRec1
;
//
now
cleanup redundant edges too ...
//
and
cleanup redundant edges too ...
FixupOutPolygon
(
*
outRec1
);
FixupOutPolygon
(
*
outRec1
);
if
(
outRec1
->
pts
)
if
(
outRec1
->
pts
)
...
@@ -3100,16 +3157,16 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
...
@@ -3100,16 +3157,16 @@ void Clipper::JoinCommonEdges(bool fixHoleLinkages)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ReversePo
ints
(
Polygon
&
p
)
void
ReversePo
lygon
(
Polygon
&
p
)
{
{
std
::
reverse
(
p
.
begin
(),
p
.
end
());
std
::
reverse
(
p
.
begin
(),
p
.
end
());
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ReversePo
int
s
(
Polygons
&
p
)
void
ReversePo
lygon
s
(
Polygons
&
p
)
{
{
for
(
Polygons
::
size_type
i
=
0
;
i
<
p
.
size
();
++
i
)
for
(
Polygons
::
size_type
i
=
0
;
i
<
p
.
size
();
++
i
)
ReversePo
ints
(
p
[
i
]);
ReversePo
lygon
(
p
[
i
]);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -3143,9 +3200,9 @@ Polygon BuildArc(const IntPoint &pt,
...
@@ -3143,9 +3200,9 @@ Polygon BuildArc(const IntPoint &pt,
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DoublePoint
GetUnitNormal
(
const
IntPoint
&
pt1
,
const
IntPoint
&
pt2
)
DoublePoint
GetUnitNormal
(
const
IntPoint
&
pt1
,
const
IntPoint
&
pt2
)
{
{
if
(
pt2
.
X
==
pt1
.
X
&&
pt2
.
Y
==
pt1
.
Y
)
if
(
pt2
.
X
==
pt1
.
X
&&
pt2
.
Y
==
pt1
.
Y
)
return
DoublePoint
(
0
,
0
);
return
DoublePoint
(
0
,
0
);
double
dx
=
(
double
)(
pt2
.
X
-
pt1
.
X
);
double
dx
=
(
double
)(
pt2
.
X
-
pt1
.
X
);
...
@@ -3169,11 +3226,11 @@ private:
...
@@ -3169,11 +3226,11 @@ private:
size_t
m_i
,
m_j
,
m_k
;
size_t
m_i
,
m_j
,
m_k
;
static
const
int
buffLength
=
128
;
static
const
int
buffLength
=
128
;
JoinType
m_jointype
;
JoinType
m_jointype
;
public
:
public
:
PolyOffsetBuilder
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
PolyOffsetBuilder
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
double
delta
,
JoinType
jointype
,
double
MiterLimit
)
double
delta
,
JoinType
jointype
,
double
MiterLimit
,
bool
CheckInputs
)
{
{
//nb precondition - out_polys != ptsin_polys
//nb precondition - out_polys != ptsin_polys
if
(
NEAR_ZERO
(
delta
))
if
(
NEAR_ZERO
(
delta
))
...
@@ -3185,22 +3242,57 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
...
@@ -3185,22 +3242,57 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
this
->
m_p
=
in_polys
;
this
->
m_p
=
in_polys
;
this
->
m_delta
=
delta
;
this
->
m_delta
=
delta
;
this
->
m_jointype
=
jointype
;
this
->
m_jointype
=
jointype
;
//ChecksInput - fixes polygon orientation if necessary and removes
//duplicate vertices. Can be set false when you're sure that polygon
//orientation is correct and that there are no duplicate vertices.
if
(
CheckInputs
)
{
size_t
Len
=
m_p
.
size
(),
botI
=
0
;
while
(
botI
<
Len
&&
m_p
[
botI
].
size
()
==
0
)
botI
++
;
if
(
botI
==
Len
)
return
;
//botPt: used to find the lowermost (in inverted Y-axis) & leftmost point
//This point (on m_p[botI]) must be on an outer polygon ring and if
//its orientation is false (counterclockwise) then assume all polygons
//need reversing ...
IntPoint
botPt
=
m_p
[
botI
][
0
];
for
(
size_t
i
=
botI
;
i
<
Len
;
++
i
)
{
if
(
m_p
[
i
].
size
()
<
3
)
continue
;
if
(
UpdateBotPt
(
m_p
[
i
][
0
],
botPt
))
botI
=
i
;
Polygon
::
iterator
it
=
m_p
[
i
].
begin
()
+
1
;
while
(
it
!=
m_p
[
i
].
end
())
{
if
(
PointsEqual
(
*
it
,
*
(
it
-
1
)))
it
=
m_p
[
i
].
erase
(
it
);
else
{
if
(
UpdateBotPt
(
*
it
,
botPt
))
botI
=
i
;
++
it
;
}
}
}
if
(
!
Orientation
(
m_p
[
botI
]))
ReversePolygons
(
m_p
);
}
if
(
MiterLimit
<=
1
)
MiterLimit
=
1
;
if
(
MiterLimit
<=
1
)
MiterLimit
=
1
;
m_RMin
=
2
/
(
MiterLimit
*
MiterLimit
);
m_RMin
=
2
/
(
MiterLimit
*
MiterLimit
);
double
deltaSq
=
delta
*
delta
;
double
deltaSq
=
delta
*
delta
;
out_polys
.
clear
();
out_polys
.
clear
();
out_polys
.
resize
(
in_polys
.
size
());
out_polys
.
resize
(
m_p
.
size
());
for
(
m_i
=
0
;
m_i
<
in_polys
.
size
();
m_i
++
)
for
(
m_i
=
0
;
m_i
<
m_p
.
size
();
m_i
++
)
{
{
m_curr_poly
=
&
out_polys
[
m_i
];
m_curr_poly
=
&
out_polys
[
m_i
];
size_t
len
=
in_polys
[
m_i
].
size
();
size_t
len
=
m_p
[
m_i
].
size
();
if
(
len
>
1
&&
m_p
[
m_i
][
0
].
X
==
m_p
[
m_i
][
len
-
1
].
X
&&
if
(
len
>
1
&&
m_p
[
m_i
][
0
].
X
==
m_p
[
m_i
][
len
-
1
].
X
&&
m_p
[
m_i
][
0
].
Y
==
m_p
[
m_i
][
len
-
1
].
Y
)
len
--
;
m_p
[
m_i
][
0
].
Y
==
m_p
[
m_i
][
len
-
1
].
Y
)
len
--
;
//when 'shrinking' polygons - to minimize artefacts
//when 'shrinking' polygons - to minimize artefacts
//strip those polygons that have an area < pi * delta^2 ...
//strip those polygons that have an area < pi * delta^2 ...
double
a1
=
Area
(
in_polys
[
m_i
]);
double
a1
=
Area
(
m_p
[
m_i
]);
if
(
delta
<
0
)
{
if
(
a1
>
0
&&
a1
<
deltaSq
*
pi
)
len
=
0
;
}
if
(
delta
<
0
)
{
if
(
a1
>
0
&&
a1
<
deltaSq
*
pi
)
len
=
0
;
}
else
if
(
a1
<
0
&&
-
a1
<
deltaSq
*
pi
)
len
=
0
;
//holes have neg. area
else
if
(
a1
<
0
&&
-
a1
<
deltaSq
*
pi
)
len
=
0
;
//holes have neg. area
...
@@ -3209,7 +3301,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
...
@@ -3209,7 +3301,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
else
if
(
len
==
1
)
else
if
(
len
==
1
)
{
{
Polygon
arc
;
Polygon
arc
;
arc
=
BuildArc
(
in_polys
[
m_i
][
len
-
1
],
0
,
2
*
pi
,
delta
);
arc
=
BuildArc
(
m_p
[
m_i
][
len
-
1
],
0
,
2
*
pi
,
delta
);
out_polys
[
m_i
]
=
arc
;
out_polys
[
m_i
]
=
arc
;
continue
;
continue
;
}
}
...
@@ -3217,10 +3309,10 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
...
@@ -3217,10 +3309,10 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
//build normals ...
//build normals ...
normals
.
clear
();
normals
.
clear
();
normals
.
resize
(
len
);
normals
.
resize
(
len
);
normals
[
len
-
1
]
=
GetUnitNormal
(
in_polys
[
m_i
][
len
-
1
],
in_polys
[
m_i
][
0
]);
normals
[
len
-
1
]
=
GetUnitNormal
(
m_p
[
m_i
][
len
-
1
],
m_p
[
m_i
][
0
]);
for
(
m_j
=
0
;
m_j
<
len
-
1
;
++
m_j
)
for
(
m_j
=
0
;
m_j
<
len
-
1
;
++
m_j
)
normals
[
m_j
]
=
GetUnitNormal
(
in_polys
[
m_i
][
m_j
],
in_polys
[
m_i
][
m_j
+
1
]);
normals
[
m_j
]
=
GetUnitNormal
(
m_p
[
m_i
][
m_j
],
m_p
[
m_i
][
m_j
+
1
]);
m_k
=
len
-
1
;
m_k
=
len
-
1
;
for
(
m_j
=
0
;
m_j
<
len
;
++
m_j
)
for
(
m_j
=
0
;
m_j
<
len
;
++
m_j
)
{
{
...
@@ -3228,7 +3320,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
...
@@ -3228,7 +3320,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
{
{
case
jtMiter
:
case
jtMiter
:
{
{
m_R
=
1
+
(
normals
[
m_j
].
X
*
normals
[
m_k
].
X
+
m_R
=
1
+
(
normals
[
m_j
].
X
*
normals
[
m_k
].
X
+
normals
[
m_j
].
Y
*
normals
[
m_k
].
Y
);
normals
[
m_j
].
Y
*
normals
[
m_k
].
Y
);
if
(
m_R
>=
m_RMin
)
DoMiter
();
else
DoSquare
(
MiterLimit
);
if
(
m_R
>=
m_RMin
)
DoMiter
();
else
DoSquare
(
MiterLimit
);
break
;
break
;
...
@@ -3261,7 +3353,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
...
@@ -3261,7 +3353,7 @@ PolyOffsetBuilder(const Polygons& in_polys, Polygons& out_polys,
if
(
clpr
.
Execute
(
ctUnion
,
out_polys
,
pftNegative
,
pftNegative
))
if
(
clpr
.
Execute
(
ctUnion
,
out_polys
,
pftNegative
,
pftNegative
))
{
{
out_polys
.
erase
(
out_polys
.
begin
());
out_polys
.
erase
(
out_polys
.
begin
());
ReversePo
int
s
(
out_polys
);
ReversePo
lygon
s
(
out_polys
);
}
else
}
else
out_polys
.
clear
();
out_polys
.
clear
();
...
@@ -3286,12 +3378,13 @@ void DoSquare(double mul = 1.0)
...
@@ -3286,12 +3378,13 @@ void DoSquare(double mul = 1.0)
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
normals
[
m_k
].
Y
*
m_delta
));
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
normals
[
m_k
].
Y
*
m_delta
));
IntPoint
pt2
=
IntPoint
((
long64
)
Round
(
m_p
[
m_i
][
m_j
].
X
+
normals
[
m_j
].
X
*
m_delta
),
IntPoint
pt2
=
IntPoint
((
long64
)
Round
(
m_p
[
m_i
][
m_j
].
X
+
normals
[
m_j
].
X
*
m_delta
),
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
normals
[
m_j
].
Y
*
m_delta
));
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
normals
[
m_j
].
Y
*
m_delta
));
double
sinAngle
=
normals
[
m_k
].
X
*
normals
[
m_j
].
Y
-
normals
[
m_j
].
X
*
normals
[
m_k
].
Y
;
if
((
normals
[
m_k
].
X
*
normals
[
m_j
].
Y
-
normals
[
m_j
].
X
*
normals
[
m_k
].
Y
)
*
m_delta
>=
0
)
if
(
sinAngle
*
m_delta
>=
0
)
{
{
//occasionally (due to floating point math) sinAngle can be > 1 so ...
double
a1
=
std
::
atan2
(
normals
[
m_k
].
Y
,
normals
[
m_k
].
X
);
if
(
sinAngle
>
1
)
sinAngle
=
1
;
else
if
(
sinAngle
<
-
1
)
sinAngle
=
-
1
;
double
a2
=
std
::
atan2
(
-
normals
[
m_j
].
Y
,
-
normals
[
m_j
].
X
);
double
dx
=
tan
((
pi
-
asin
(
sinAngle
))
/
4
)
*
abs
(
m_delta
*
mul
);
a1
=
std
::
fabs
(
a2
-
a1
);
if
(
a1
>
pi
)
a1
=
pi
*
2
-
a1
;
double
dx
=
std
::
tan
((
pi
-
a1
)
/
4
)
*
std
::
fabs
(
m_delta
*
mul
);
pt1
=
IntPoint
((
long64
)(
pt1
.
X
-
normals
[
m_k
].
Y
*
dx
),
pt1
=
IntPoint
((
long64
)(
pt1
.
X
-
normals
[
m_k
].
Y
*
dx
),
(
long64
)(
pt1
.
Y
+
normals
[
m_k
].
X
*
dx
));
(
long64
)(
pt1
.
Y
+
normals
[
m_k
].
X
*
dx
));
AddPoint
(
pt1
);
AddPoint
(
pt1
);
...
@@ -3301,9 +3394,9 @@ void DoSquare(double mul = 1.0)
...
@@ -3301,9 +3394,9 @@ void DoSquare(double mul = 1.0)
}
}
else
else
{
{
AddPoint
(
pt1
);
AddPoint
(
pt1
);
AddPoint
(
m_p
[
m_i
][
m_j
]);
AddPoint
(
m_p
[
m_i
][
m_j
]);
AddPoint
(
pt2
);
AddPoint
(
pt2
);
}
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -3313,7 +3406,7 @@ void DoMiter()
...
@@ -3313,7 +3406,7 @@ void DoMiter()
if
((
normals
[
m_k
].
X
*
normals
[
m_j
].
Y
-
normals
[
m_j
].
X
*
normals
[
m_k
].
Y
)
*
m_delta
>=
0
)
if
((
normals
[
m_k
].
X
*
normals
[
m_j
].
Y
-
normals
[
m_j
].
X
*
normals
[
m_k
].
Y
)
*
m_delta
>=
0
)
{
{
double
q
=
m_delta
/
m_R
;
double
q
=
m_delta
/
m_R
;
AddPoint
(
IntPoint
((
long64
)
Round
(
m_p
[
m_i
][
m_j
].
X
+
AddPoint
(
IntPoint
((
long64
)
Round
(
m_p
[
m_i
][
m_j
].
X
+
(
normals
[
m_k
].
X
+
normals
[
m_j
].
X
)
*
q
),
(
normals
[
m_k
].
X
+
normals
[
m_j
].
X
)
*
q
),
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
(
normals
[
m_k
].
Y
+
normals
[
m_j
].
Y
)
*
q
)));
(
long64
)
Round
(
m_p
[
m_i
][
m_j
].
Y
+
(
normals
[
m_k
].
Y
+
normals
[
m_j
].
Y
)
*
q
)));
}
}
...
@@ -3357,42 +3450,53 @@ void DoRound()
...
@@ -3357,42 +3450,53 @@ void DoRound()
}
}
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
bool
UpdateBotPt
(
const
IntPoint
&
pt
,
IntPoint
&
botPt
)
{
if
(
pt
.
Y
>
botPt
.
Y
||
(
pt
.
Y
==
botPt
.
Y
&&
pt
.
X
<
botPt
.
X
))
{
botPt
=
pt
;
return
true
;
}
else
return
false
;
}
//--------------------------------------------------------------------------
};
//end PolyOffsetBuilder
};
//end PolyOffsetBuilder
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
OffsetPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
void
OffsetPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
double
delta
,
JoinType
jointype
,
double
MiterLimit
)
double
delta
,
JoinType
jointype
,
double
MiterLimit
,
bool
CheckInputs
)
{
{
if
(
&
out_polys
==
&
in_polys
)
if
(
&
out_polys
==
&
in_polys
)
{
{
Polygons
poly2
(
in_polys
);
Polygons
poly2
(
in_polys
);
PolyOffsetBuilder
(
poly2
,
out_polys
,
delta
,
jointype
,
MiterLimit
);
PolyOffsetBuilder
(
poly2
,
out_polys
,
delta
,
jointype
,
MiterLimit
,
CheckInputs
);
}
}
else
PolyOffsetBuilder
(
in_polys
,
out_polys
,
delta
,
jointype
,
MiterLimit
);
else
PolyOffsetBuilder
(
in_polys
,
out_polys
,
delta
,
jointype
,
MiterLimit
,
CheckInputs
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SimplifyPolygon
(
const
Polygon
&
in_poly
,
Polygons
&
out_polys
)
void
SimplifyPolygon
(
const
Polygon
&
in_poly
,
Polygons
&
out_polys
,
PolyFillType
fillType
)
{
{
Clipper
c
;
Clipper
c
;
c
.
AddPolygon
(
in_poly
,
ptSubject
);
c
.
AddPolygon
(
in_poly
,
ptSubject
);
c
.
Execute
(
ctUnion
,
out_polys
);
c
.
Execute
(
ctUnion
,
out_polys
,
fillType
,
fillType
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SimplifyPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
)
void
SimplifyPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
PolyFillType
fillType
)
{
{
Clipper
c
;
Clipper
c
;
c
.
AddPolygons
(
in_polys
,
ptSubject
);
c
.
AddPolygons
(
in_polys
,
ptSubject
);
c
.
Execute
(
ctUnion
,
out_polys
);
c
.
Execute
(
ctUnion
,
out_polys
,
fillType
,
fillType
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SimplifyPolygons
(
Polygons
&
polys
)
void
SimplifyPolygons
(
Polygons
&
polys
,
PolyFillType
fillType
)
{
{
SimplifyPolygons
(
polys
,
polys
);
SimplifyPolygons
(
polys
,
polys
,
fillType
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
...
polygon/clipper.hpp
View file @
31332c39
/*******************************************************************************
/*******************************************************************************
* *
* *
* Author : Angus Johnson *
* Author : Angus Johnson *
* Version : 4.
8.5
*
* Version : 4.
9.6
*
* Date :
15 July 2012
*
* Date :
9 November 2012
*
* Website : http://www.angusj.com *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2012 *
* Copyright : Angus Johnson 2010-2012 *
* *
* *
...
@@ -78,13 +78,13 @@ enum JoinType { jtSquare, jtRound, jtMiter };
...
@@ -78,13 +78,13 @@ enum JoinType { jtSquare, jtRound, jtMiter };
bool
Orientation
(
const
Polygon
&
poly
);
bool
Orientation
(
const
Polygon
&
poly
);
double
Area
(
const
Polygon
&
poly
);
double
Area
(
const
Polygon
&
poly
);
void
OffsetPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
void
OffsetPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
double
delta
,
JoinType
jointype
=
jtSquare
,
double
MiterLimit
=
2
);
double
delta
,
JoinType
jointype
=
jtSquare
,
double
MiterLimit
=
2
,
bool
CheckInputs
=
true
);
void
SimplifyPolygon
(
const
Polygon
&
in_poly
,
Polygons
&
out_polys
);
void
SimplifyPolygon
(
const
Polygon
&
in_poly
,
Polygons
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
);
void
SimplifyPolygons
(
const
Polygons
&
in_polys
,
Polygons
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
Polygons
&
polys
);
void
SimplifyPolygons
(
Polygons
&
polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
ReversePo
ints
(
Polygon
&
p
);
void
ReversePo
lygon
(
Polygon
&
p
);
void
ReversePo
int
s
(
Polygons
&
p
);
void
ReversePo
lygon
s
(
Polygons
&
p
);
//used internally ...
//used internally ...
enum
EdgeSide
{
esNeither
=
0
,
esLeft
=
1
,
esRight
=
2
,
esBoth
=
3
};
enum
EdgeSide
{
esNeither
=
0
,
esLeft
=
1
,
esRight
=
2
,
esBoth
=
3
};
...
@@ -98,6 +98,8 @@ struct TEdge {
...
@@ -98,6 +98,8 @@ struct TEdge {
long64
xtop
;
long64
xtop
;
long64
ytop
;
long64
ytop
;
double
dx
;
double
dx
;
long64
deltaX
;
long64
deltaY
;
long64
tmpX
;
long64
tmpX
;
PolyType
polyType
;
PolyType
polyType
;
EdgeSide
side
;
EdgeSide
side
;
...
@@ -257,7 +259,7 @@ private:
...
@@ -257,7 +259,7 @@ private:
void
DoEdge2
(
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
DoBothEdges
(
TEdge
*
edge1
,
TEdge
*
edge2
,
const
IntPoint
&
pt
);
void
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
void
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
,
IntersectProtects
protects
);
const
IntPoint
&
pt
,
const
IntersectProtects
protects
);
OutRec
*
CreateOutRec
();
OutRec
*
CreateOutRec
();
void
AddOutPt
(
TEdge
*
e
,
const
IntPoint
&
pt
);
void
AddOutPt
(
TEdge
*
e
,
const
IntPoint
&
pt
);
void
DisposeBottomPt
(
OutRec
&
outRec
);
void
DisposeBottomPt
(
OutRec
&
outRec
);
...
@@ -276,12 +278,12 @@ private:
...
@@ -276,12 +278,12 @@ private:
void
FixupOutPolygon
(
OutRec
&
outRec
);
void
FixupOutPolygon
(
OutRec
&
outRec
);
bool
IsHole
(
TEdge
*
e
);
bool
IsHole
(
TEdge
*
e
);
void
FixHoleLinkage
(
OutRec
*
outRec
);
void
FixHoleLinkage
(
OutRec
*
outRec
);
void
CheckHoleLinkages1
(
OutRec
*
outRec1
,
OutRec
*
outRec2
);
void
CheckHoleLinkages2
(
OutRec
*
outRec1
,
OutRec
*
outRec2
);
void
AddJoin
(
TEdge
*
e1
,
TEdge
*
e2
,
int
e1OutIdx
=
-
1
,
int
e2OutIdx
=
-
1
);
void
AddJoin
(
TEdge
*
e1
,
TEdge
*
e2
,
int
e1OutIdx
=
-
1
,
int
e2OutIdx
=
-
1
);
void
ClearJoins
();
void
ClearJoins
();
void
AddHorzJoin
(
TEdge
*
e
,
int
idx
);
void
AddHorzJoin
(
TEdge
*
e
,
int
idx
);
void
ClearHorzJoins
();
void
ClearHorzJoins
();
bool
JoinPoints
(
const
JoinRec
*
j
,
OutPt
*&
p1
,
OutPt
*&
p2
);
void
FixupJoinRecs
(
JoinRec
*
j
,
OutPt
*
pt
,
unsigned
startIdx
);
void
JoinCommonEdges
(
bool
fixHoleLinkages
);
void
JoinCommonEdges
(
bool
fixHoleLinkages
);
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment