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
8da93abc
Commit
8da93abc
authored
Nov 12, 2014
by
jean-pierre charras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Polygon tools: update Clipper lib to 6.2.1
Minor doc update.
parent
b411b240
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
435 additions
and
619 deletions
+435
-619
COMPILING.txt
Documentation/compiling/COMPILING.txt
+2
-2
build-config.txt
Documentation/compiling/build-config.txt
+3
-41
build-msw.txt
Documentation/compiling/build-msw.txt
+12
-9
clipper.cpp
polygon/clipper.cpp
+386
-532
clipper.hpp
polygon/clipper.hpp
+32
-35
No files found.
Documentation/compiling/COMPILING.txt
View file @
8da93abc
...
@@ -130,10 +130,10 @@ In order to have a working Kicad installtion, you need
...
@@ -130,10 +130,10 @@ In order to have a working Kicad installtion, you need
- documentation and translations (they are not included in sources)
- documentation and translations (they are not included in sources)
product branch:
product branch:
bzr branch
lp:
kicad kicad_src
bzr branch
https://code.launchpad.net/~kicad-product-committers/
kicad kicad_src
Stable branch:
Stable branch:
bzr branch
lp:
kicad/stable kicad_src
bzr branch
https://code.launchpad.net/~kicad-product-committers/
kicad/stable kicad_src
Components and Footprints libraries
Components and Footprints libraries
all (schematic libs, 3D shapes ...) but new footprints libraries (use Download zip tool)
all (schematic libs, 3D shapes ...) but new footprints libraries (use Download zip tool)
...
...
Documentation/compiling/build-config.txt
View file @
8da93abc
...
@@ -14,7 +14,7 @@ boost libraries will be downloaded the first time you build Kicad.
...
@@ -14,7 +14,7 @@ boost libraries will be downloaded the first time you build Kicad.
CMake
CMake
=====
=====
KiCad uses CMake to generate the build files specific for the target platform
KiCad uses CMake
(version 2.12 or later)
to generate the build files specific for the target platform
specified by the developer. This document attempts to define some of the more
specified by the developer. This document attempts to define some of the more
common CMake and KiCad build configuration settings. You can use CMake either
common CMake and KiCad build configuration settings. You can use CMake either
by the command CMake on or the graphical version ccmake. This document only
by the command CMake on or the graphical version ccmake. This document only
...
@@ -78,24 +78,6 @@ the wxWidgets library. If you wish to use a custom built wxWidgets library,
...
@@ -78,24 +78,6 @@ the wxWidgets library. If you wish to use a custom built wxWidgets library,
set wxWidgets_ROOT_DIR to the correct path.
set wxWidgets_ROOT_DIR to the correct path.
wxWidgets_USE_DEBUG (ON/OFF)
----------------------------
Default: OFF
When creating a debug build of KiCad, it is often useful to link against the
debug build of the wxWidgets. To use the debug build of wxWidgets, set
wxWidgets_USE_DEBUG to ON.
wxWidgets_USE_UNICODE (ON/OFF)
------------------------------
Default: ON (wxWidgets 2.9 or later), OFF (older versions)
If your platform supports Unicode and you wish to build KiCad with Unicode
support, set wxWidgets_USE_UNICODE to ON. Please note as of the 2.9 branch
this option is not required.
KiCad Specific Options
KiCad Specific Options
======================
======================
...
@@ -114,17 +96,6 @@ WARNING: The KiCad developers strongly advise you to build the bundled copy of
...
@@ -114,17 +96,6 @@ WARNING: The KiCad developers strongly advise you to build the bundled copy of
the Boost library, as it is known to work with KiCad. Other versions may
the Boost library, as it is known to work with KiCad. Other versions may
contain bugs that may result in KiCad errors.
contain bugs that may result in KiCad errors.
USE_WX_GRAPHICS_CONTEXT (ON/OFF)
--------------------------------
Default: OFF
This option is *Experimental*. It enables advanced drawing library code using
wxGraphicsContext and should only be used for testing purposes. Under Windows,
a very recent version of mingw is needed. It also requires wxWidgets to be
built with the --enable-graphics_ctx configuration switch.
USE_IMAGES_IN_MENUS (ON/OFF)
USE_IMAGES_IN_MENUS (ON/OFF)
----------------------------
----------------------------
Default: OFF for OSX, ON for other platforms.
Default: OFF for OSX, ON for other platforms.
...
@@ -147,20 +118,11 @@ to avoid download and building the dependencies multiple times.
...
@@ -147,20 +118,11 @@ to avoid download and building the dependencies multiple times.
KICAD_USER_CONFIG_DIR (PATH)
KICAD_USER_CONFIG_DIR (PATH)
----------------------------
----------------------------
Default:
Home directory
(Unix-based systems), Application data directory (Windows)
Default:
~/.config
(Unix-based systems), Application data directory (Windows)
This option specifies where to store user-specific configuration information.
This option specifies where to store user-specific configuration information.
KICAD_KEEPCASE (ON/OFF)
-----------------------
Default: ON
If this is OFF, component names are automatically converted to uppercase meaning
they are case insensitive. If it is ON, component names are not changed and
are therefore case sensitive.
USE_WX_OVERLAY (ON/OFF)
USE_WX_OVERLAY (ON/OFF)
-----------------------
-----------------------
Default: ON for OSX, OFF for other platforms.
Default: ON for OSX, OFF for other platforms.
...
@@ -192,7 +154,7 @@ KICAD_SCRIPTING_WXPYTHON (ON/OFF)
...
@@ -192,7 +154,7 @@ KICAD_SCRIPTING_WXPYTHON (ON/OFF)
Default: OFF
Default: OFF
This option enables or disables building wxPython support into the KiCad
This option enables or disables building wxPython support into the KiCad
scripting support. Currently only Pcbnew
is supported
. This option requires
scripting support. Currently only Pcbnew
has scripting support
. This option requires
SWIG, Python, and wxPython to be installed on the system.
SWIG, Python, and wxPython to be installed on the system.
...
...
Documentation/compiling/build-msw.txt
View file @
8da93abc
...
@@ -103,16 +103,16 @@ install the wxWidgets library into MinGW then enter the following commands:
...
@@ -103,16 +103,16 @@ install the wxWidgets library into MinGW then enter the following commands:
#mkdir Release
#mkdir Release
#cd Release
#cd Release
#../configure --with-opengl
#../configure --
enable-monolithic=no --enable-shared=yes --
with-opengl
#make
#make
If you want to install wxWidgets in MinGW then enter the following commands:
If you want to install wxWidgets in MinGW then enter the following commands:
#mkdir Release
#mkdir Release
#cd Release
#cd Release
#../configure --prefix=/mingw --enable-monolithic=no --
disable-shared
--with-opengl
#../configure --prefix=/mingw --enable-monolithic=no --
enable-shared=yes
--with-opengl
#make && make install
#make && make install
wxWidgets
will be statically linked to Kicad, which avoid issus with wxWidgets dlls
wxWidgets
cannot be statically linked to Kicad.
Download the KiCad Source Code
Download the KiCad Source Code
------------------------------
------------------------------
...
@@ -126,16 +126,19 @@ Launchpad repository has two branches for KiCad sources:
...
@@ -126,16 +126,19 @@ Launchpad repository has two branches for KiCad sources:
near a stable state)
near a stable state)
To download the testing branch:
To download the testing branch:
#bzr branch
lp:
kicad kicad_testing
#bzr branch
https://code.launchpad.net/~kicad-product-committers/
kicad kicad_testing
To download the stable branch:
To download the stable branch:
#bzr branch
lp:
kicad/stable kicad_stable
#bzr branch
https://code.launchpad.net/~kicad-product-committers/
kicad/stable kicad_stable
To download the component and footprint libraries
To download the component and footprint libraries:
#bzr branch lp:~kicad-lib-committers/kicad/library kicad_libraries
(This branch is a bzr/launchpad import of the Git repository
at https://github.com/KiCad/kicad-library.git.
It has schematic parts and 3D models in it.)
#bzr branch https://code.launchpad.net/~kicad-product-committers/kicad/library kicad_libraries
To download the documentation and translation files:
To download the documentation and translation files:
#bzr branch
lp:
~kicad-developers/kicad/doc kicad_doc
#bzr branch
https://code.launchpad.net/
~kicad-developers/kicad/doc kicad_doc
Create Makefiles with CMake
Create Makefiles with CMake
---------------------------
---------------------------
...
@@ -219,7 +222,7 @@ Building the Developer Documentation
...
@@ -219,7 +222,7 @@ Building the Developer Documentation
------------------------------------
------------------------------------
To build the HTML developer documentation, run the following commands:
To build the HTML developer documentation, run the following commands:
#cd <kicadSource>/build/
debug
#cd <kicadSource>/build/
release
#make doxygen-docs
#make doxygen-docs
The documentation will be created in the <kicadSouce>/Documentation/html
The documentation will be created in the <kicadSouce>/Documentation/html
...
...
polygon/clipper.cpp
View file @
8da93abc
/*******************************************************************************
/*******************************************************************************
* *
* *
* Author : Angus Johnson *
* Author : Angus Johnson *
* Version : 6.
1.3a
*
* Version : 6.
2.1
*
* Date :
22 January
2014 *
* Date :
31 October
2014 *
* Website : http://www.angusj.com *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2014 *
* Copyright : Angus Johnson 2010-2014 *
* *
* *
...
@@ -50,15 +50,6 @@
...
@@ -50,15 +50,6 @@
namespace
ClipperLib
{
namespace
ClipperLib
{
#ifdef use_int32
static
cInt
const
loRange
=
46340
;
static
cInt
const
hiRange
=
46340
;
#else
static
cInt
const
loRange
=
0x3FFFFFFF
;
static
cInt
const
hiRange
=
0x3FFFFFFFFFFFFFFFLL
;
typedef
unsigned
long
long
ulong64
;
#endif
static
double
const
pi
=
3.141592653589793238
;
static
double
const
pi
=
3.141592653589793238
;
static
double
const
two_pi
=
pi
*
2
;
static
double
const
two_pi
=
pi
*
2
;
static
double
const
def_arc_tolerance
=
0.25
;
static
double
const
def_arc_tolerance
=
0.25
;
...
@@ -99,11 +90,10 @@ struct IntersectNode {
...
@@ -99,11 +90,10 @@ struct IntersectNode {
IntPoint
Pt
;
IntPoint
Pt
;
};
};
struct
LocalMinim
a
{
struct
LocalMinim
um
{
cInt
Y
;
cInt
Y
;
TEdge
*
LeftBound
;
TEdge
*
LeftBound
;
TEdge
*
RightBound
;
TEdge
*
RightBound
;
LocalMinima
*
Next
;
};
};
struct
OutPt
;
struct
OutPt
;
...
@@ -131,6 +121,14 @@ struct Join {
...
@@ -131,6 +121,14 @@ struct Join {
IntPoint
OffPt
;
IntPoint
OffPt
;
};
};
struct
LocMinSorter
{
inline
bool
operator
()(
const
LocalMinimum
&
locMin1
,
const
LocalMinimum
&
locMin2
)
{
return
locMin2
.
Y
<
locMin1
.
Y
;
}
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -170,7 +168,10 @@ PolyNode* PolyTree::GetFirst() const
...
@@ -170,7 +168,10 @@ PolyNode* PolyTree::GetFirst() const
int
PolyTree
::
Total
()
const
int
PolyTree
::
Total
()
const
{
{
return
(
int
)
AllNodes
.
size
();
int
result
=
(
int
)
AllNodes
.
size
();
//with negative offsets, ignore the hidden outer polygon ...
if
(
result
>
0
&&
Childs
[
0
]
!=
AllNodes
[
0
])
result
--
;
return
result
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -240,8 +241,8 @@ bool PolyNode::IsOpen() const
...
@@ -240,8 +241,8 @@ bool PolyNode::IsOpen() const
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Int128 class (enables safe math on signed 64bit integers)
// Int128 class (enables safe math on signed 64bit integers)
// eg Int128 val1((
cInt
)9223372036854775807); //ie 2^63 -1
// eg Int128 val1((
long64
)9223372036854775807); //ie 2^63 -1
// Int128 val2((
cInt
)9223372036854775807);
// Int128 val2((
long64
)9223372036854775807);
// Int128 val3 = val1 * val2;
// Int128 val3 = val1 * val2;
// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37)
// val3.AsString => "85070591730234615847396907784232501249" (8.5e+37)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -249,22 +250,21 @@ bool PolyNode::IsOpen() const
...
@@ -249,22 +250,21 @@ bool PolyNode::IsOpen() const
class
Int128
class
Int128
{
{
public
:
public
:
ulong64
lo
;
long64
hi
;
cUInt
lo
;
Int128
(
long64
_lo
=
0
)
cInt
hi
;
Int128
(
cInt
_lo
=
0
)
{
{
lo
=
(
cUInt
)
_lo
;
lo
=
(
ulong64
)
_lo
;
if
(
_lo
<
0
)
hi
=
-
1
;
else
hi
=
0
;
if
(
_lo
<
0
)
hi
=
-
1
;
else
hi
=
0
;
}
}
Int128
(
const
Int128
&
val
)
:
lo
(
val
.
lo
),
hi
(
val
.
hi
){}
Int128
(
const
Int128
&
val
)
:
lo
(
val
.
lo
),
hi
(
val
.
hi
){}
Int128
(
const
cInt
&
_hi
,
const
ulong64
&
_lo
)
:
lo
(
_lo
),
hi
(
_hi
){}
Int128
(
const
long64
&
_hi
,
const
ulong64
&
_lo
)
:
lo
(
_lo
),
hi
(
_hi
){}
Int128
&
operator
=
(
const
cInt
&
val
)
Int128
&
operator
=
(
const
long64
&
val
)
{
{
lo
=
(
ulong64
)
val
;
lo
=
(
ulong64
)
val
;
if
(
val
<
0
)
hi
=
-
1
;
else
hi
=
0
;
if
(
val
<
0
)
hi
=
-
1
;
else
hi
=
0
;
...
@@ -330,81 +330,18 @@ class Int128
...
@@ -330,81 +330,18 @@ class Int128
Int128
operator
-
()
const
//unary negation
Int128
operator
-
()
const
//unary negation
{
{
if
(
lo
==
0
)
if
(
lo
==
0
)
return
Int128
(
-
hi
,
0
);
return
Int128
(
-
hi
,
0
);
else
else
return
Int128
(
~
hi
,
~
lo
+
1
);
return
Int128
(
~
hi
,
~
lo
+
1
);
}
}
Int128
operator
/
(
const
Int128
&
rhs
)
const
operator
double
()
const
{
if
(
rhs
.
lo
==
0
&&
rhs
.
hi
==
0
)
throw
"Int128 operator/: divide by zero"
;
bool
negate
=
(
rhs
.
hi
<
0
)
!=
(
hi
<
0
);
Int128
dividend
=
*
this
;
Int128
divisor
=
rhs
;
if
(
dividend
.
hi
<
0
)
dividend
=
-
dividend
;
if
(
divisor
.
hi
<
0
)
divisor
=
-
divisor
;
if
(
divisor
<
dividend
)
{
Int128
result
=
Int128
(
0
);
Int128
cntr
=
Int128
(
1
);
while
(
divisor
.
hi
>=
0
&&
!
(
divisor
>
dividend
))
{
divisor
.
hi
<<=
1
;
if
((
cInt
)
divisor
.
lo
<
0
)
divisor
.
hi
++
;
divisor
.
lo
<<=
1
;
cntr
.
hi
<<=
1
;
if
((
cInt
)
cntr
.
lo
<
0
)
cntr
.
hi
++
;
cntr
.
lo
<<=
1
;
}
divisor
.
lo
>>=
1
;
if
((
divisor
.
hi
&
1
)
==
1
)
divisor
.
lo
|=
0x8000000000000000LL
;
divisor
.
hi
=
(
ulong64
)
divisor
.
hi
>>
1
;
cntr
.
lo
>>=
1
;
if
((
cntr
.
hi
&
1
)
==
1
)
cntr
.
lo
|=
0x8000000000000000LL
;
cntr
.
hi
>>=
1
;
while
(
cntr
.
hi
!=
0
||
cntr
.
lo
!=
0
)
{
if
(
!
(
dividend
<
divisor
))
{
dividend
-=
divisor
;
result
.
hi
|=
cntr
.
hi
;
result
.
lo
|=
cntr
.
lo
;
}
divisor
.
lo
>>=
1
;
if
((
divisor
.
hi
&
1
)
==
1
)
divisor
.
lo
|=
0x8000000000000000LL
;
divisor
.
hi
>>=
1
;
cntr
.
lo
>>=
1
;
if
((
cntr
.
hi
&
1
)
==
1
)
cntr
.
lo
|=
0x8000000000000000LL
;
cntr
.
hi
>>=
1
;
}
if
(
negate
)
result
=
-
result
;
return
result
;
}
else
if
(
rhs
.
hi
==
this
->
hi
&&
rhs
.
lo
==
this
->
lo
)
return
Int128
(
negate
?
-
1
:
1
);
else
return
Int128
(
0
);
}
double
AsDouble
()
const
{
{
const
double
shift64
=
18446744073709551616.0
;
//2^64
const
double
shift64
=
18446744073709551616.0
;
//2^64
if
(
hi
<
0
)
if
(
hi
<
0
)
{
{
cUInt
lo_
=
~
lo
+
1
;
if
(
lo
==
0
)
return
(
double
)
hi
*
shift64
;
if
(
lo_
==
0
)
return
(
double
)
hi
*
shift64
;
else
return
-
(
double
)(
~
lo
+
~
hi
*
shift64
);
else
return
-
(
double
)(
lo_
+
~
hi
*
shift64
);
}
}
else
else
return
(
double
)(
lo
+
hi
*
shift64
);
return
(
double
)(
lo
+
hi
*
shift64
);
...
@@ -413,7 +350,7 @@ class Int128
...
@@ -413,7 +350,7 @@ class Int128
};
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Int128
Int128Mul
(
cInt
lhs
,
cInt
rhs
)
Int128
Int128Mul
(
long64
lhs
,
long64
rhs
)
{
{
bool
negate
=
(
lhs
<
0
)
!=
(
rhs
<
0
);
bool
negate
=
(
lhs
<
0
)
!=
(
rhs
<
0
);
...
@@ -431,9 +368,9 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
...
@@ -431,9 +368,9 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
ulong64
c
=
int1Hi
*
int2Lo
+
int1Lo
*
int2Hi
;
ulong64
c
=
int1Hi
*
int2Lo
+
int1Lo
*
int2Hi
;
Int128
tmp
;
Int128
tmp
;
tmp
.
hi
=
cInt
(
a
+
(
c
>>
32
));
tmp
.
hi
=
long64
(
a
+
(
c
>>
32
));
tmp
.
lo
=
cInt
(
c
<<
32
);
tmp
.
lo
=
long64
(
c
<<
32
);
tmp
.
lo
+=
cInt
(
b
);
tmp
.
lo
+=
long64
(
b
);
if
(
tmp
.
lo
<
b
)
tmp
.
hi
++
;
if
(
tmp
.
lo
<
b
)
tmp
.
hi
++
;
if
(
negate
)
tmp
=
-
tmp
;
if
(
negate
)
tmp
=
-
tmp
;
return
tmp
;
return
tmp
;
...
@@ -444,6 +381,13 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
...
@@ -444,6 +381,13 @@ Int128 Int128Mul (cInt lhs, cInt rhs)
// Miscellaneous global functions
// Miscellaneous global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
Swap
(
cInt
&
val1
,
cInt
&
val2
)
{
cInt
tmp
=
val1
;
val1
=
val2
;
val2
=
tmp
;
}
//------------------------------------------------------------------------------
bool
Orientation
(
const
Path
&
poly
)
bool
Orientation
(
const
Path
&
poly
)
{
{
return
Area
(
poly
)
>=
0
;
return
Area
(
poly
)
>=
0
;
...
@@ -494,6 +438,7 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
...
@@ -494,6 +438,7 @@ bool PointIsVertex(const IntPoint &Pt, OutPt *pp)
int
PointInPolygon
(
const
IntPoint
&
pt
,
const
Path
&
path
)
int
PointInPolygon
(
const
IntPoint
&
pt
,
const
Path
&
path
)
{
{
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//See "The Point in Polygon Problem for Arbitrary Polygons" by Hormann & Agathos
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int
result
=
0
;
int
result
=
0
;
size_t
cnt
=
path
.
size
();
size_t
cnt
=
path
.
size
();
...
@@ -539,7 +484,6 @@ int PointInPolygon (const IntPoint &pt, const Path &path)
...
@@ -539,7 +484,6 @@ int PointInPolygon (const IntPoint &pt, const Path &path)
int
PointInPolygon
(
const
IntPoint
&
pt
,
OutPt
*
op
)
int
PointInPolygon
(
const
IntPoint
&
pt
,
OutPt
*
op
)
{
{
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//returns 0 if false, +1 if true, -1 if pt ON polygon boundary
//http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.88.5498&rep=rep1&type=pdf
int
result
=
0
;
int
result
=
0
;
OutPt
*
startOp
=
op
;
OutPt
*
startOp
=
op
;
for
(;;)
for
(;;)
...
@@ -584,8 +528,9 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
...
@@ -584,8 +528,9 @@ bool Poly2ContainsPoly1(OutPt *OutPt1, OutPt *OutPt2)
OutPt
*
op
=
OutPt1
;
OutPt
*
op
=
OutPt1
;
do
do
{
{
//nb: PointInPolygon returns 0 if false, +1 if true, -1 if pt on polygon
int
res
=
PointInPolygon
(
op
->
Pt
,
OutPt2
);
int
res
=
PointInPolygon
(
op
->
Pt
,
OutPt2
);
if
(
res
>=
0
)
return
res
!=
0
;
if
(
res
>=
0
)
return
res
>
0
;
op
=
op
->
Next
;
op
=
op
->
Next
;
}
}
while
(
op
!=
OutPt1
);
while
(
op
!=
OutPt1
);
...
@@ -674,20 +619,18 @@ inline cInt TopX(TEdge &edge, const cInt currentY)
...
@@ -674,20 +619,18 @@ inline cInt TopX(TEdge &edge, const cInt currentY)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
IntersectPoint
(
TEdge
&
Edge1
,
TEdge
&
Edge2
,
void
IntersectPoint
(
TEdge
&
Edge1
,
TEdge
&
Edge2
,
IntPoint
&
ip
)
IntPoint
&
ip
,
bool
UseFullInt64Range
)
{
{
#ifdef use_xyz
#ifdef use_xyz
ip
.
Z
=
0
;
ip
.
Z
=
0
;
#endif
#endif
double
b1
,
b2
;
double
b1
,
b2
;
//nb: with very large coordinate values, it's possible for SlopesEqual() to
if
(
Edge1
.
Dx
==
Edge2
.
Dx
)
//return false but for the edge.Dx value be equal due to double precision rounding.
if
(
SlopesEqual
(
Edge1
,
Edge2
,
UseFullInt64Range
)
||
Edge1
.
Dx
==
Edge2
.
Dx
)
{
{
i
f
(
Edge2
.
Bot
.
Y
>
Edge1
.
Bot
.
Y
)
ip
=
Edge2
.
Bot
;
i
p
.
Y
=
Edge1
.
Curr
.
Y
;
else
ip
=
Edge1
.
Bot
;
ip
.
X
=
TopX
(
Edge1
,
ip
.
Y
)
;
return
false
;
return
;
}
}
else
if
(
Edge1
.
Delta
.
X
==
0
)
else
if
(
Edge1
.
Delta
.
X
==
0
)
{
{
...
@@ -734,7 +677,15 @@ bool IntersectPoint(TEdge &Edge1, TEdge &Edge2,
...
@@ -734,7 +677,15 @@ bool IntersectPoint(TEdge &Edge1, TEdge &Edge2,
else
else
ip
.
X
=
TopX
(
Edge2
,
ip
.
Y
);
ip
.
X
=
TopX
(
Edge2
,
ip
.
Y
);
}
}
return
true
;
//finally, don't allow 'ip' to be BELOW curr.Y (ie bottom of scanbeam) ...
if
(
ip
.
Y
>
Edge1
.
Curr
.
Y
)
{
ip
.
Y
=
Edge1
.
Curr
.
Y
;
//use the more vertical edge to derive X ...
if
(
std
::
fabs
(
Edge1
.
Dx
)
>
std
::
fabs
(
Edge2
.
Dx
))
ip
.
X
=
TopX
(
Edge2
,
ip
.
Y
);
else
ip
.
X
=
TopX
(
Edge1
,
ip
.
Y
);
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -807,13 +758,9 @@ inline void ReverseHorizontal(TEdge &e)
...
@@ -807,13 +758,9 @@ inline void ReverseHorizontal(TEdge &e)
//swap horizontal edges' Top and Bottom x's so they follow the natural
//swap horizontal edges' Top and Bottom x's so they follow the natural
//progression of the bounds - ie so their xbots will align with the
//progression of the bounds - ie so their xbots will align with the
//adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
//adjoining lower edge. [Helpful in the ProcessHorizontal() method.]
cInt
tmp
=
e
.
Top
.
X
;
Swap
(
e
.
Top
.
X
,
e
.
Bot
.
X
);
e
.
Top
.
X
=
e
.
Bot
.
X
;
e
.
Bot
.
X
=
tmp
;
#ifdef use_xyz
#ifdef use_xyz
tmp
=
e
.
Top
.
Z
;
Swap
(
e
.
Top
.
Z
,
e
.
Bot
.
Z
);
e
.
Top
.
Z
=
e
.
Bot
.
Z
;
e
.
Bot
.
Z
=
tmp
;
#endif
#endif
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -905,26 +852,6 @@ OutPt* GetBottomPt(OutPt *pp)
...
@@ -905,26 +852,6 @@ OutPt* GetBottomPt(OutPt *pp)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
FindSegment
(
OutPt
*
&
pp
,
bool
UseFullInt64Range
,
IntPoint
&
pt1
,
IntPoint
&
pt2
)
{
//OutPt1 & OutPt2 => the overlap segment (if the function returns true)
if
(
!
pp
)
return
false
;
OutPt
*
pp2
=
pp
;
IntPoint
pt1a
=
pt1
,
pt2a
=
pt2
;
do
{
if
(
SlopesEqual
(
pt1a
,
pt2a
,
pp
->
Pt
,
pp
->
Prev
->
Pt
,
UseFullInt64Range
)
&&
SlopesEqual
(
pt1a
,
pt2a
,
pp
->
Pt
,
UseFullInt64Range
)
&&
GetOverlapSegment
(
pt1a
,
pt2a
,
pp
->
Pt
,
pp
->
Prev
->
Pt
,
pt1
,
pt2
))
return
true
;
pp
=
pp
->
Next
;
}
while
(
pp
!=
pp2
);
return
false
;
}
//------------------------------------------------------------------------------
bool
Pt2IsBetweenPt1AndPt3
(
const
IntPoint
pt1
,
bool
Pt2IsBetweenPt1AndPt3
(
const
IntPoint
pt1
,
const
IntPoint
pt2
,
const
IntPoint
pt3
)
const
IntPoint
pt2
,
const
IntPoint
pt3
)
{
{
...
@@ -937,50 +864,20 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
...
@@ -937,50 +864,20 @@ bool Pt2IsBetweenPt1AndPt3(const IntPoint pt1,
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
OutPt
*
InsertPolyPtBetween
(
OutPt
*
p1
,
OutPt
*
p2
,
const
IntPoint
Pt
)
bool
HorzSegmentsOverlap
(
cInt
seg1a
,
cInt
seg1b
,
cInt
seg2a
,
cInt
seg2b
)
{
if
(
p1
==
p2
)
throw
"JoinError"
;
OutPt
*
result
=
new
OutPt
;
result
->
Pt
=
Pt
;
if
(
p2
==
p1
->
Next
)
{
p1
->
Next
=
result
;
p2
->
Prev
=
result
;
result
->
Next
=
p2
;
result
->
Prev
=
p1
;
}
else
{
p2
->
Next
=
result
;
p1
->
Prev
=
result
;
result
->
Next
=
p1
;
result
->
Prev
=
p2
;
}
return
result
;
}
//------------------------------------------------------------------------------
bool
HorzSegmentsOverlap
(
const
IntPoint
&
pt1a
,
const
IntPoint
&
pt1b
,
const
IntPoint
&
pt2a
,
const
IntPoint
&
pt2b
)
{
{
//precondition: both segments are horizontal
if
(
seg1a
>
seg1b
)
Swap
(
seg1a
,
seg1b
);
if
((
pt1a
.
X
>
pt2a
.
X
)
==
(
pt1a
.
X
<
pt2b
.
X
))
return
true
;
if
(
seg2a
>
seg2b
)
Swap
(
seg2a
,
seg2b
);
else
if
((
pt1b
.
X
>
pt2a
.
X
)
==
(
pt1b
.
X
<
pt2b
.
X
))
return
true
;
return
(
seg1a
<
seg2b
)
&&
(
seg2a
<
seg1b
);
else
if
((
pt2a
.
X
>
pt1a
.
X
)
==
(
pt2a
.
X
<
pt1b
.
X
))
return
true
;
else
if
((
pt2b
.
X
>
pt1a
.
X
)
==
(
pt2b
.
X
<
pt1b
.
X
))
return
true
;
else
if
((
pt1a
.
X
==
pt2a
.
X
)
&&
(
pt1b
.
X
==
pt2b
.
X
))
return
true
;
else
if
((
pt1a
.
X
==
pt2b
.
X
)
&&
(
pt1b
.
X
==
pt2a
.
X
))
return
true
;
else
return
false
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// ClipperBase class methods ...
// ClipperBase class methods ...
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
ClipperBase
::
ClipperBase
()
//constructor
ClipperBase
::
ClipperBase
()
//constructor
{
{
m_MinimaList
=
0
;
m_CurrentLM
=
m_MinimaList
.
begin
();
//begin() == end() here
m_CurrentLM
=
0
;
m_UseFullRange
=
false
;
m_UseFullRange
=
false
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1023,23 +920,76 @@ TEdge* FindNextLocMin(TEdge* E)
...
@@ -1023,23 +920,76 @@ TEdge* FindNextLocMin(TEdge* E)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
TEdge
*
ClipperBase
::
ProcessBound
(
TEdge
*
E
,
bool
IsClockwise
)
TEdge
*
ClipperBase
::
ProcessBound
(
TEdge
*
E
,
bool
NextIsForward
)
{
{
TEdge
*
EStart
=
E
,
*
Result
=
E
;
TEdge
*
Result
=
E
;
TEdge
*
Horz
=
0
;
TEdge
*
Horz
=
0
;
cInt
StartX
;
if
(
IsHorizontal
(
*
E
)
)
if
(
E
->
OutIdx
==
Skip
)
{
{
//it's possible for adjacent overlapping horz edges to start heading left
//if edges still remain in the current bound beyond the skip edge then
//before finishing right, so ...
//create another LocMin and call ProcessBound once more
if
(
IsClockwise
)
StartX
=
E
->
Prev
->
Bot
.
X
;
if
(
NextIsForward
)
else
StartX
=
E
->
Next
->
Bot
.
X
;
{
if
(
E
->
Bot
.
X
!=
StartX
)
ReverseHorizontal
(
*
E
);
while
(
E
->
Top
.
Y
==
E
->
Next
->
Bot
.
Y
)
E
=
E
->
Next
;
//don't include top horizontals when parsing a bound a second time,
//they will be contained in the opposite bound ...
while
(
E
!=
Result
&&
IsHorizontal
(
*
E
))
E
=
E
->
Prev
;
}
else
{
while
(
E
->
Top
.
Y
==
E
->
Prev
->
Bot
.
Y
)
E
=
E
->
Prev
;
while
(
E
!=
Result
&&
IsHorizontal
(
*
E
))
E
=
E
->
Next
;
}
}
if
(
Result
->
OutIdx
!=
Skip
)
if
(
E
==
Result
)
{
{
if
(
IsClockwise
)
if
(
NextIsForward
)
Result
=
E
->
Next
;
else
Result
=
E
->
Prev
;
}
else
{
//there are more edges in the bound beyond result starting with E
if
(
NextIsForward
)
E
=
Result
->
Next
;
else
E
=
Result
->
Prev
;
MinimaList
::
value_type
locMin
;
locMin
.
Y
=
E
->
Bot
.
Y
;
locMin
.
LeftBound
=
0
;
locMin
.
RightBound
=
E
;
E
->
WindDelta
=
0
;
Result
=
ProcessBound
(
E
,
NextIsForward
);
m_MinimaList
.
push_back
(
locMin
);
}
return
Result
;
}
TEdge
*
EStart
;
if
(
IsHorizontal
(
*
E
))
{
//We need to be careful with open paths because this may not be a
//true local minima (ie E may be following a skip edge).
//Also, consecutive horz. edges may start heading left before going right.
if
(
NextIsForward
)
EStart
=
E
->
Prev
;
else
EStart
=
E
->
Next
;
if
(
EStart
->
OutIdx
!=
Skip
)
{
if
(
IsHorizontal
(
*
EStart
))
//ie an adjoining horizontal skip edge
{
if
(
EStart
->
Bot
.
X
!=
E
->
Bot
.
X
&&
EStart
->
Top
.
X
!=
E
->
Bot
.
X
)
ReverseHorizontal
(
*
E
);
}
else
if
(
EStart
->
Bot
.
X
!=
E
->
Bot
.
X
)
ReverseHorizontal
(
*
E
);
}
}
EStart
=
E
;
if
(
NextIsForward
)
{
{
while
(
Result
->
Top
.
Y
==
Result
->
Next
->
Bot
.
Y
&&
Result
->
Next
->
OutIdx
!=
Skip
)
while
(
Result
->
Top
.
Y
==
Result
->
Next
->
Bot
.
Y
&&
Result
->
Next
->
OutIdx
!=
Skip
)
Result
=
Result
->
Next
;
Result
=
Result
->
Next
;
...
@@ -1052,7 +1002,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
...
@@ -1052,7 +1002,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
while
(
IsHorizontal
(
*
Horz
->
Prev
))
Horz
=
Horz
->
Prev
;
while
(
IsHorizontal
(
*
Horz
->
Prev
))
Horz
=
Horz
->
Prev
;
if
(
Horz
->
Prev
->
Top
.
X
==
Result
->
Next
->
Top
.
X
)
if
(
Horz
->
Prev
->
Top
.
X
==
Result
->
Next
->
Top
.
X
)
{
{
if
(
!
IsClockwise
)
Result
=
Horz
->
Prev
;
if
(
!
NextIsForward
)
Result
=
Horz
->
Prev
;
}
}
else
if
(
Horz
->
Prev
->
Top
.
X
>
Result
->
Next
->
Top
.
X
)
Result
=
Horz
->
Prev
;
else
if
(
Horz
->
Prev
->
Top
.
X
>
Result
->
Next
->
Top
.
X
)
Result
=
Horz
->
Prev
;
}
}
...
@@ -1076,7 +1026,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
...
@@ -1076,7 +1026,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
while
(
IsHorizontal
(
*
Horz
->
Next
))
Horz
=
Horz
->
Next
;
while
(
IsHorizontal
(
*
Horz
->
Next
))
Horz
=
Horz
->
Next
;
if
(
Horz
->
Next
->
Top
.
X
==
Result
->
Prev
->
Top
.
X
)
if
(
Horz
->
Next
->
Top
.
X
==
Result
->
Prev
->
Top
.
X
)
{
{
if
(
!
IsClockwise
)
Result
=
Horz
->
Next
;
if
(
!
NextIsForward
)
Result
=
Horz
->
Next
;
}
}
else
if
(
Horz
->
Next
->
Top
.
X
>
Result
->
Prev
->
Top
.
X
)
Result
=
Horz
->
Next
;
else
if
(
Horz
->
Next
->
Top
.
X
>
Result
->
Prev
->
Top
.
X
)
Result
=
Horz
->
Next
;
}
}
...
@@ -1092,45 +1042,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
...
@@ -1092,45 +1042,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool IsClockwise)
ReverseHorizontal
(
*
E
);
ReverseHorizontal
(
*
E
);
Result
=
Result
->
Prev
;
//move to the edge just beyond current bound
Result
=
Result
->
Prev
;
//move to the edge just beyond current bound
}
}
}
if
(
Result
->
OutIdx
==
Skip
)
{
//if edges still remain in the current bound beyond the skip edge then
//create another LocMin and call ProcessBound once more
E
=
Result
;
if
(
IsClockwise
)
{
while
(
E
->
Top
.
Y
==
E
->
Next
->
Bot
.
Y
)
E
=
E
->
Next
;
//don't include top horizontals when parsing a bound a second time,
//they will be contained in the opposite bound ...
while
(
E
!=
Result
&&
IsHorizontal
(
*
E
))
E
=
E
->
Prev
;
}
else
{
while
(
E
->
Top
.
Y
==
E
->
Prev
->
Bot
.
Y
)
E
=
E
->
Prev
;
while
(
E
!=
Result
&&
IsHorizontal
(
*
E
))
E
=
E
->
Next
;
}
if
(
E
==
Result
)
{
if
(
IsClockwise
)
Result
=
E
->
Next
;
else
Result
=
E
->
Prev
;
}
else
{
//there are more edges in the bound beyond result starting with E
if
(
IsClockwise
)
E
=
Result
->
Next
;
else
E
=
Result
->
Prev
;
LocalMinima
*
locMin
=
new
LocalMinima
;
locMin
->
Next
=
0
;
locMin
->
Y
=
E
->
Bot
.
Y
;
locMin
->
LeftBound
=
0
;
locMin
->
RightBound
=
E
;
locMin
->
RightBound
->
WindDelta
=
0
;
Result
=
ProcessBound
(
locMin
->
RightBound
,
IsClockwise
);
InsertLocalMinima
(
locMin
);
}
}
return
Result
;
return
Result
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1179,7 +1091,8 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
...
@@ -1179,7 +1091,8 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
TEdge
*
E
=
eStart
,
*
eLoopStop
=
eStart
;
TEdge
*
E
=
eStart
,
*
eLoopStop
=
eStart
;
for
(;;)
for
(;;)
{
{
if
((
E
->
Curr
==
E
->
Next
->
Curr
))
//nb: allows matching start and end points when not Closed ...
if
(
E
->
Curr
==
E
->
Next
->
Curr
&&
(
Closed
||
E
->
Next
!=
eStart
))
{
{
if
(
E
==
E
->
Next
)
break
;
if
(
E
==
E
->
Next
)
break
;
if
(
E
==
eStart
)
eStart
=
E
->
Next
;
if
(
E
==
eStart
)
eStart
=
E
->
Next
;
...
@@ -1205,7 +1118,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
...
@@ -1205,7 +1118,7 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
continue
;
continue
;
}
}
E
=
E
->
Next
;
E
=
E
->
Next
;
if
(
E
==
eLoopStop
)
break
;
if
(
(
E
==
eLoopStop
)
||
(
!
Closed
&&
E
->
Next
==
eStart
)
)
break
;
}
}
if
((
!
Closed
&&
(
E
==
E
->
Next
))
||
(
Closed
&&
(
E
->
Prev
==
E
->
Next
)))
if
((
!
Closed
&&
(
E
==
E
->
Next
))
||
(
Closed
&&
(
E
->
Prev
==
E
->
Next
)))
...
@@ -1243,27 +1156,31 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
...
@@ -1243,27 +1156,31 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
}
}
E
->
Prev
->
OutIdx
=
Skip
;
E
->
Prev
->
OutIdx
=
Skip
;
if
(
E
->
Prev
->
Bot
.
X
<
E
->
Prev
->
Top
.
X
)
ReverseHorizontal
(
*
E
->
Prev
);
if
(
E
->
Prev
->
Bot
.
X
<
E
->
Prev
->
Top
.
X
)
ReverseHorizontal
(
*
E
->
Prev
);
LocalMinima
*
locMin
=
new
LocalMinima
();
MinimaList
::
value_type
locMin
;
locMin
->
Next
=
0
;
locMin
.
Y
=
E
->
Bot
.
Y
;
locMin
->
Y
=
E
->
Bot
.
Y
;
locMin
.
LeftBound
=
0
;
locMin
->
LeftBound
=
0
;
locMin
.
RightBound
=
E
;
locMin
->
RightBound
=
E
;
locMin
.
RightBound
->
Side
=
esRight
;
locMin
->
RightBound
->
Side
=
esRight
;
locMin
.
RightBound
->
WindDelta
=
0
;
locMin
->
RightBound
->
WindDelta
=
0
;
while
(
E
->
Next
->
OutIdx
!=
Skip
)
while
(
E
->
Next
->
OutIdx
!=
Skip
)
{
{
E
->
NextInLML
=
E
->
Next
;
E
->
NextInLML
=
E
->
Next
;
if
(
E
->
Bot
.
X
!=
E
->
Prev
->
Top
.
X
)
ReverseHorizontal
(
*
E
);
if
(
E
->
Bot
.
X
!=
E
->
Prev
->
Top
.
X
)
ReverseHorizontal
(
*
E
);
E
=
E
->
Next
;
E
=
E
->
Next
;
}
}
InsertLocalMinima
(
locMin
);
m_MinimaList
.
push_back
(
locMin
);
m_edges
.
push_back
(
edges
);
m_edges
.
push_back
(
edges
);
return
true
;
return
true
;
}
}
m_edges
.
push_back
(
edges
);
m_edges
.
push_back
(
edges
);
bool
clockwise
;
bool
leftBoundIsForward
;
TEdge
*
EMin
=
0
;
TEdge
*
EMin
=
0
;
//workaround to avoid an endless loop in the while loop below when
//open paths have matching start and end points ...
if
(
E
->
Prev
->
Bot
==
E
->
Prev
->
Top
)
E
=
E
->
Next
;
for
(;;)
for
(;;)
{
{
E
=
FindNextLocMin
(
E
);
E
=
FindNextLocMin
(
E
);
...
@@ -1272,38 +1189,40 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
...
@@ -1272,38 +1189,40 @@ bool ClipperBase::AddPath(const Path &pg, PolyType PolyTyp, bool Closed)
//E and E.Prev now share a local minima (left aligned if horizontal).
//E and E.Prev now share a local minima (left aligned if horizontal).
//Compare their slopes to find which starts which bound ...
//Compare their slopes to find which starts which bound ...
LocalMinima
*
locMin
=
new
LocalMinima
;
MinimaList
::
value_type
locMin
;
locMin
->
Next
=
0
;
locMin
.
Y
=
E
->
Bot
.
Y
;
locMin
->
Y
=
E
->
Bot
.
Y
;
if
(
E
->
Dx
<
E
->
Prev
->
Dx
)
if
(
E
->
Dx
<
E
->
Prev
->
Dx
)
{
{
locMin
->
LeftBound
=
E
->
Prev
;
locMin
.
LeftBound
=
E
->
Prev
;
locMin
->
RightBound
=
E
;
locMin
.
RightBound
=
E
;
clockwise
=
false
;
//Q.nextInLML = Q.prev
leftBoundIsForward
=
false
;
//Q.nextInLML = Q.prev
}
else
}
else
{
{
locMin
->
LeftBound
=
E
;
locMin
.
LeftBound
=
E
;
locMin
->
RightBound
=
E
->
Prev
;
locMin
.
RightBound
=
E
->
Prev
;
clockwise
=
true
;
//Q.nextInLML = Q.next
leftBoundIsForward
=
true
;
//Q.nextInLML = Q.next
}
}
locMin
->
LeftBound
->
Side
=
esLeft
;
locMin
.
LeftBound
->
Side
=
esLeft
;
locMin
->
RightBound
->
Side
=
esRight
;
locMin
.
RightBound
->
Side
=
esRight
;
if
(
!
Closed
)
locMin
->
LeftBound
->
WindDelta
=
0
;
if
(
!
Closed
)
locMin
.
LeftBound
->
WindDelta
=
0
;
else
if
(
locMin
->
LeftBound
->
Next
==
locMin
->
RightBound
)
else
if
(
locMin
.
LeftBound
->
Next
==
locMin
.
RightBound
)
locMin
->
LeftBound
->
WindDelta
=
-
1
;
locMin
.
LeftBound
->
WindDelta
=
-
1
;
else
locMin
->
LeftBound
->
WindDelta
=
1
;
else
locMin
.
LeftBound
->
WindDelta
=
1
;
locMin
->
RightBound
->
WindDelta
=
-
locMin
->
LeftBound
->
WindDelta
;
locMin
.
RightBound
->
WindDelta
=
-
locMin
.
LeftBound
->
WindDelta
;
E
=
ProcessBound
(
locMin
->
LeftBound
,
clockwise
);
E
=
ProcessBound
(
locMin
.
LeftBound
,
leftBoundIsForward
);
TEdge
*
E2
=
ProcessBound
(
locMin
->
RightBound
,
!
clockwise
);
if
(
E
->
OutIdx
==
Skip
)
E
=
ProcessBound
(
E
,
leftBoundIsForward
);
if
(
locMin
->
LeftBound
->
OutIdx
==
Skip
)
TEdge
*
E2
=
ProcessBound
(
locMin
.
RightBound
,
!
leftBoundIsForward
);
locMin
->
LeftBound
=
0
;
if
(
E2
->
OutIdx
==
Skip
)
E2
=
ProcessBound
(
E2
,
!
leftBoundIsForward
);
else
if
(
locMin
->
RightBound
->
OutIdx
==
Skip
)
locMin
->
RightBound
=
0
;
if
(
locMin
.
LeftBound
->
OutIdx
==
Skip
)
InsertLocalMinima
(
locMin
);
locMin
.
LeftBound
=
0
;
if
(
!
clockwise
)
E
=
E2
;
else
if
(
locMin
.
RightBound
->
OutIdx
==
Skip
)
locMin
.
RightBound
=
0
;
m_MinimaList
.
push_back
(
locMin
);
if
(
!
leftBoundIsForward
)
E
=
E2
;
}
}
return
true
;
return
true
;
}
}
...
@@ -1318,27 +1237,6 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
...
@@ -1318,27 +1237,6 @@ bool ClipperBase::AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ClipperBase
::
InsertLocalMinima
(
LocalMinima
*
newLm
)
{
if
(
!
m_MinimaList
)
{
m_MinimaList
=
newLm
;
}
else
if
(
newLm
->
Y
>=
m_MinimaList
->
Y
)
{
newLm
->
Next
=
m_MinimaList
;
m_MinimaList
=
newLm
;
}
else
{
LocalMinima
*
tmpLm
=
m_MinimaList
;
while
(
tmpLm
->
Next
&&
(
newLm
->
Y
<
tmpLm
->
Next
->
Y
)
)
tmpLm
=
tmpLm
->
Next
;
newLm
->
Next
=
tmpLm
->
Next
;
tmpLm
->
Next
=
newLm
;
}
}
//------------------------------------------------------------------------------
void
ClipperBase
::
Clear
()
void
ClipperBase
::
Clear
()
{
{
DisposeLocalMinimaList
();
DisposeLocalMinimaList
();
...
@@ -1357,12 +1255,12 @@ void ClipperBase::Clear()
...
@@ -1357,12 +1255,12 @@ void ClipperBase::Clear()
void
ClipperBase
::
Reset
()
void
ClipperBase
::
Reset
()
{
{
m_CurrentLM
=
m_MinimaList
;
m_CurrentLM
=
m_MinimaList
.
begin
();
if
(
!
m_CurrentLM
)
return
;
//ie nothing to process
if
(
m_CurrentLM
==
m_MinimaList
.
end
())
return
;
//ie nothing to process
std
::
sort
(
m_MinimaList
.
begin
(),
m_MinimaList
.
end
(),
LocMinSorter
());
//reset all edges ...
//reset all edges ...
LocalMinima
*
lm
=
m_MinimaList
;
for
(
MinimaList
::
iterator
lm
=
m_MinimaList
.
begin
();
lm
!=
m_MinimaList
.
end
();
++
lm
)
while
(
lm
)
{
{
TEdge
*
e
=
lm
->
LeftBound
;
TEdge
*
e
=
lm
->
LeftBound
;
if
(
e
)
if
(
e
)
...
@@ -1379,35 +1277,29 @@ void ClipperBase::Reset()
...
@@ -1379,35 +1277,29 @@ void ClipperBase::Reset()
e
->
Side
=
esRight
;
e
->
Side
=
esRight
;
e
->
OutIdx
=
Unassigned
;
e
->
OutIdx
=
Unassigned
;
}
}
lm
=
lm
->
Next
;
}
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ClipperBase
::
DisposeLocalMinimaList
()
void
ClipperBase
::
DisposeLocalMinimaList
()
{
{
while
(
m_MinimaList
)
m_MinimaList
.
clear
();
{
m_CurrentLM
=
m_MinimaList
.
begin
();
LocalMinima
*
tmpLm
=
m_MinimaList
->
Next
;
delete
m_MinimaList
;
m_MinimaList
=
tmpLm
;
}
m_CurrentLM
=
0
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
ClipperBase
::
PopLocalMinima
()
void
ClipperBase
::
PopLocalMinima
()
{
{
if
(
!
m_CurrentLM
)
return
;
if
(
m_CurrentLM
==
m_MinimaList
.
end
()
)
return
;
m_CurrentLM
=
m_CurrentLM
->
Next
;
++
m_CurrentLM
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
IntRect
ClipperBase
::
GetBounds
()
IntRect
ClipperBase
::
GetBounds
()
{
{
IntRect
result
;
IntRect
result
;
LocalMinima
*
lm
=
m_MinimaList
;
MinimaList
::
iterator
lm
=
m_MinimaList
.
begin
()
;
if
(
!
lm
)
if
(
lm
==
m_MinimaList
.
end
()
)
{
{
result
.
left
=
result
.
top
=
result
.
right
=
result
.
bottom
=
0
;
result
.
left
=
result
.
top
=
result
.
right
=
result
.
bottom
=
0
;
return
result
;
return
result
;
...
@@ -1416,10 +1308,9 @@ IntRect ClipperBase::GetBounds()
...
@@ -1416,10 +1308,9 @@ IntRect ClipperBase::GetBounds()
result
.
top
=
lm
->
LeftBound
->
Bot
.
Y
;
result
.
top
=
lm
->
LeftBound
->
Bot
.
Y
;
result
.
right
=
lm
->
LeftBound
->
Bot
.
X
;
result
.
right
=
lm
->
LeftBound
->
Bot
.
X
;
result
.
bottom
=
lm
->
LeftBound
->
Bot
.
Y
;
result
.
bottom
=
lm
->
LeftBound
->
Bot
.
Y
;
while
(
lm
)
while
(
lm
!=
m_MinimaList
.
end
()
)
{
{
if
(
lm
->
LeftBound
->
Bot
.
Y
>
result
.
bottom
)
result
.
bottom
=
std
::
max
(
result
.
bottom
,
lm
->
LeftBound
->
Bot
.
Y
);
result
.
bottom
=
lm
->
LeftBound
->
Bot
.
Y
;
TEdge
*
e
=
lm
->
LeftBound
;
TEdge
*
e
=
lm
->
LeftBound
;
for
(;;)
{
for
(;;)
{
TEdge
*
bottomE
=
e
;
TEdge
*
bottomE
=
e
;
...
@@ -1429,16 +1320,15 @@ IntRect ClipperBase::GetBounds()
...
@@ -1429,16 +1320,15 @@ IntRect ClipperBase::GetBounds()
if
(
e
->
Bot
.
X
>
result
.
right
)
result
.
right
=
e
->
Bot
.
X
;
if
(
e
->
Bot
.
X
>
result
.
right
)
result
.
right
=
e
->
Bot
.
X
;
e
=
e
->
NextInLML
;
e
=
e
->
NextInLML
;
}
}
if
(
e
->
Bot
.
X
<
result
.
left
)
result
.
left
=
e
->
Bot
.
X
;
result
.
left
=
std
::
min
(
result
.
left
,
e
->
Bot
.
X
);
if
(
e
->
Bot
.
X
>
result
.
right
)
result
.
right
=
e
->
Bot
.
X
;
result
.
right
=
std
::
max
(
result
.
right
,
e
->
Bot
.
X
);
if
(
e
->
Top
.
X
<
result
.
left
)
result
.
left
=
e
->
Top
.
X
;
result
.
left
=
std
::
min
(
result
.
left
,
e
->
Top
.
X
);
if
(
e
->
Top
.
X
>
result
.
right
)
result
.
right
=
e
->
Top
.
X
;
result
.
right
=
std
::
max
(
result
.
right
,
e
->
Top
.
X
);
if
(
e
->
Top
.
Y
<
result
.
top
)
result
.
top
=
e
->
Top
.
Y
;
result
.
top
=
std
::
min
(
result
.
top
,
e
->
Top
.
Y
);
if
(
bottomE
==
lm
->
LeftBound
)
e
=
lm
->
RightBound
;
if
(
bottomE
==
lm
->
LeftBound
)
e
=
lm
->
RightBound
;
else
break
;
else
break
;
}
}
lm
=
lm
->
Next
;
++
lm
;
}
}
return
result
;
return
result
;
}
}
...
@@ -1466,12 +1356,11 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor
...
@@ -1466,12 +1356,11 @@ Clipper::Clipper(int initOptions) : ClipperBase() //constructor
Clipper
::~
Clipper
()
//destructor
Clipper
::~
Clipper
()
//destructor
{
{
Clear
();
Clear
();
m_Scanbeam
.
clear
();
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#ifdef use_xyz
#ifdef use_xyz
void
Clipper
::
ZFillFunction
(
T
ZFillCallback
zFillFunc
)
void
Clipper
::
ZFillFunction
(
ZFillCallback
zFillFunc
)
{
{
m_ZFill
=
zFillFunc
;
m_ZFill
=
zFillFunc
;
}
}
...
@@ -1481,15 +1370,11 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc)
...
@@ -1481,15 +1370,11 @@ void Clipper::ZFillFunction(TZFillCallback zFillFunc)
void
Clipper
::
Reset
()
void
Clipper
::
Reset
()
{
{
ClipperBase
::
Reset
();
ClipperBase
::
Reset
();
m_Scanbeam
.
clear
();
m_Scanbeam
=
ScanbeamList
();
m_ActiveEdges
=
0
;
m_ActiveEdges
=
0
;
m_SortedEdges
=
0
;
m_SortedEdges
=
0
;
LocalMinima
*
lm
=
m_MinimaList
;
for
(
MinimaList
::
iterator
lm
=
m_MinimaList
.
begin
();
lm
!=
m_MinimaList
.
end
();
++
lm
)
while
(
lm
)
{
InsertScanbeam
(
lm
->
Y
);
InsertScanbeam
(
lm
->
Y
);
lm
=
lm
->
Next
;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1550,7 +1435,7 @@ bool Clipper::ExecuteInternal()
...
@@ -1550,7 +1435,7 @@ bool Clipper::ExecuteInternal()
bool
succeeded
=
true
;
bool
succeeded
=
true
;
try
{
try
{
Reset
();
Reset
();
if
(
!
m_CurrentLM
)
return
fals
e
;
if
(
m_CurrentLM
==
m_MinimaList
.
end
())
return
tru
e
;
cInt
botY
=
PopScanbeam
();
cInt
botY
=
PopScanbeam
();
do
{
do
{
InsertLocalMinimaIntoAEL
(
botY
);
InsertLocalMinimaIntoAEL
(
botY
);
...
@@ -1558,11 +1443,11 @@ bool Clipper::ExecuteInternal()
...
@@ -1558,11 +1443,11 @@ bool Clipper::ExecuteInternal()
ProcessHorizontals
(
false
);
ProcessHorizontals
(
false
);
if
(
m_Scanbeam
.
empty
())
break
;
if
(
m_Scanbeam
.
empty
())
break
;
cInt
topY
=
PopScanbeam
();
cInt
topY
=
PopScanbeam
();
succeeded
=
ProcessIntersections
(
botY
,
topY
);
succeeded
=
ProcessIntersections
(
topY
);
if
(
!
succeeded
)
break
;
if
(
!
succeeded
)
break
;
ProcessEdgesAtTopOfScanbeam
(
topY
);
ProcessEdgesAtTopOfScanbeam
(
topY
);
botY
=
topY
;
botY
=
topY
;
}
while
(
!
m_Scanbeam
.
empty
()
||
m_CurrentLM
);
}
while
(
!
m_Scanbeam
.
empty
()
||
m_CurrentLM
!=
m_MinimaList
.
end
()
);
}
}
catch
(...)
catch
(...)
{
{
...
@@ -1601,14 +1486,16 @@ bool Clipper::ExecuteInternal()
...
@@ -1601,14 +1486,16 @@ bool Clipper::ExecuteInternal()
void
Clipper
::
InsertScanbeam
(
const
cInt
Y
)
void
Clipper
::
InsertScanbeam
(
const
cInt
Y
)
{
{
m_Scanbeam
.
insert
(
Y
);
//if (!m_Scanbeam.empty() && Y == m_Scanbeam.top()) return;// avoid duplicates.
m_Scanbeam
.
push
(
Y
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
cInt
Clipper
::
PopScanbeam
()
cInt
Clipper
::
PopScanbeam
()
{
{
cInt
Y
=
*
m_Scanbeam
.
begin
();
const
cInt
Y
=
m_Scanbeam
.
top
();
m_Scanbeam
.
erase
(
m_Scanbeam
.
begin
());
m_Scanbeam
.
pop
();
while
(
!
m_Scanbeam
.
empty
()
&&
Y
==
m_Scanbeam
.
top
())
{
m_Scanbeam
.
pop
();
}
// Pop duplicates.
return
Y
;
return
Y
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1967,7 +1854,7 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
...
@@ -1967,7 +1854,7 @@ void Clipper::AddGhostJoin(OutPt *op, const IntPoint OffPt)
void
Clipper
::
InsertLocalMinimaIntoAEL
(
const
cInt
botY
)
void
Clipper
::
InsertLocalMinimaIntoAEL
(
const
cInt
botY
)
{
{
while
(
m_CurrentLM
&&
(
m_CurrentLM
->
Y
==
botY
)
)
while
(
m_CurrentLM
!=
m_MinimaList
.
end
()
&&
(
m_CurrentLM
->
Y
==
botY
)
)
{
{
TEdge
*
lb
=
m_CurrentLM
->
LeftBound
;
TEdge
*
lb
=
m_CurrentLM
->
LeftBound
;
TEdge
*
rb
=
m_CurrentLM
->
RightBound
;
TEdge
*
rb
=
m_CurrentLM
->
RightBound
;
...
@@ -2018,7 +1905,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
...
@@ -2018,7 +1905,7 @@ void Clipper::InsertLocalMinimaIntoAEL(const cInt botY)
Join
*
jr
=
m_GhostJoins
[
i
];
Join
*
jr
=
m_GhostJoins
[
i
];
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert
//if the horizontal Rb and a 'ghost' horizontal overlap, then convert
//the 'ghost' join to a real join ready for later ...
//the 'ghost' join to a real join ready for later ...
if
(
HorzSegmentsOverlap
(
jr
->
OutPt1
->
Pt
,
jr
->
OffPt
,
rb
->
Bot
,
rb
->
Top
))
if
(
HorzSegmentsOverlap
(
jr
->
OutPt1
->
Pt
.
X
,
jr
->
OffPt
.
X
,
rb
->
Bot
.
X
,
rb
->
Top
.
X
))
AddJoin
(
jr
->
OutPt1
,
Op1
,
jr
->
OffPt
);
AddJoin
(
jr
->
OutPt1
,
Op1
,
jr
->
OffPt
);
}
}
}
}
...
@@ -2088,45 +1975,34 @@ void Clipper::DeleteFromSEL(TEdge *e)
...
@@ -2088,45 +1975,34 @@ void Clipper::DeleteFromSEL(TEdge *e)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#ifdef use_xyz
#ifdef use_xyz
void
Clipper
::
SetZ
(
IntPoint
&
pt
,
TEdge
&
e1
,
TEdge
&
e2
)
void
Clipper
::
SetZ
(
IntPoint
&
pt
,
TEdge
&
e
)
{
{
pt
.
Z
=
0
;
if
(
pt
.
Z
!=
0
||
!
m_ZFill
)
return
;
if
(
m_ZFill
)
else
if
(
pt
==
e1
.
Bot
)
pt
.
Z
=
e1
.
Bot
.
Z
;
{
else
if
(
pt
==
e1
.
Top
)
pt
.
Z
=
e1
.
Top
.
Z
;
//put the 'preferred' point as first parameter ...
else
if
(
pt
==
e2
.
Bot
)
pt
.
Z
=
e2
.
Bot
.
Z
;
if
(
e
.
OutIdx
<
0
)
else
if
(
pt
==
e2
.
Top
)
pt
.
Z
=
e2
.
Top
.
Z
;
(
*
m_ZFill
)(
e
.
Bot
,
e
.
Top
,
pt
);
//outside a path so presume entering
else
(
*
m_ZFill
)(
e1
.
Bot
,
e1
.
Top
,
e2
.
Bot
,
e2
.
Top
,
pt
);
else
(
*
m_ZFill
)(
e
.
Top
,
e
.
Bot
,
pt
);
//inside a path so presume exiting
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#endif
#endif
void
Clipper
::
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
void
Clipper
::
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
IntPoint
&
Pt
)
const
IntPoint
&
Pt
,
bool
protect
)
{
{
//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 ...
bool
e1stops
=
!
protect
&&
!
e1
->
NextInLML
&&
e1
->
Top
.
X
==
Pt
.
X
&&
e1
->
Top
.
Y
==
Pt
.
Y
;
bool
e2stops
=
!
protect
&&
!
e2
->
NextInLML
&&
e2
->
Top
.
X
==
Pt
.
X
&&
e2
->
Top
.
Y
==
Pt
.
Y
;
bool
e1Contributing
=
(
e1
->
OutIdx
>=
0
);
bool
e1Contributing
=
(
e1
->
OutIdx
>=
0
);
bool
e2Contributing
=
(
e2
->
OutIdx
>=
0
);
bool
e2Contributing
=
(
e2
->
OutIdx
>=
0
);
#ifdef use_xyz
SetZ
(
Pt
,
*
e1
,
*
e2
);
#endif
#ifdef use_lines
#ifdef use_lines
//if either edge is on an OPEN path ...
//if either edge is on an OPEN path ...
if
(
e1
->
WindDelta
==
0
||
e2
->
WindDelta
==
0
)
if
(
e1
->
WindDelta
==
0
||
e2
->
WindDelta
==
0
)
{
{
//ignore subject-subject open path intersections UNLESS they
//ignore subject-subject open path intersections UNLESS they
//are both open paths, AND they are both 'contributing maximas' ...
//are both open paths, AND they are both 'contributing maximas' ...
if
(
e1
->
WindDelta
==
0
&&
e2
->
WindDelta
==
0
)
if
(
e1
->
WindDelta
==
0
&&
e2
->
WindDelta
==
0
)
return
;
{
if
((
e1stops
||
e2stops
)
&&
e1Contributing
&&
e2Contributing
)
AddLocalMaxPoly
(
e1
,
e2
,
Pt
);
}
//if intersecting a subj line with a subj poly ...
//if intersecting a subj line with a subj poly ...
else
if
(
e1
->
PolyTyp
==
e2
->
PolyTyp
&&
else
if
(
e1
->
PolyTyp
==
e2
->
PolyTyp
&&
...
@@ -2165,13 +2041,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -2165,13 +2041,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
if
(
e2Contributing
)
e2
->
OutIdx
=
Unassigned
;
if
(
e2Contributing
)
e2
->
OutIdx
=
Unassigned
;
}
}
}
}
if
(
e1stops
)
if
(
e1
->
OutIdx
<
0
)
DeleteFromAEL
(
e1
);
else
throw
clipperException
(
"Error intersecting polylines"
);
if
(
e2stops
)
if
(
e2
->
OutIdx
<
0
)
DeleteFromAEL
(
e2
);
else
throw
clipperException
(
"Error intersecting polylines"
);
return
;
return
;
}
}
#endif
#endif
...
@@ -2236,10 +2105,11 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -2236,10 +2105,11 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
if
(
e1Contributing
&&
e2Contributing
)
if
(
e1Contributing
&&
e2Contributing
)
{
{
if
(
e1stops
||
e2stops
||
if
((
e1Wc
!=
0
&&
e1Wc
!=
1
)
||
(
e2Wc
!=
0
&&
e2Wc
!=
1
)
||
(
e1Wc
!=
0
&&
e1Wc
!=
1
)
||
(
e2Wc
!=
0
&&
e2Wc
!=
1
)
||
(
e1
->
PolyTyp
!=
e2
->
PolyTyp
&&
m_ClipType
!=
ctXor
)
)
(
e1
->
PolyTyp
!=
e2
->
PolyTyp
&&
m_ClipType
!=
ctXor
)
)
{
AddLocalMaxPoly
(
e1
,
e2
,
Pt
);
AddLocalMaxPoly
(
e1
,
e2
,
Pt
);
}
else
else
{
{
AddOutPt
(
e1
,
Pt
);
AddOutPt
(
e1
,
Pt
);
...
@@ -2266,8 +2136,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -2266,8 +2136,7 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
SwapPolyIndexes
(
*
e1
,
*
e2
);
SwapPolyIndexes
(
*
e1
,
*
e2
);
}
}
}
}
else
if
(
(
e1Wc
==
0
||
e1Wc
==
1
)
&&
else
if
(
(
e1Wc
==
0
||
e1Wc
==
1
)
&&
(
e2Wc
==
0
||
e2Wc
==
1
))
(
e2Wc
==
0
||
e2Wc
==
1
)
&&
!
e1stops
&&
!
e2stops
)
{
{
//neither edge is currently contributing ...
//neither edge is currently contributing ...
...
@@ -2286,7 +2155,9 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -2286,7 +2155,9 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
}
}
if
(
e1
->
PolyTyp
!=
e2
->
PolyTyp
)
if
(
e1
->
PolyTyp
!=
e2
->
PolyTyp
)
{
AddLocalMinPoly
(
e1
,
e2
,
Pt
);
AddLocalMinPoly
(
e1
,
e2
,
Pt
);
}
else
if
(
e1Wc
==
1
&&
e2Wc
==
1
)
else
if
(
e1Wc
==
1
&&
e2Wc
==
1
)
switch
(
m_ClipType
)
{
switch
(
m_ClipType
)
{
case
ctIntersection
:
case
ctIntersection
:
...
@@ -2308,17 +2179,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
...
@@ -2308,17 +2179,6 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2,
else
else
SwapSides
(
*
e1
,
*
e2
);
SwapSides
(
*
e1
,
*
e2
);
}
}
if
(
(
e1stops
!=
e2stops
)
&&
(
(
e1stops
&&
(
e1
->
OutIdx
>=
0
))
||
(
e2stops
&&
(
e2
->
OutIdx
>=
0
))
)
)
{
SwapSides
(
*
e1
,
*
e2
);
SwapPolyIndexes
(
*
e1
,
*
e2
);
}
//finally, delete any non-contributing maxima edges ...
if
(
e1stops
)
DeleteFromAEL
(
e1
);
if
(
e2stops
)
DeleteFromAEL
(
e2
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -2509,12 +2369,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
...
@@ -2509,12 +2369,7 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
newOp
->
Prev
=
newOp
;
newOp
->
Prev
=
newOp
;
if
(
!
outRec
->
IsOpen
)
if
(
!
outRec
->
IsOpen
)
SetHoleState
(
e
,
outRec
);
SetHoleState
(
e
,
outRec
);
#ifdef use_xyz
e
->
OutIdx
=
outRec
->
Idx
;
if
(
pt
==
e
->
Bot
)
newOp
->
Pt
=
e
->
Bot
;
else
if
(
pt
==
e
->
Top
)
newOp
->
Pt
=
e
->
Top
;
else
SetZ
(
newOp
->
Pt
,
*
e
);
#endif
e
->
OutIdx
=
outRec
->
Idx
;
//nb: do this after SetZ !
return
newOp
;
return
newOp
;
}
else
}
else
{
{
...
@@ -2533,11 +2388,6 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
...
@@ -2533,11 +2388,6 @@ OutPt* Clipper::AddOutPt(TEdge *e, const IntPoint &pt)
newOp
->
Prev
->
Next
=
newOp
;
newOp
->
Prev
->
Next
=
newOp
;
op
->
Prev
=
newOp
;
op
->
Prev
=
newOp
;
if
(
ToFront
)
outRec
->
Pts
=
newOp
;
if
(
ToFront
)
outRec
->
Pts
=
newOp
;
#ifdef use_xyz
if
(
pt
==
e
->
Bot
)
newOp
->
Pt
=
e
->
Bot
;
else
if
(
pt
==
e
->
Top
)
newOp
->
Pt
=
e
->
Top
;
else
SetZ
(
newOp
->
Pt
,
*
e
);
#endif
return
newOp
;
return
newOp
;
}
}
}
}
...
@@ -2704,37 +2554,6 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
...
@@ -2704,37 +2554,6 @@ void GetHorzDirection(TEdge& HorzEdge, Direction& Dir, cInt& Left, cInt& Right)
}
}
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void
Clipper
::
PrepareHorzJoins
(
TEdge
*
horzEdge
,
bool
isTopOfScanbeam
)
{
//get the last Op for this horizontal edge
//the point may be anywhere along the horizontal ...
OutPt
*
outPt
=
m_PolyOuts
[
horzEdge
->
OutIdx
]
->
Pts
;
if
(
horzEdge
->
Side
!=
esLeft
)
outPt
=
outPt
->
Prev
;
//First, match up overlapping horizontal edges (eg when one polygon's
//intermediate horz edge overlaps an intermediate horz edge of another, or
//when one polygon sits on top of another) ...
//for (JoinList::size_type i = 0; i < m_GhostJoins.size(); ++i)
//{
// Join* j = m_GhostJoins[i];
// if (HorzSegmentsOverlap(j->OutPt1->Pt, j->OffPt, horzEdge->Bot, horzEdge->Top))
// AddJoin(j->OutPt1, outPt, j->OffPt);
//}
//Also, since horizontal edges at the top of one SB are often removed from
//the AEL before we process the horizontal edges at the bottom of the next,
//we need to create 'ghost' Join records of 'contrubuting' horizontals that
//we can compare with horizontals at the bottom of the next SB.
if
(
isTopOfScanbeam
)
{
if
(
outPt
->
Pt
==
horzEdge
->
Top
)
AddGhostJoin
(
outPt
,
horzEdge
->
Bot
);
else
AddGhostJoin
(
outPt
,
horzEdge
->
Top
);
}
}
//------------------------------------------------------------------------------
/*******************************************************************************
/*******************************************************************************
* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or *
* Notes: Horizontal edges (HEs) at scanline intersections (ie at the Top or *
* Bottom of a scanbeam) are processed as if layered. The order in which HEs *
* Bottom of a scanbeam) are processed as if layered. The order in which HEs *
...
@@ -2774,28 +2593,42 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
...
@@ -2774,28 +2593,42 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
if
((
dir
==
dLeftToRight
&&
e
->
Curr
.
X
<=
horzRight
)
||
if
((
dir
==
dLeftToRight
&&
e
->
Curr
.
X
<=
horzRight
)
||
(
dir
==
dRightToLeft
&&
e
->
Curr
.
X
>=
horzLeft
))
(
dir
==
dRightToLeft
&&
e
->
Curr
.
X
>=
horzLeft
))
{
{
if
(
horzEdge
->
OutIdx
>=
0
&&
horzEdge
->
WindDelta
!=
0
)
PrepareHorzJoins
(
horzEdge
,
isTopOfScanbeam
);
//so far we're still in range of the horizontal Edge but make sure
//so far we're still in range of the horizontal Edge but make sure
//we're at the last of consec. horizontals when matching with eMaxPair
//we're at the last of consec. horizontals when matching with eMaxPair
if
(
e
==
eMaxPair
&&
IsLastHorz
)
if
(
e
==
eMaxPair
&&
IsLastHorz
)
{
{
if
(
dir
==
dLeftToRight
)
IntersectEdges
(
horzEdge
,
e
,
e
->
Top
);
if
(
horzEdge
->
OutIdx
>=
0
)
else
{
IntersectEdges
(
e
,
horzEdge
,
e
->
Top
);
OutPt
*
op1
=
AddOutPt
(
horzEdge
,
horzEdge
->
Top
);
if
(
eMaxPair
->
OutIdx
>=
0
)
throw
clipperException
(
"ProcessHorizontal error"
);
TEdge
*
eNextHorz
=
m_SortedEdges
;
while
(
eNextHorz
)
{
if
(
eNextHorz
->
OutIdx
>=
0
&&
HorzSegmentsOverlap
(
horzEdge
->
Bot
.
X
,
horzEdge
->
Top
.
X
,
eNextHorz
->
Bot
.
X
,
eNextHorz
->
Top
.
X
))
{
OutPt
*
op2
=
AddOutPt
(
eNextHorz
,
eNextHorz
->
Bot
);
AddJoin
(
op2
,
op1
,
eNextHorz
->
Top
);
}
eNextHorz
=
eNextHorz
->
NextInSEL
;
}
AddGhostJoin
(
op1
,
horzEdge
->
Bot
);
AddLocalMaxPoly
(
horzEdge
,
eMaxPair
,
horzEdge
->
Top
);
}
DeleteFromAEL
(
horzEdge
);
DeleteFromAEL
(
eMaxPair
);
return
;
return
;
}
}
else
if
(
dir
==
dLeftToRight
)
else
if
(
dir
==
dLeftToRight
)
{
{
IntPoint
Pt
=
IntPoint
(
e
->
Curr
.
X
,
horzEdge
->
Curr
.
Y
);
IntPoint
Pt
=
IntPoint
(
e
->
Curr
.
X
,
horzEdge
->
Curr
.
Y
);
IntersectEdges
(
horzEdge
,
e
,
Pt
,
true
);
IntersectEdges
(
horzEdge
,
e
,
Pt
);
}
}
else
else
{
{
IntPoint
Pt
=
IntPoint
(
e
->
Curr
.
X
,
horzEdge
->
Curr
.
Y
);
IntPoint
Pt
=
IntPoint
(
e
->
Curr
.
X
,
horzEdge
->
Curr
.
Y
);
IntersectEdges
(
e
,
horzEdge
,
Pt
,
true
);
IntersectEdges
(
e
,
horzEdge
,
Pt
);
}
}
SwapPositionsInAEL
(
horzEdge
,
e
);
SwapPositionsInAEL
(
horzEdge
,
e
);
}
}
...
@@ -2804,9 +2637,6 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
...
@@ -2804,9 +2637,6 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
e
=
eNext
;
e
=
eNext
;
}
//end while
}
//end while
if
(
horzEdge
->
OutIdx
>=
0
&&
horzEdge
->
WindDelta
!=
0
)
PrepareHorzJoins
(
horzEdge
,
isTopOfScanbeam
);
if
(
horzEdge
->
NextInLML
&&
IsHorizontal
(
*
horzEdge
->
NextInLML
))
if
(
horzEdge
->
NextInLML
&&
IsHorizontal
(
*
horzEdge
->
NextInLML
))
{
{
UpdateEdgeIntoAEL
(
horzEdge
);
UpdateEdgeIntoAEL
(
horzEdge
);
...
@@ -2821,6 +2651,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
...
@@ -2821,6 +2651,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
if
(
horzEdge
->
OutIdx
>=
0
)
if
(
horzEdge
->
OutIdx
>=
0
)
{
{
OutPt
*
op1
=
AddOutPt
(
horzEdge
,
horzEdge
->
Top
);
OutPt
*
op1
=
AddOutPt
(
horzEdge
,
horzEdge
->
Top
);
if
(
isTopOfScanbeam
)
AddGhostJoin
(
op1
,
horzEdge
->
Bot
);
UpdateEdgeIntoAEL
(
horzEdge
);
UpdateEdgeIntoAEL
(
horzEdge
);
if
(
horzEdge
->
WindDelta
==
0
)
return
;
if
(
horzEdge
->
WindDelta
==
0
)
return
;
//nb: HorzEdge is no longer horizontal here
//nb: HorzEdge is no longer horizontal here
...
@@ -2846,22 +2677,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
...
@@ -2846,22 +2677,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge, bool isTopOfScanbeam)
else
else
UpdateEdgeIntoAEL
(
horzEdge
);
UpdateEdgeIntoAEL
(
horzEdge
);
}
}
else
if
(
eMaxPair
)
{
if
(
eMaxPair
->
OutIdx
>=
0
)
{
if
(
dir
==
dLeftToRight
)
IntersectEdges
(
horzEdge
,
eMaxPair
,
horzEdge
->
Top
);
else
else
IntersectEdges
(
eMaxPair
,
horzEdge
,
horzEdge
->
Top
);
if
(
eMaxPair
->
OutIdx
>=
0
)
throw
clipperException
(
"ProcessHorizontal error"
);
}
else
{
DeleteFromAEL
(
horzEdge
);
DeleteFromAEL
(
eMaxPair
);
}
}
else
{
{
if
(
horzEdge
->
OutIdx
>=
0
)
AddOutPt
(
horzEdge
,
horzEdge
->
Top
);
if
(
horzEdge
->
OutIdx
>=
0
)
AddOutPt
(
horzEdge
,
horzEdge
->
Top
);
DeleteFromAEL
(
horzEdge
);
DeleteFromAEL
(
horzEdge
);
...
@@ -2892,11 +2708,11 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
...
@@ -2892,11 +2708,11 @@ void Clipper::UpdateEdgeIntoAEL(TEdge *&e)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool
Clipper
::
ProcessIntersections
(
const
cInt
botY
,
const
cInt
topY
)
bool
Clipper
::
ProcessIntersections
(
const
cInt
topY
)
{
{
if
(
!
m_ActiveEdges
)
return
true
;
if
(
!
m_ActiveEdges
)
return
true
;
try
{
try
{
BuildIntersectList
(
botY
,
topY
);
BuildIntersectList
(
topY
);
size_t
IlSize
=
m_IntersectList
.
size
();
size_t
IlSize
=
m_IntersectList
.
size
();
if
(
IlSize
==
0
)
return
true
;
if
(
IlSize
==
0
)
return
true
;
if
(
IlSize
==
1
||
FixupIntersectionOrder
())
ProcessIntersectList
();
if
(
IlSize
==
1
||
FixupIntersectionOrder
())
ProcessIntersectList
();
...
@@ -2921,7 +2737,7 @@ void Clipper::DisposeIntersectNodes()
...
@@ -2921,7 +2737,7 @@ void Clipper::DisposeIntersectNodes()
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
Clipper
::
BuildIntersectList
(
const
cInt
botY
,
const
cInt
topY
)
void
Clipper
::
BuildIntersectList
(
const
cInt
topY
)
{
{
if
(
!
m_ActiveEdges
)
return
;
if
(
!
m_ActiveEdges
)
return
;
...
@@ -2948,16 +2764,7 @@ void Clipper::BuildIntersectList(const cInt botY, const cInt topY)
...
@@ -2948,16 +2764,7 @@ void Clipper::BuildIntersectList(const cInt botY, const cInt topY)
IntPoint
Pt
;
IntPoint
Pt
;
if
(
e
->
Curr
.
X
>
eNext
->
Curr
.
X
)
if
(
e
->
Curr
.
X
>
eNext
->
Curr
.
X
)
{
{
if
(
!
IntersectPoint
(
*
e
,
*
eNext
,
Pt
,
m_UseFullRange
)
&&
e
->
Curr
.
X
>
eNext
->
Curr
.
X
+
1
)
IntersectPoint
(
*
e
,
*
eNext
,
Pt
);
throw
clipperException
(
"Intersection error"
);
if
(
Pt
.
Y
>
botY
)
{
Pt
.
Y
=
botY
;
if
(
std
::
fabs
(
e
->
Dx
)
>
std
::
fabs
(
eNext
->
Dx
))
Pt
.
X
=
TopX
(
*
eNext
,
botY
);
else
Pt
.
X
=
TopX
(
*
e
,
botY
);
}
IntersectNode
*
newNode
=
new
IntersectNode
;
IntersectNode
*
newNode
=
new
IntersectNode
;
newNode
->
Edge1
=
e
;
newNode
->
Edge1
=
e
;
newNode
->
Edge2
=
eNext
;
newNode
->
Edge2
=
eNext
;
...
@@ -2985,7 +2792,7 @@ void Clipper::ProcessIntersectList()
...
@@ -2985,7 +2792,7 @@ void Clipper::ProcessIntersectList()
{
{
IntersectNode
*
iNode
=
m_IntersectList
[
i
];
IntersectNode
*
iNode
=
m_IntersectList
[
i
];
{
{
IntersectEdges
(
iNode
->
Edge1
,
iNode
->
Edge2
,
iNode
->
Pt
,
true
);
IntersectEdges
(
iNode
->
Edge1
,
iNode
->
Edge2
,
iNode
->
Pt
);
SwapPositionsInAEL
(
iNode
->
Edge1
,
iNode
->
Edge2
);
SwapPositionsInAEL
(
iNode
->
Edge1
,
iNode
->
Edge2
);
}
}
delete
iNode
;
delete
iNode
;
...
@@ -3044,7 +2851,7 @@ void Clipper::DoMaxima(TEdge *e)
...
@@ -3044,7 +2851,7 @@ void Clipper::DoMaxima(TEdge *e)
TEdge
*
eNext
=
e
->
NextInAEL
;
TEdge
*
eNext
=
e
->
NextInAEL
;
while
(
eNext
&&
eNext
!=
eMaxPair
)
while
(
eNext
&&
eNext
!=
eMaxPair
)
{
{
IntersectEdges
(
e
,
eNext
,
e
->
Top
,
true
);
IntersectEdges
(
e
,
eNext
,
e
->
Top
);
SwapPositionsInAEL
(
e
,
eNext
);
SwapPositionsInAEL
(
e
,
eNext
);
eNext
=
e
->
NextInAEL
;
eNext
=
e
->
NextInAEL
;
}
}
...
@@ -3056,7 +2863,9 @@ void Clipper::DoMaxima(TEdge *e)
...
@@ -3056,7 +2863,9 @@ void Clipper::DoMaxima(TEdge *e)
}
}
else
if
(
e
->
OutIdx
>=
0
&&
eMaxPair
->
OutIdx
>=
0
)
else
if
(
e
->
OutIdx
>=
0
&&
eMaxPair
->
OutIdx
>=
0
)
{
{
IntersectEdges
(
e
,
eMaxPair
,
e
->
Top
);
if
(
e
->
OutIdx
>=
0
)
AddLocalMaxPoly
(
e
,
eMaxPair
,
e
->
Top
);
DeleteFromAEL
(
e
);
DeleteFromAEL
(
eMaxPair
);
}
}
#ifdef use_lines
#ifdef use_lines
else
if
(
e
->
WindDelta
==
0
)
else
if
(
e
->
WindDelta
==
0
)
...
@@ -3124,9 +2933,13 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
...
@@ -3124,9 +2933,13 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
if
((
e
->
OutIdx
>=
0
)
&&
(
e
->
WindDelta
!=
0
)
&&
ePrev
&&
(
ePrev
->
OutIdx
>=
0
)
&&
if
((
e
->
OutIdx
>=
0
)
&&
(
e
->
WindDelta
!=
0
)
&&
ePrev
&&
(
ePrev
->
OutIdx
>=
0
)
&&
(
ePrev
->
Curr
.
X
==
e
->
Curr
.
X
)
&&
(
ePrev
->
WindDelta
!=
0
))
(
ePrev
->
Curr
.
X
==
e
->
Curr
.
X
)
&&
(
ePrev
->
WindDelta
!=
0
))
{
{
OutPt
*
op
=
AddOutPt
(
ePrev
,
e
->
Curr
);
IntPoint
pt
=
e
->
Curr
;
OutPt
*
op2
=
AddOutPt
(
e
,
e
->
Curr
);
#ifdef use_xyz
AddJoin
(
op
,
op2
,
e
->
Curr
);
//StrictlySimple (type-3) join
SetZ
(
pt
,
*
ePrev
,
*
e
);
#endif
OutPt
*
op
=
AddOutPt
(
ePrev
,
pt
);
OutPt
*
op2
=
AddOutPt
(
e
,
pt
);
AddJoin
(
op
,
op2
,
pt
);
//StrictlySimple (type-3) join
}
}
}
}
...
@@ -3508,6 +3321,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
...
@@ -3508,6 +3321,7 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
(
j
->
OffPt
==
j
->
OutPt2
->
Pt
))
(
j
->
OffPt
==
j
->
OutPt2
->
Pt
))
{
{
//Strictly Simple join ...
//Strictly Simple join ...
if
(
outRec1
!=
outRec2
)
return
false
;
op1b
=
j
->
OutPt1
->
Next
;
op1b
=
j
->
OutPt1
->
Next
;
while
(
op1b
!=
op1
&&
(
op1b
->
Pt
==
j
->
OffPt
))
while
(
op1b
!=
op1
&&
(
op1b
->
Pt
==
j
->
OffPt
))
op1b
=
op1b
->
Next
;
op1b
=
op1b
->
Next
;
...
@@ -3648,13 +3462,23 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
...
@@ -3648,13 +3462,23 @@ bool Clipper::JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2)
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
Clipper
::
FixupFirstLefts1
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
)
static
OutRec
*
ParseFirstLeft
(
OutRec
*
FirstLeft
)
{
{
while
(
FirstLeft
&&
!
FirstLeft
->
Pts
)
FirstLeft
=
FirstLeft
->
FirstLeft
;
return
FirstLeft
;
}
//------------------------------------------------------------------------------
void
Clipper
::
FixupFirstLefts1
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
)
{
//tests if NewOutRec contains the polygon before reassigning FirstLeft
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
{
{
OutRec
*
outRec
=
m_PolyOuts
[
i
];
OutRec
*
outRec
=
m_PolyOuts
[
i
];
if
(
outRec
->
Pts
&&
outRec
->
FirstLeft
==
OldOutRec
)
if
(
!
outRec
->
Pts
||
!
outRec
->
FirstLeft
)
continue
;
OutRec
*
firstLeft
=
ParseFirstLeft
(
outRec
->
FirstLeft
);
if
(
firstLeft
==
OldOutRec
)
{
{
if
(
Poly2ContainsPoly1
(
outRec
->
Pts
,
NewOutRec
->
Pts
))
if
(
Poly2ContainsPoly1
(
outRec
->
Pts
,
NewOutRec
->
Pts
))
outRec
->
FirstLeft
=
NewOutRec
;
outRec
->
FirstLeft
=
NewOutRec
;
...
@@ -3665,6 +3489,7 @@ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
...
@@ -3665,6 +3489,7 @@ void Clipper::FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec)
void
Clipper
::
FixupFirstLefts2
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
)
void
Clipper
::
FixupFirstLefts2
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
)
{
{
//reassigns FirstLeft WITHOUT testing if NewOutRec contains the polygon
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
for
(
PolyOutList
::
size_type
i
=
0
;
i
<
m_PolyOuts
.
size
();
++
i
)
{
{
OutRec
*
outRec
=
m_PolyOuts
[
i
];
OutRec
*
outRec
=
m_PolyOuts
[
i
];
...
@@ -3673,14 +3498,6 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
...
@@ -3673,14 +3498,6 @@ void Clipper::FixupFirstLefts2(OutRec* OldOutRec, OutRec* NewOutRec)
}
}
//----------------------------------------------------------------------
//----------------------------------------------------------------------
static
OutRec
*
ParseFirstLeft
(
OutRec
*
FirstLeft
)
{
while
(
FirstLeft
&&
!
FirstLeft
->
Pts
)
FirstLeft
=
FirstLeft
->
FirstLeft
;
return
FirstLeft
;
}
//------------------------------------------------------------------------------
void
Clipper
::
JoinCommonEdges
()
void
Clipper
::
JoinCommonEdges
()
{
{
for
(
JoinList
::
size_type
i
=
0
;
i
<
m_Joins
.
size
();
i
++
)
for
(
JoinList
::
size_type
i
=
0
;
i
<
m_Joins
.
size
();
i
++
)
...
@@ -3848,8 +3665,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
...
@@ -3848,8 +3665,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
(
path
[
i
].
Y
==
newNode
->
Contour
[
k
].
Y
&&
(
path
[
i
].
Y
==
newNode
->
Contour
[
k
].
Y
&&
path
[
i
].
X
<
newNode
->
Contour
[
k
].
X
))
k
=
j
;
path
[
i
].
X
<
newNode
->
Contour
[
k
].
X
))
k
=
j
;
}
}
if
((
endType
==
etClosedPolygon
&&
j
<
2
)
||
if
(
endType
==
etClosedPolygon
&&
j
<
2
)
(
endType
!=
etClosedPolygon
&&
j
<
0
))
{
{
delete
newNode
;
delete
newNode
;
return
;
return
;
...
@@ -3859,7 +3675,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
...
@@ -3859,7 +3675,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
//if this path's lowest pt is lower than all the others then update m_lowest
//if this path's lowest pt is lower than all the others then update m_lowest
if
(
endType
!=
etClosedPolygon
)
return
;
if
(
endType
!=
etClosedPolygon
)
return
;
if
(
m_lowest
.
X
<
0
)
if
(
m_lowest
.
X
<
0
)
m_lowest
=
IntPoint
(
0
,
k
);
m_lowest
=
IntPoint
(
m_polyNodes
.
ChildCount
()
-
1
,
k
);
else
else
{
{
IntPoint
ip
=
m_polyNodes
.
Childs
[(
int
)
m_lowest
.
X
]
->
Contour
[(
int
)
m_lowest
.
Y
];
IntPoint
ip
=
m_polyNodes
.
Childs
[(
int
)
m_lowest
.
X
]
->
Contour
[(
int
)
m_lowest
.
Y
];
...
@@ -3965,6 +3781,7 @@ void ClipperOffset::Execute(PolyTree& solution, double delta)
...
@@ -3965,6 +3781,7 @@ void ClipperOffset::Execute(PolyTree& solution, double delta)
PolyNode
*
outerNode
=
solution
.
Childs
[
0
];
PolyNode
*
outerNode
=
solution
.
Childs
[
0
];
solution
.
Childs
.
reserve
(
outerNode
->
ChildCount
());
solution
.
Childs
.
reserve
(
outerNode
->
ChildCount
());
solution
.
Childs
[
0
]
=
outerNode
->
Childs
[
0
];
solution
.
Childs
[
0
]
=
outerNode
->
Childs
[
0
];
solution
.
Childs
[
0
]
->
Parent
=
outerNode
->
Parent
;
for
(
int
i
=
1
;
i
<
outerNode
->
ChildCount
();
++
i
)
for
(
int
i
=
1
;
i
<
outerNode
->
ChildCount
();
++
i
)
solution
.
AddChild
(
*
outerNode
->
Childs
[
i
]);
solution
.
AddChild
(
*
outerNode
->
Childs
[
i
]);
}
}
...
@@ -4149,8 +3966,20 @@ void ClipperOffset::DoOffset(double delta)
...
@@ -4149,8 +3966,20 @@ void ClipperOffset::DoOffset(double delta)
void
ClipperOffset
::
OffsetPoint
(
int
j
,
int
&
k
,
JoinType
jointype
)
void
ClipperOffset
::
OffsetPoint
(
int
j
,
int
&
k
,
JoinType
jointype
)
{
{
//cross product ...
m_sinA
=
(
m_normals
[
k
].
X
*
m_normals
[
j
].
Y
-
m_normals
[
j
].
X
*
m_normals
[
k
].
Y
);
m_sinA
=
(
m_normals
[
k
].
X
*
m_normals
[
j
].
Y
-
m_normals
[
j
].
X
*
m_normals
[
k
].
Y
);
if
(
m_sinA
<
0.00005
&&
m_sinA
>
-
0.00005
)
return
;
if
(
std
::
fabs
(
m_sinA
*
m_delta
)
<
1.0
)
{
//dot product ...
double
cosA
=
(
m_normals
[
k
].
X
*
m_normals
[
j
].
X
+
m_normals
[
j
].
Y
*
m_normals
[
k
].
Y
);
if
(
cosA
>
0
)
// angle => 0 degrees
{
m_destPoly
.
push_back
(
IntPoint
(
Round
(
m_srcPoly
[
j
].
X
+
m_normals
[
k
].
X
*
m_delta
),
Round
(
m_srcPoly
[
j
].
Y
+
m_normals
[
k
].
Y
*
m_delta
)));
return
;
}
//else angle => 180 degrees
}
else
if
(
m_sinA
>
1.0
)
m_sinA
=
1.0
;
else
if
(
m_sinA
>
1.0
)
m_sinA
=
1.0
;
else
if
(
m_sinA
<
-
1.0
)
m_sinA
=
-
1.0
;
else
if
(
m_sinA
<
-
1.0
)
m_sinA
=
-
1.0
;
...
@@ -4204,7 +4033,7 @@ void ClipperOffset::DoRound(int j, int k)
...
@@ -4204,7 +4033,7 @@ void ClipperOffset::DoRound(int j, int k)
{
{
double
a
=
std
::
atan2
(
m_sinA
,
double
a
=
std
::
atan2
(
m_sinA
,
m_normals
[
k
].
X
*
m_normals
[
j
].
X
+
m_normals
[
k
].
Y
*
m_normals
[
j
].
Y
);
m_normals
[
k
].
X
*
m_normals
[
j
].
X
+
m_normals
[
k
].
Y
*
m_normals
[
j
].
Y
);
int
steps
=
(
int
)
Round
(
m_StepsPerRad
*
std
::
fabs
(
a
)
);
int
steps
=
std
::
max
((
int
)
Round
(
m_StepsPerRad
*
std
::
fabs
(
a
)),
1
);
double
X
=
m_normals
[
k
].
X
,
Y
=
m_normals
[
k
].
Y
,
X2
;
double
X
=
m_normals
[
k
].
X
,
Y
=
m_normals
[
k
].
Y
,
X2
;
for
(
int
i
=
0
;
i
<
steps
;
++
i
)
for
(
int
i
=
0
;
i
<
steps
;
++
i
)
...
@@ -4232,7 +4061,7 @@ void Clipper::DoSimplePolygons()
...
@@ -4232,7 +4061,7 @@ void Clipper::DoSimplePolygons()
{
{
OutRec
*
outrec
=
m_PolyOuts
[
i
++
];
OutRec
*
outrec
=
m_PolyOuts
[
i
++
];
OutPt
*
op
=
outrec
->
Pts
;
OutPt
*
op
=
outrec
->
Pts
;
if
(
!
op
)
continue
;
if
(
!
op
||
outrec
->
IsOpen
)
continue
;
do
//for each Pt in Polygon until duplicate found do ...
do
//for each Pt in Polygon until duplicate found do ...
{
{
OutPt
*
op2
=
op
->
Next
;
OutPt
*
op2
=
op
->
Next
;
...
@@ -4257,6 +4086,7 @@ void Clipper::DoSimplePolygons()
...
@@ -4257,6 +4086,7 @@ void Clipper::DoSimplePolygons()
//OutRec2 is contained by OutRec1 ...
//OutRec2 is contained by OutRec1 ...
outrec2
->
IsHole
=
!
outrec
->
IsHole
;
outrec2
->
IsHole
=
!
outrec
->
IsHole
;
outrec2
->
FirstLeft
=
outrec
;
outrec2
->
FirstLeft
=
outrec
;
if
(
m_UsingPolyTree
)
FixupFirstLefts2
(
outrec2
,
outrec
);
}
}
else
else
if
(
Poly2ContainsPoly1
(
outrec
->
Pts
,
outrec2
->
Pts
))
if
(
Poly2ContainsPoly1
(
outrec
->
Pts
,
outrec2
->
Pts
))
...
@@ -4266,11 +4096,14 @@ void Clipper::DoSimplePolygons()
...
@@ -4266,11 +4096,14 @@ void Clipper::DoSimplePolygons()
outrec
->
IsHole
=
!
outrec2
->
IsHole
;
outrec
->
IsHole
=
!
outrec2
->
IsHole
;
outrec2
->
FirstLeft
=
outrec
->
FirstLeft
;
outrec2
->
FirstLeft
=
outrec
->
FirstLeft
;
outrec
->
FirstLeft
=
outrec2
;
outrec
->
FirstLeft
=
outrec2
;
}
else
if
(
m_UsingPolyTree
)
FixupFirstLefts2
(
outrec
,
outrec2
);
}
else
{
{
//the 2 polygons are separate ...
//the 2 polygons are separate ...
outrec2
->
IsHole
=
outrec
->
IsHole
;
outrec2
->
IsHole
=
outrec
->
IsHole
;
outrec2
->
FirstLeft
=
outrec
->
FirstLeft
;
outrec2
->
FirstLeft
=
outrec
->
FirstLeft
;
if
(
m_UsingPolyTree
)
FixupFirstLefts1
(
outrec
,
outrec2
);
}
}
op2
=
op
;
//ie get ready for the Next iteration
op2
=
op
;
//ie get ready for the Next iteration
}
}
...
@@ -4348,7 +4181,27 @@ double DistanceFromLineSqrd(
...
@@ -4348,7 +4181,27 @@ double DistanceFromLineSqrd(
bool
SlopesNearCollinear
(
const
IntPoint
&
pt1
,
bool
SlopesNearCollinear
(
const
IntPoint
&
pt1
,
const
IntPoint
&
pt2
,
const
IntPoint
&
pt3
,
double
distSqrd
)
const
IntPoint
&
pt2
,
const
IntPoint
&
pt3
,
double
distSqrd
)
{
{
//this function is more accurate when the point that's geometrically
//between the other 2 points is the one that's tested for distance.
//ie makes it more likely to pick up 'spikes' ...
if
(
Abs
(
pt1
.
X
-
pt2
.
X
)
>
Abs
(
pt1
.
Y
-
pt2
.
Y
))
{
if
((
pt1
.
X
>
pt2
.
X
)
==
(
pt1
.
X
<
pt3
.
X
))
return
DistanceFromLineSqrd
(
pt1
,
pt2
,
pt3
)
<
distSqrd
;
else
if
((
pt2
.
X
>
pt1
.
X
)
==
(
pt2
.
X
<
pt3
.
X
))
return
DistanceFromLineSqrd
(
pt2
,
pt1
,
pt3
)
<
distSqrd
;
else
return
DistanceFromLineSqrd
(
pt3
,
pt1
,
pt2
)
<
distSqrd
;
}
else
{
if
((
pt1
.
Y
>
pt2
.
Y
)
==
(
pt1
.
Y
<
pt3
.
Y
))
return
DistanceFromLineSqrd
(
pt1
,
pt2
,
pt3
)
<
distSqrd
;
else
if
((
pt2
.
Y
>
pt1
.
Y
)
==
(
pt2
.
Y
<
pt3
.
Y
))
return
DistanceFromLineSqrd
(
pt2
,
pt1
,
pt3
)
<
distSqrd
;
return
DistanceFromLineSqrd
(
pt2
,
pt1
,
pt3
)
<
distSqrd
;
else
return
DistanceFromLineSqrd
(
pt3
,
pt1
,
pt2
)
<
distSqrd
;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -4476,8 +4329,8 @@ void Minkowski(const Path& poly, const Path& path,
...
@@ -4476,8 +4329,8 @@ void Minkowski(const Path& poly, const Path& path,
pp
.
push_back
(
p
);
pp
.
push_back
(
p
);
}
}
Paths
quads
;
solution
.
clear
()
;
quads
.
reserve
((
pathCnt
+
delta
)
*
(
polyCnt
+
1
));
solution
.
reserve
((
pathCnt
+
delta
)
*
(
polyCnt
+
1
));
for
(
size_t
i
=
0
;
i
<
pathCnt
-
1
+
delta
;
++
i
)
for
(
size_t
i
=
0
;
i
<
pathCnt
-
1
+
delta
;
++
i
)
for
(
size_t
j
=
0
;
j
<
polyCnt
;
++
j
)
for
(
size_t
j
=
0
;
j
<
polyCnt
;
++
j
)
{
{
...
@@ -4488,23 +4341,30 @@ void Minkowski(const Path& poly, const Path& path,
...
@@ -4488,23 +4341,30 @@ void Minkowski(const Path& poly, const Path& path,
quad
.
push_back
(
pp
[(
i
+
1
)
%
pathCnt
][(
j
+
1
)
%
polyCnt
]);
quad
.
push_back
(
pp
[(
i
+
1
)
%
pathCnt
][(
j
+
1
)
%
polyCnt
]);
quad
.
push_back
(
pp
[
i
%
pathCnt
][(
j
+
1
)
%
polyCnt
]);
quad
.
push_back
(
pp
[
i
%
pathCnt
][(
j
+
1
)
%
polyCnt
]);
if
(
!
Orientation
(
quad
))
ReversePath
(
quad
);
if
(
!
Orientation
(
quad
))
ReversePath
(
quad
);
quads
.
push_back
(
quad
);
solution
.
push_back
(
quad
);
}
}
}
//------------------------------------------------------------------------------
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Path
&
path
,
Paths
&
solution
,
bool
pathIsClosed
)
{
Minkowski
(
pattern
,
path
,
solution
,
true
,
pathIsClosed
);
Clipper
c
;
Clipper
c
;
c
.
AddPaths
(
quads
,
ptSubject
,
true
);
c
.
AddPaths
(
solution
,
ptSubject
,
true
);
c
.
Execute
(
ctUnion
,
solution
,
pftNonZero
,
pftNonZero
);
c
.
Execute
(
ctUnion
,
solution
,
pftNonZero
,
pftNonZero
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Path
&
path
,
Paths
&
solution
,
bool
pathIsClosed
)
void
TranslatePath
(
const
Path
&
input
,
Path
&
output
,
IntPoint
delta
)
{
{
Minkowski
(
pattern
,
path
,
solution
,
true
,
pathIsClosed
);
//precondition: input != output
output
.
resize
(
input
.
size
());
for
(
size_t
i
=
0
;
i
<
input
.
size
();
++
i
)
output
[
i
]
=
IntPoint
(
input
[
i
].
X
+
delta
.
X
,
input
[
i
].
Y
+
delta
.
Y
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Paths
&
paths
,
Paths
&
solution
,
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Paths
&
paths
,
Paths
&
solution
,
bool
pathIsClosed
)
PolyFillType
pathFillType
,
bool
pathIsClosed
)
{
{
Clipper
c
;
Clipper
c
;
for
(
size_t
i
=
0
;
i
<
paths
.
size
();
++
i
)
for
(
size_t
i
=
0
;
i
<
paths
.
size
();
++
i
)
...
@@ -4512,21 +4372,29 @@ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution,
...
@@ -4512,21 +4372,29 @@ void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution,
Paths
tmp
;
Paths
tmp
;
Minkowski
(
pattern
,
paths
[
i
],
tmp
,
true
,
pathIsClosed
);
Minkowski
(
pattern
,
paths
[
i
],
tmp
,
true
,
pathIsClosed
);
c
.
AddPaths
(
tmp
,
ptSubject
,
true
);
c
.
AddPaths
(
tmp
,
ptSubject
,
true
);
if
(
pathIsClosed
)
{
Path
tmp2
;
TranslatePath
(
paths
[
i
],
tmp2
,
pattern
[
0
]);
c
.
AddPath
(
tmp2
,
ptClip
,
true
);
}
}
if
(
pathIsClosed
)
c
.
AddPaths
(
paths
,
ptClip
,
true
);
}
c
.
Execute
(
ctUnion
,
solution
,
pathFillType
,
pathFillType
);
c
.
Execute
(
ctUnion
,
solution
,
pftNonZero
,
pftNonZero
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
MinkowskiDiff
(
const
Path
&
poly1
,
const
Path
&
poly2
,
Paths
&
solution
)
void
MinkowskiDiff
(
const
Path
&
poly1
,
const
Path
&
poly2
,
Paths
&
solution
)
{
{
Minkowski
(
poly1
,
poly2
,
solution
,
false
,
true
);
Minkowski
(
poly1
,
poly2
,
solution
,
false
,
true
);
Clipper
c
;
c
.
AddPaths
(
solution
,
ptSubject
,
true
);
c
.
Execute
(
ctUnion
,
solution
,
pftNonZero
,
pftNonZero
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
enum
NodeType
{
ntAny
,
ntOpen
,
ntClosed
};
enum
NodeType
{
ntAny
,
ntOpen
,
ntClosed
};
void
AddPolyNodeToP
olygon
s
(
const
PolyNode
&
polynode
,
NodeType
nodetype
,
Paths
&
paths
)
void
AddPolyNodeToP
ath
s
(
const
PolyNode
&
polynode
,
NodeType
nodetype
,
Paths
&
paths
)
{
{
bool
match
=
true
;
bool
match
=
true
;
if
(
nodetype
==
ntClosed
)
match
=
!
polynode
.
IsOpen
();
if
(
nodetype
==
ntClosed
)
match
=
!
polynode
.
IsOpen
();
...
@@ -4535,7 +4403,7 @@ void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& p
...
@@ -4535,7 +4403,7 @@ void AddPolyNodeToPolygons(const PolyNode& polynode, NodeType nodetype, Paths& p
if
(
!
polynode
.
Contour
.
empty
()
&&
match
)
if
(
!
polynode
.
Contour
.
empty
()
&&
match
)
paths
.
push_back
(
polynode
.
Contour
);
paths
.
push_back
(
polynode
.
Contour
);
for
(
int
i
=
0
;
i
<
polynode
.
ChildCount
();
++
i
)
for
(
int
i
=
0
;
i
<
polynode
.
ChildCount
();
++
i
)
AddPolyNodeToP
olygon
s
(
*
polynode
.
Childs
[
i
],
nodetype
,
paths
);
AddPolyNodeToP
ath
s
(
*
polynode
.
Childs
[
i
],
nodetype
,
paths
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -4543,7 +4411,7 @@ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
...
@@ -4543,7 +4411,7 @@ void PolyTreeToPaths(const PolyTree& polytree, Paths& paths)
{
{
paths
.
resize
(
0
);
paths
.
resize
(
0
);
paths
.
reserve
(
polytree
.
Total
());
paths
.
reserve
(
polytree
.
Total
());
AddPolyNodeToP
olygon
s
(
polytree
,
ntAny
,
paths
);
AddPolyNodeToP
ath
s
(
polytree
,
ntAny
,
paths
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -4551,7 +4419,7 @@ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
...
@@ -4551,7 +4419,7 @@ void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths)
{
{
paths
.
resize
(
0
);
paths
.
resize
(
0
);
paths
.
reserve
(
polytree
.
Total
());
paths
.
reserve
(
polytree
.
Total
());
AddPolyNodeToP
olygon
s
(
polytree
,
ntClosed
,
paths
);
AddPolyNodeToP
ath
s
(
polytree
,
ntClosed
,
paths
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -4593,18 +4461,4 @@ std::ostream& operator <<(std::ostream &s, const Paths &p)
...
@@ -4593,18 +4461,4 @@ std::ostream& operator <<(std::ostream &s, const Paths &p)
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#ifdef use_deprecated
void
OffsetPaths
(
const
Paths
&
in_polys
,
Paths
&
out_polys
,
double
delta
,
JoinType
jointype
,
EndType_
endtype
,
double
limit
)
{
ClipperOffset
co
(
limit
,
limit
);
co
.
AddPaths
(
in_polys
,
jointype
,
(
EndType
)
endtype
);
co
.
Execute
(
out_polys
,
delta
);
}
//------------------------------------------------------------------------------
#endif
}
//ClipperLib namespace
}
//ClipperLib namespace
polygon/clipper.hpp
View file @
8da93abc
/*******************************************************************************
/*******************************************************************************
* *
* *
* Author : Angus Johnson *
* Author : Angus Johnson *
* Version : 6.
1.3a
*
* Version : 6.
2.1
*
* Date :
22 January
2014 *
* Date :
31 October
2014 *
* Website : http://www.angusj.com *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2014 *
* Copyright : Angus Johnson 2010-2014 *
* *
* *
...
@@ -34,7 +34,7 @@
...
@@ -34,7 +34,7 @@
#ifndef clipper_hpp
#ifndef clipper_hpp
#define clipper_hpp
#define clipper_hpp
#define CLIPPER_VERSION "6.
1.3
"
#define CLIPPER_VERSION "6.
2.0
"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//improve performance but coordinate values are limited to the range +/- 46340
...
@@ -46,9 +46,8 @@
...
@@ -46,9 +46,8 @@
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//use_lines: Enables line clipping. Adds a very minor cost to performance.
//#define use_lines
//#define use_lines
//use_deprecated: Enables support for the obsolete OffsetPaths() function
//use_deprecated: Enables temporary support for the obsolete functions
//which has been replace with the ClipperOffset class.
//#define use_deprecated
#define use_deprecated
#include <vector>
#include <vector>
#include <set>
#include <set>
...
@@ -57,6 +56,7 @@
...
@@ -57,6 +56,7 @@
#include <cstdlib>
#include <cstdlib>
#include <ostream>
#include <ostream>
#include <functional>
#include <functional>
#include <queue>
namespace
ClipperLib
{
namespace
ClipperLib
{
...
@@ -69,11 +69,16 @@ enum PolyType { ptSubject, ptClip };
...
@@ -69,11 +69,16 @@ enum PolyType { ptSubject, ptClip };
enum
PolyFillType
{
pftEvenOdd
,
pftNonZero
,
pftPositive
,
pftNegative
};
enum
PolyFillType
{
pftEvenOdd
,
pftNonZero
,
pftPositive
,
pftNegative
};
#ifdef use_int32
#ifdef use_int32
typedef
int
cInt
;
typedef
int
cInt
;
typedef
unsigned
int
cUInt
;
static
cInt
const
loRange
=
0x7FFF
;
static
cInt
const
hiRange
=
0x7FFF
;
#else
#else
typedef
signed
long
long
cInt
;
typedef
signed
long
long
cInt
;
typedef
unsigned
long
long
cUInt
;
static
cInt
const
loRange
=
0x3FFFFFFF
;
static
cInt
const
hiRange
=
0x3FFFFFFFFFFFFFFFLL
;
typedef
signed
long
long
long64
;
//used by Int128 class
typedef
unsigned
long
long
ulong64
;
#endif
#endif
struct
IntPoint
{
struct
IntPoint
{
...
@@ -117,15 +122,12 @@ struct DoublePoint
...
@@ -117,15 +122,12 @@ struct DoublePoint
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#ifdef use_xyz
#ifdef use_xyz
typedef
void
(
*
TZFillCallback
)(
IntPoint
&
z1
,
IntPoint
&
z2
,
IntPoint
&
pt
);
typedef
void
(
*
ZFillCallback
)(
IntPoint
&
e1bot
,
IntPoint
&
e1top
,
IntPoint
&
e2bot
,
IntPoint
&
e2top
,
IntPoint
&
pt
);
#endif
#endif
enum
InitOptions
{
ioReverseSolution
=
1
,
ioStrictlySimple
=
2
,
ioPreserveCollinear
=
4
};
enum
InitOptions
{
ioReverseSolution
=
1
,
ioStrictlySimple
=
2
,
ioPreserveCollinear
=
4
};
enum
JoinType
{
jtSquare
,
jtRound
,
jtMiter
};
enum
JoinType
{
jtSquare
,
jtRound
,
jtMiter
};
enum
EndType
{
etClosedPolygon
,
etClosedLine
,
etOpenButt
,
etOpenSquare
,
etOpenRound
};
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
;
...
@@ -134,6 +136,7 @@ class PolyNode
...
@@ -134,6 +136,7 @@ class PolyNode
{
{
public
:
public
:
PolyNode
();
PolyNode
();
virtual
~
PolyNode
(){};
Path
Contour
;
Path
Contour
;
PolyNodes
Childs
;
PolyNodes
Childs
;
PolyNode
*
Parent
;
PolyNode
*
Parent
;
...
@@ -168,11 +171,6 @@ bool Orientation(const Path &poly);
...
@@ -168,11 +171,6 @@ bool Orientation(const Path &poly);
double
Area
(
const
Path
&
poly
);
double
Area
(
const
Path
&
poly
);
int
PointInPolygon
(
const
IntPoint
&
pt
,
const
Path
&
path
);
int
PointInPolygon
(
const
IntPoint
&
pt
,
const
Path
&
path
);
#ifdef use_deprecated
void
OffsetPaths
(
const
Paths
&
in_polys
,
Paths
&
out_polys
,
double
delta
,
JoinType
jointype
,
EndType_
endtype
,
double
limit
=
0
);
#endif
void
SimplifyPolygon
(
const
Path
&
in_poly
,
Paths
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
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
(
const
Paths
&
in_polys
,
Paths
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
Paths
&
polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
Paths
&
polys
,
PolyFillType
fillType
=
pftEvenOdd
);
...
@@ -183,8 +181,7 @@ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.
...
@@ -183,8 +181,7 @@ void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.
void
CleanPolygons
(
Paths
&
polys
,
double
distance
=
1.415
);
void
CleanPolygons
(
Paths
&
polys
,
double
distance
=
1.415
);
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Path
&
path
,
Paths
&
solution
,
bool
pathIsClosed
);
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Path
&
path
,
Paths
&
solution
,
bool
pathIsClosed
);
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Paths
&
paths
,
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Paths
&
paths
,
Paths
&
solution
,
bool
pathIsClosed
);
Paths
&
solution
,
PolyFillType
pathFillType
,
bool
pathIsClosed
);
void
MinkowskiDiff
(
const
Path
&
poly1
,
const
Path
&
poly2
,
Paths
&
solution
);
void
MinkowskiDiff
(
const
Path
&
poly1
,
const
Path
&
poly2
,
Paths
&
solution
);
void
PolyTreeToPaths
(
const
PolyTree
&
polytree
,
Paths
&
paths
);
void
PolyTreeToPaths
(
const
PolyTree
&
polytree
,
Paths
&
paths
);
...
@@ -202,7 +199,7 @@ enum EdgeSide { esLeft = 1, esRight = 2};
...
@@ -202,7 +199,7 @@ enum EdgeSide { esLeft = 1, esRight = 2};
//forward declarations (for stuff used internally) ...
//forward declarations (for stuff used internally) ...
struct
TEdge
;
struct
TEdge
;
struct
IntersectNode
;
struct
IntersectNode
;
struct
LocalMinim
a
;
struct
LocalMinim
um
;
struct
Scanbeam
;
struct
Scanbeam
;
struct
OutPt
;
struct
OutPt
;
struct
OutRec
;
struct
OutRec
;
...
@@ -213,7 +210,6 @@ typedef std::vector < TEdge* > EdgeList;
...
@@ -213,7 +210,6 @@ typedef std::vector < TEdge* > EdgeList;
typedef
std
::
vector
<
Join
*
>
JoinList
;
typedef
std
::
vector
<
Join
*
>
JoinList
;
typedef
std
::
vector
<
IntersectNode
*
>
IntersectList
;
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
...
@@ -236,12 +232,14 @@ protected:
...
@@ -236,12 +232,14 @@ protected:
void
PopLocalMinima
();
void
PopLocalMinima
();
virtual
void
Reset
();
virtual
void
Reset
();
TEdge
*
ProcessBound
(
TEdge
*
E
,
bool
IsClockwise
);
TEdge
*
ProcessBound
(
TEdge
*
E
,
bool
IsClockwise
);
void
InsertLocalMinima
(
LocalMinima
*
newLm
);
void
DoMinimaLML
(
TEdge
*
E1
,
TEdge
*
E2
,
bool
IsClosed
);
void
DoMinimaLML
(
TEdge
*
E1
,
TEdge
*
E2
,
bool
IsClosed
);
TEdge
*
DescendToMin
(
TEdge
*&
E
);
TEdge
*
DescendToMin
(
TEdge
*&
E
);
void
AscendToMax
(
TEdge
*&
E
,
bool
Appending
,
bool
IsClosed
);
void
AscendToMax
(
TEdge
*&
E
,
bool
Appending
,
bool
IsClosed
);
LocalMinima
*
m_CurrentLM
;
LocalMinima
*
m_MinimaList
;
typedef
std
::
vector
<
LocalMinimum
>
MinimaList
;
MinimaList
::
iterator
m_CurrentLM
;
MinimaList
m_MinimaList
;
bool
m_UseFullRange
;
bool
m_UseFullRange
;
EdgeList
m_edges
;
EdgeList
m_edges
;
bool
m_PreserveCollinear
;
bool
m_PreserveCollinear
;
...
@@ -268,7 +266,7 @@ public:
...
@@ -268,7 +266,7 @@ public:
void
StrictlySimple
(
bool
value
)
{
m_StrictSimple
=
value
;};
void
StrictlySimple
(
bool
value
)
{
m_StrictSimple
=
value
;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
#ifdef use_xyz
void
ZFillFunction
(
T
ZFillCallback
zFillFunc
);
void
ZFillFunction
(
ZFillCallback
zFillFunc
);
#endif
#endif
protected
:
protected
:
void
Reset
();
void
Reset
();
...
@@ -279,7 +277,8 @@ private:
...
@@ -279,7 +277,8 @@ private:
JoinList
m_GhostJoins
;
JoinList
m_GhostJoins
;
IntersectList
m_IntersectList
;
IntersectList
m_IntersectList
;
ClipType
m_ClipType
;
ClipType
m_ClipType
;
std
::
set
<
cInt
,
std
::
greater
<
cInt
>
>
m_Scanbeam
;
typedef
std
::
priority_queue
<
cInt
>
ScanbeamList
;
ScanbeamList
m_Scanbeam
;
TEdge
*
m_ActiveEdges
;
TEdge
*
m_ActiveEdges
;
TEdge
*
m_SortedEdges
;
TEdge
*
m_SortedEdges
;
bool
m_ExecuteLocked
;
bool
m_ExecuteLocked
;
...
@@ -289,7 +288,7 @@ private:
...
@@ -289,7 +288,7 @@ private:
bool
m_UsingPolyTree
;
bool
m_UsingPolyTree
;
bool
m_StrictSimple
;
bool
m_StrictSimple
;
#ifdef use_xyz
#ifdef use_xyz
T
ZFillCallback
m_ZFill
;
//custom callback
ZFillCallback
m_ZFill
;
//custom callback
#endif
#endif
void
SetWindingCount
(
TEdge
&
edge
);
void
SetWindingCount
(
TEdge
&
edge
);
bool
IsEvenOddFillType
(
const
TEdge
&
edge
)
const
;
bool
IsEvenOddFillType
(
const
TEdge
&
edge
)
const
;
...
@@ -308,21 +307,19 @@ private:
...
@@ -308,21 +307,19 @@ private:
bool
IsTopHorz
(
const
cInt
XPos
);
bool
IsTopHorz
(
const
cInt
XPos
);
void
SwapPositionsInAEL
(
TEdge
*
edge1
,
TEdge
*
edge2
);
void
SwapPositionsInAEL
(
TEdge
*
edge1
,
TEdge
*
edge2
);
void
DoMaxima
(
TEdge
*
e
);
void
DoMaxima
(
TEdge
*
e
);
void
PrepareHorzJoins
(
TEdge
*
horzEdge
,
bool
isTopOfScanbeam
);
void
ProcessHorizontals
(
bool
IsTopOfScanbeam
);
void
ProcessHorizontals
(
bool
IsTopOfScanbeam
);
void
ProcessHorizontal
(
TEdge
*
horzEdge
,
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
);
OutPt
*
AddLocalMinPoly
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
);
OutPt
*
AddLocalMinPoly
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
);
OutRec
*
GetOutRec
(
int
idx
);
OutRec
*
GetOutRec
(
int
idx
);
void
AppendPolygon
(
TEdge
*
e1
,
TEdge
*
e2
);
void
AppendPolygon
(
TEdge
*
e1
,
TEdge
*
e2
);
void
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
void
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
IntPoint
&
pt
);
const
IntPoint
&
pt
,
bool
protect
=
false
);
OutRec
*
CreateOutRec
();
OutRec
*
CreateOutRec
();
OutPt
*
AddOutPt
(
TEdge
*
e
,
const
IntPoint
&
pt
);
OutPt
*
AddOutPt
(
TEdge
*
e
,
const
IntPoint
&
pt
);
void
DisposeAllOutRecs
();
void
DisposeAllOutRecs
();
void
DisposeOutRec
(
PolyOutList
::
size_type
index
);
void
DisposeOutRec
(
PolyOutList
::
size_type
index
);
bool
ProcessIntersections
(
const
cInt
botY
,
const
cInt
topY
);
bool
ProcessIntersections
(
const
cInt
topY
);
void
BuildIntersectList
(
const
cInt
botY
,
const
cInt
topY
);
void
BuildIntersectList
(
const
cInt
topY
);
void
ProcessIntersectList
();
void
ProcessIntersectList
();
void
ProcessEdgesAtTopOfScanbeam
(
const
cInt
topY
);
void
ProcessEdgesAtTopOfScanbeam
(
const
cInt
topY
);
void
BuildResult
(
Paths
&
polys
);
void
BuildResult
(
Paths
&
polys
);
...
@@ -344,7 +341,7 @@ private:
...
@@ -344,7 +341,7 @@ private:
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
#ifdef use_xyz
void
SetZ
(
IntPoint
&
pt
,
TEdge
&
e
);
void
SetZ
(
IntPoint
&
pt
,
TEdge
&
e
1
,
TEdge
&
e2
);
#endif
#endif
};
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
...
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