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
4ce4631d
Commit
4ce4631d
authored
Dec 08, 2007
by
raburton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
set eol-style and mime-type properties for new polygon related files
parent
dab0fd9e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1657 additions
and
1657 deletions
+1657
-1657
GenericPolygonClipperLibrary.cpp
polygon/GenericPolygonClipperLibrary.cpp
+1
-1
GenericPolygonClipperLibraryVERSIONS.TXT
polygon/GenericPolygonClipperLibraryVERSIONS.TXT
+123
-123
defs-macros.h
polygon/defs-macros.h
+32
-32
links.txt
polygon/links.txt
+17
-17
makefile.g95
polygon/makefile.g95
+18
-18
makefile.gtk
polygon/makefile.gtk
+37
-37
makefile.include
polygon/makefile.include
+16
-16
makefile.macosx
polygon/makefile.macosx
+26
-26
php_polygon.cpp
polygon/php_polygon.cpp
+1101
-1101
php_polygon.h
polygon/php_polygon.h
+61
-61
php_polygon_vertex.cpp
polygon/php_polygon_vertex.cpp
+144
-144
php_polygon_vertex.h
polygon/php_polygon_vertex.h
+81
-81
No files found.
polygon/GenericPolygonClipperLibrary.cpp
View file @
4ce4631d
...
@@ -1741,7 +1741,7 @@ void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
...
@@ -1741,7 +1741,7 @@ void gpc_polygon_clip(gpc_op op, gpc_polygon *subj, gpc_polygon *clip,
npoly
=
poly
->
next
;
npoly
=
poly
->
next
;
FREE
(
poly
);
FREE
(
poly
);
}
}
}
}
/* Tidy up */
/* Tidy up */
reset_it
(
&
it
);
reset_it
(
&
it
);
...
...
polygon/GenericPolygonClipperLibraryVERSIONS.TXT
View file @
4ce4631d
Generic Polygon Clipper (gpc) Revision History
Generic Polygon Clipper (gpc) Revision History
==============================================
==============================================
v2.32 17th Dec 2004
v2.32 17th Dec 2004
---------------------
---------------------
Fixed occasional memory leak occurring when processing some
Fixed occasional memory leak occurring when processing some
degenerate polygon arrangements.
degenerate polygon arrangements.
Added explicit type casting to memory allocator in support of
Added explicit type casting to memory allocator in support of
increased code portability.
increased code portability.
v2.31 4th Jun 1999
v2.31 4th Jun 1999
---------------------
---------------------
Separated edge merging measure based on a user-defined GPC_EPSILON
Separated edge merging measure based on a user-defined GPC_EPSILON
value from general numeric equality testing and ordering, which now
value from general numeric equality testing and ordering, which now
uses direct arithmetic comparison rather an EPSILON based proximity
uses direct arithmetic comparison rather an EPSILON based proximity
test.
test.
Fixed problem with numerical equality test during construction of
Fixed problem with numerical equality test during construction of
local minima and scanbeam tables, leading to occasional crash.
local minima and scanbeam tables, leading to occasional crash.
Fixed hole array memory leak in gpc_add_contour.
Fixed hole array memory leak in gpc_add_contour.
Fixed uninitialised hole field bug in gpc_polygon_clip result.
Fixed uninitialised hole field bug in gpc_polygon_clip result.
v2.30 11th Apr 1999
v2.30 11th Apr 1999
---------------------
---------------------
Major re-write.
Major re-write.
Minor API change: additional 'hole' array field added to gpc_polygon
Minor API change: additional 'hole' array field added to gpc_polygon
datatype to indicate which constituent contours are internal holes,
datatype to indicate which constituent contours are internal holes,
and which form external boundaries.
and which form external boundaries.
Minor API change: additional 'hole' argument to gpc_add_contour
Minor API change: additional 'hole' argument to gpc_add_contour
to indicate whether the new contour is a hole or external contour.
to indicate whether the new contour is a hole or external contour.
Minor API change: additional parameter to gpc_read_polygon and
Minor API change: additional parameter to gpc_read_polygon and
gpc_write_polygon to indicate whether or not to read or write
gpc_write_polygon to indicate whether or not to read or write
contour hole flags.
contour hole flags.
Fixed NULL pointer bug in add/merge left/right operations.
Fixed NULL pointer bug in add/merge left/right operations.
Fixed numerical problem in intersection table generation.
Fixed numerical problem in intersection table generation.
Fixed zero byte malloc problem.
Fixed zero byte malloc problem.
Fixed problem producing occasional 2 vertex contours.
Fixed problem producing occasional 2 vertex contours.
Added bounding box test optimisations.
Added bounding box test optimisations.
Simplified edge bundle creation, detection of scanbeam internal
Simplified edge bundle creation, detection of scanbeam internal
edge intersections and tristrip scanbeam boundary code.
edge intersections and tristrip scanbeam boundary code.
Renamed 'class' variable to be C++ friendly.
Renamed 'class' variable to be C++ friendly.
v2.22 17th Oct 1998
v2.22 17th Oct 1998
---------------------
---------------------
Re-implemented edge interpolation and intersection calculations
Re-implemented edge interpolation and intersection calculations
to improve numerical robustness.
to improve numerical robustness.
Simplified setting of GPC_EPSILON.
Simplified setting of GPC_EPSILON.
v2.21 19th Aug 1998
v2.21 19th Aug 1998
---------------------
---------------------
Fixed problem causing occasional incorrect output when processing
Fixed problem causing occasional incorrect output when processing
self-intersecting polygons (bow-ties etc).
self-intersecting polygons (bow-ties etc).
Removed bug which may lead to non-generation of uppermost triangle
Removed bug which may lead to non-generation of uppermost triangle
in tristrip output.
in tristrip output.
v2.20 26th May 1998
v2.20 26th May 1998
---------------------
---------------------
Major re-write.
Major re-write.
Added exclusive-or polygon set operation.
Added exclusive-or polygon set operation.
Replaced table-based processing of edge intersections with
Replaced table-based processing of edge intersections with
rule-based system.
rule-based system.
Replaced two-pass approach to scanbeam interior processing with
Replaced two-pass approach to scanbeam interior processing with
single pass method.
single pass method.
v2.10a 14th May 1998
v2.10a 14th May 1998
---------------------
---------------------
Minor bug-fixes to counter some v2.10 reliability problems.
Minor bug-fixes to counter some v2.10 reliability problems.
v2.10 11th May 1998
v2.10 11th May 1998
---------------------
---------------------
Major re-write.
Major re-write.
Incorporated edge bundle processing of AET to overcome coincident
Incorporated edge bundle processing of AET to overcome coincident
edge problems present in previous releases.
edge problems present in previous releases.
Replaced Vatti's method for processing scanbeam interior regions
Replaced Vatti's method for processing scanbeam interior regions
with an adapted version of the scanbeam boundary processing
with an adapted version of the scanbeam boundary processing
algorithm.
algorithm.
v2.02 16th Apr 1998 (unreleased)
v2.02 16th Apr 1998 (unreleased)
----------------------------------
----------------------------------
Fixed internal minimum vertex duplication in gpc_polygon_clip
Fixed internal minimum vertex duplication in gpc_polygon_clip
result.
result.
Improved line intersection code discourage superfluous
Improved line intersection code discourage superfluous
intersections near line ends.
intersections near line ends.
Removed limited precision number formatting in gpc_write_polygon.
Removed limited precision number formatting in gpc_write_polygon.
Modification to allow subject or clip polygon to be reused as the
Modification to allow subject or clip polygon to be reused as the
result in gpc_polygon_clip without memory leakage.
result in gpc_polygon_clip without memory leakage.
v2.01 23rd Feb 1998
v2.01 23rd Feb 1998
---------------------
---------------------
Removed bug causing duplicated vertices in output polygon.
Removed bug causing duplicated vertices in output polygon.
Fixed scanbeam table index overrun problem.
Fixed scanbeam table index overrun problem.
v2.00 25th Nov 1997
v2.00 25th Nov 1997
---------------------
---------------------
Major re-write.
Major re-write.
Replaced temporary horizontal edge work-around (using tilting)
Replaced temporary horizontal edge work-around (using tilting)
with true horizontal edge handling.
with true horizontal edge handling.
Trapezoidal output replaced by tristrips.
Trapezoidal output replaced by tristrips.
gpc_op constants now feature a `GPC_' prefix.
gpc_op constants now feature a `GPC_' prefix.
Data structures now passed by reference to gpc functions.
Data structures now passed by reference to gpc functions.
Replaced AET search by proxy addressing in polygon table.
Replaced AET search by proxy addressing in polygon table.
Eliminated most (all?) coincident vertex / edge crashes.
Eliminated most (all?) coincident vertex / edge crashes.
v1.02 18th Oct 1997 (unreleased)
v1.02 18th Oct 1997 (unreleased)
----------------------------------
----------------------------------
Significantly reduced number of mallocs in build_lmt.
Significantly reduced number of mallocs in build_lmt.
Scanbeam table now built using heapsort rather than insertion
Scanbeam table now built using heapsort rather than insertion
sort.
sort.
v1.01 12th Oct 1997
v1.01 12th Oct 1997
---------------------
---------------------
Fixed memory leak during output polygon build in
Fixed memory leak during output polygon build in
gpc_clip_polygon.
gpc_clip_polygon.
Removed superfluous logfile debug code.
Removed superfluous logfile debug code.
Commented out malloc counts.
Commented out malloc counts.
Added missing horizontal edge tilt-correction code in
Added missing horizontal edge tilt-correction code in
gpc_clip_polygon.
gpc_clip_polygon.
v1.00 8th Oct 1997
v1.00 8th Oct 1997
--------------------
--------------------
First release.
First release.
polygon/defs-macros.h
View file @
4ce4631d
/**********************/
/**********************/
/* Some usual defines */
/* Some usual defines */
/**********************/
/**********************/
#ifndef DEFS_MACROS_H
#ifndef DEFS_MACROS_H
#define DEFS_MACROS_H
#define DEFS_MACROS_H
#ifndef BOOL
#ifndef BOOL
#define BOOL bool
#define BOOL bool
#endif
#endif
#ifndef FALSE
#ifndef FALSE
#define FALSE false
#define FALSE false
#endif
#endif
#ifndef TRUE
#ifndef TRUE
#define TRUE true
#define TRUE true
#endif
#endif
#ifndef NULL
#ifndef NULL
#define NULL 0
#define NULL 0
#endif
#endif
#ifndef abs
#ifndef abs
#define abs(x) (((x) >=0) ? (x) : (-(x)))
#define abs(x) (((x) >=0) ? (x) : (-(x)))
#endif
#endif
#define TRACE printf
#define TRACE printf
#define ASSERT(x) // todo : change to DEBUG, under wxWidgets
#define ASSERT(x) // todo : change to DEBUG, under wxWidgets
#endif // ifndef DEFS_MACROS_H
#endif // ifndef DEFS_MACROS_H
polygon/links.txt
View file @
4ce4631d
links to software relative to polygons (clipping and and other operations)
links to software relative to polygons (clipping and and other operations)
used in freePCB (Written by Alan Wright)
used in freePCB (Written by Alan Wright)
gpc (here: GenericPolygonClipperLibrary.cpp)
gpc (here: GenericPolygonClipperLibrary.cpp)
http://www.cs.man.ac.uk/~toby/alan/software/gpc.html
http://www.cs.man.ac.uk/~toby/alan/software/gpc.html
polygon.php (ported in "C++" by Alan Wright)
polygon.php (ported in "C++" by Alan Wright)
the c++ corresponding file is php_polygon.cpp
the c++ corresponding file is php_polygon.cpp
http://www.phpclasses.org/browse/file/10683.html
http://www.phpclasses.org/browse/file/10683.html
used in gpcb:
used in gpcb:
polygon1.c:
polygon1.c:
http://www.koders.com/c/
http://www.koders.com/c/
and for this file:
and for this file:
http://www.koders.com/c/fidE26CF2236C2DF7E435D597390A05B982EDFB4C38.aspx
http://www.koders.com/c/fidE26CF2236C2DF7E435D597390A05B982EDFB4C38.aspx
gpcb uses a modified file (integer coordinates)
gpcb uses a modified file (integer coordinates)
polygon/makefile.g95
View file @
4ce4631d
WXDIR
=
$(WXWIN)
WXDIR
=
$(WXWIN)
TARGET
=
lib_polygon.a
TARGET
=
lib_polygon.a
all
:
$(TARGET)
all
:
$(TARGET)
include
../libs.win
include
../libs.win
include
makefile.include
include
makefile.include
$(TARGET)
:
$(OBJECTS) ../libs.win makefile.include
$(TARGET)
:
$(OBJECTS) ../libs.win makefile.include
ar ruv
$@
$(OBJECTS)
ar ruv
$@
$(OBJECTS)
ranlib
$@
ranlib
$@
clean
:
clean
:
rm
-f
*
.bak
rm
-f
*
.bak
rm
-f
*
.o
rm
-f
*
.o
rm
-f
$(TARGET)
rm
-f
$(TARGET)
polygon/makefile.gtk
View file @
4ce4631d
## Makefile for common.a
## Makefile for common.a
CC
=
gcc
CC
=
gcc
include
../libs.linux
include
../libs.linux
# Compiler flags.
# Compiler flags.
CPPFLAGS
+=
-I
./
-I
../include
CPPFLAGS
+=
-I
./
-I
../include
EDACPPFLAGS
=
$(CPPFLAGS)
EDACPPFLAGS
=
$(CPPFLAGS)
TARGET
=
lib_polygon.a
TARGET
=
lib_polygon.a
all
:
$(TARGET)
all
:
$(TARGET)
deps
:
deps
:
$(CXX)
$(CPPFLAGS)
-E
-MMD
-MG
*
.cpp
>
/dev/null
$(CXX)
$(CPPFLAGS)
-E
-MMD
-MG
*
.cpp
>
/dev/null
include
makefile.include
include
makefile.include
-include
*.d
-include
*.d
CPPFLAGS
+=
$(EXTRACPPFLAGS)
-fno-strict-aliasing
CPPFLAGS
+=
$(EXTRACPPFLAGS)
-fno-strict-aliasing
EDACPPFLAGS
=
$(CPPFLAGS)
EDACPPFLAGS
=
$(CPPFLAGS)
$(TARGET)
:
$(OBJECTS) makefile.gtk makefile.include
$(TARGET)
:
$(OBJECTS) makefile.gtk makefile.include
rm
-f
$@
rm
-f
$@
ar
-rv
$@
$(OBJECTS)
ar
-rv
$@
$(OBJECTS)
ranlib
$@
ranlib
$@
install
:
$(TARGET)
install
:
$(TARGET)
clean
:
clean
:
rm
-f
*
.o
*
~ core
*
.bak
*
.obj
*
.d
rm
-f
*
.o
*
~ core
*
.bak
*
.obj
*
.d
rm
-f
$(TARGET)
rm
-f
$(TARGET)
polygon/makefile.include
View file @
4ce4631d
EXTRACPPFLAGS
+=
-I
$(SYSINCLUDE)
-I
./
-Ibitmaps
-I
../include
EXTRACPPFLAGS
+=
-I
$(SYSINCLUDE)
-I
./
-Ibitmaps
-I
../include
COMMON
=
COMMON
=
OBJECTS
=
\
OBJECTS
=
\
GenericPolygonClipperLibrary.o
\
GenericPolygonClipperLibrary.o
\
php_polygon.o\
php_polygon.o
\
php_polygon_vertex.o
php_polygon_vertex.o
GenericPolygonClipperLibrary.o
:
GenericPolygonClipperLibrary.cpp GenericPolygonClipperLibrary.h
GenericPolygonClipperLibrary.o
:
GenericPolygonClipperLibrary.cpp GenericPolygonClipperLibrary.h
php_polygon.o
:
php_polygon.cpp php_polygon.h php_polygon_vertex.h defs-macros.h
php_polygon.o
:
php_polygon.cpp php_polygon.h php_polygon_vertex.h defs-macros.h
#polygon1.o: polygon1.cpp polyarea.h vectmatr.h
#polygon1.o: polygon1.cpp polyarea.h vectmatr.h
polygon/makefile.macosx
View file @
4ce4631d
## Makefile for common.a
## Makefile for common.a
include
../libs.macosx
include
../libs.macosx
TARGET
=
lib_polygon.a
TARGET
=
lib_polygon.a
all
:
$(TARGET)
all
:
$(TARGET)
deps
:
deps
:
$(CXX)
$(CPPFLAGS)
-E
-MMD
-MG
*
.cpp
>
/dev/null
$(CXX)
$(CPPFLAGS)
-E
-MMD
-MG
*
.cpp
>
/dev/null
include
makefile.include
include
makefile.include
-include
*.d
-include
*.d
CPPFLAGS
+=
$(EXTRACPPFLAGS)
CPPFLAGS
+=
$(EXTRACPPFLAGS)
EDACPPFLAGS
=
$(CPPFLAGS)
EDACPPFLAGS
=
$(CPPFLAGS)
$(TARGET)
:
$(OBJECTS) makefile.macosx makefile.include
$(TARGET)
:
$(OBJECTS) makefile.macosx makefile.include
rm
-f
$@
rm
-f
$@
ar
-rv
$@
$(OBJECTS)
ar
-rv
$@
$(OBJECTS)
ranlib
$@
ranlib
$@
clean
:
clean
:
rm
-f
*
.o
;
rm
-f
*
~
rm
-f
*
.o
;
rm
-f
*
~
rm
-f
$(TARGET)
rm
-f
$(TARGET)
polygon/php_polygon.cpp
View file @
4ce4631d
// file php_polygon.cpp
// file php_polygon.cpp
// This is a port of a php class written by Brenor Brophy (see below)
// This is a port of a php class written by Brenor Brophy (see below)
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
** File: polygon.php
** File: polygon.php
** Description: PHP class for a polygon.
** Description: PHP class for a polygon.
** Version: 1.1
** Version: 1.1
** Author: Brenor Brophy
** Author: Brenor Brophy
** Email: brenor at sbcglobal dot net
** Email: brenor at sbcglobal dot net
** Homepage: www.brenorbrophy.com
** Homepage: www.brenorbrophy.com
**------------------------------------------------------------------------------
**------------------------------------------------------------------------------
** COPYRIGHT (c) 2005 BRENOR BROPHY
** COPYRIGHT (c) 2005 BRENOR BROPHY
**
**
** The source code included in this package is free software; you can
** The source code included in this package is free software; you can
** redistribute it and/or modify it under the terms of the GNU General Public
** redistribute it and/or modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation. This license can be
** License as published by the Free Software Foundation. This license can be
** read at:
** read at:
**
**
** http://www.opensource.org/licenses/gpl-license.php
** http://www.opensource.org/licenses/gpl-license.php
**
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
**------------------------------------------------------------------------------
**------------------------------------------------------------------------------
**
**
** Based on the paper "Efficient Clipping of Arbitary Polygons" by Gunther
** Based on the paper "Efficient Clipping of Arbitary Polygons" by Gunther
** Greiner (greiner at informatik dot uni-erlangen dot de) and Kai Hormann
** Greiner (greiner at informatik dot uni-erlangen dot de) and Kai Hormann
** (hormann at informatik dot tu-clausthal dot de), ACM Transactions on Graphics
** (hormann at informatik dot tu-clausthal dot de), ACM Transactions on Graphics
** 1998;17(2):71-83.
** 1998;17(2):71-83.
**
**
** Available at: www.in.tu-clausthal.de/~hormann/papers/clipping.pdf
** Available at: www.in.tu-clausthal.de/~hormann/papers/clipping.pdf
**
**
** Another useful site describing the algorithm and with some example
** Another useful site describing the algorithm and with some example
** C code by Ionel Daniel Stroe is at:
** C code by Ionel Daniel Stroe is at:
**
**
** http://davis.wpi.edu/~matt/courses/clipping/
** http://davis.wpi.edu/~matt/courses/clipping/
**
**
** The algorithm is extended by Brenor Brophy to allow polygons with
** The algorithm is extended by Brenor Brophy to allow polygons with
** arcs between vertices.
** arcs between vertices.
**
**
** Rev History
** Rev History
** -----------------------------------------------------------------------------
** -----------------------------------------------------------------------------
** 1.0 08/25/2005 Initial Release
** 1.0 08/25/2005 Initial Release
** 1.1 09/04/2005 Added Move(), Rotate(), isPolyInside() and bRect() methods.
** 1.1 09/04/2005 Added Move(), Rotate(), isPolyInside() and bRect() methods.
** Added software license language to header comments
** Added software license language to header comments
*/
*/
//#include "stdafx.h"
//#include "stdafx.h"
#include <stdio.h>
#include <stdio.h>
#include <math.h>
#include <math.h>
#include "php_polygon_vertex.h"
#include "php_polygon_vertex.h"
#include "php_polygon.h"
#include "php_polygon.h"
const
double
PT
=
0.99999
;
const
double
PT
=
0.99999
;
//const double eps = (1.0 - PT)/10.0;
//const double eps = (1.0 - PT)/10.0;
const
double
eps
=
0.0
;
const
double
eps
=
0.0
;
polygon
::
polygon
(
vertex
*
first
)
polygon
::
polygon
(
vertex
*
first
)
{
{
m_first
=
first
;
m_first
=
first
;
m_cnt
=
0
;
m_cnt
=
0
;
}
}
polygon
::~
polygon
()
polygon
::~
polygon
()
{
{
while
(
m_cnt
>
1
)
while
(
m_cnt
>
1
)
{
{
vertex
*
v
=
getFirst
();
vertex
*
v
=
getFirst
();
del
(
v
->
m_nextV
);
del
(
v
->
m_nextV
);
}
}
if
(
m_first
)
if
(
m_first
)
{
{
delete
m_first
;
delete
m_first
;
}
}
}
}
vertex
*
polygon
::
getFirst
()
vertex
*
polygon
::
getFirst
()
{
{
return
m_first
;
return
m_first
;
}
}
polygon
*
polygon
::
NextPoly
()
polygon
*
polygon
::
NextPoly
()
{
{
return
m_first
->
NextPoly
();
return
m_first
->
NextPoly
();
}
}
/*
/*
** Add a vertex object to the polygon (vertex is added at the "end" of the list)
** Add a vertex object to the polygon (vertex is added at the "end" of the list)
** Which because polygons are closed lists means it is added just before the first
** Which because polygons are closed lists means it is added just before the first
** vertex.
** vertex.
*/
*/
void
polygon
::
add
(
vertex
*
nv
)
void
polygon
::
add
(
vertex
*
nv
)
{
{
if
(
m_cnt
==
0
)
// If this is the first vertex in the polygon
if
(
m_cnt
==
0
)
// If this is the first vertex in the polygon
{
{
m_first
=
nv
;
// Save a reference to it in the polygon
m_first
=
nv
;
// Save a reference to it in the polygon
m_first
->
setNext
(
nv
);
// Set its pointer to point to itself
m_first
->
setNext
(
nv
);
// Set its pointer to point to itself
m_first
->
setPrev
(
nv
);
// because it is the only vertex in the list
m_first
->
setPrev
(
nv
);
// because it is the only vertex in the list
segment
*
ps
=
m_first
->
Nseg
();
// Get ref to the Next segment object
segment
*
ps
=
m_first
->
Nseg
();
// Get ref to the Next segment object
m_first
->
setPseg
(
ps
);
// and save it as Prev segment as well
m_first
->
setPseg
(
ps
);
// and save it as Prev segment as well
}
}
else
// At least one other vertex already exists
else
// At least one other vertex already exists
{
{
// p <-> nv <-> n
// p <-> nv <-> n
// ps ns
// ps ns
vertex
*
n
=
m_first
;
// Get a ref to the first vertex in the list
vertex
*
n
=
m_first
;
// Get a ref to the first vertex in the list
vertex
*
p
=
n
->
Prev
();
// Get ref to previous vertex
vertex
*
p
=
n
->
Prev
();
// Get ref to previous vertex
n
->
setPrev
(
nv
);
// Add at end of list (just before first)
n
->
setPrev
(
nv
);
// Add at end of list (just before first)
nv
->
setNext
(
n
);
// link the new vertex to it
nv
->
setNext
(
n
);
// link the new vertex to it
nv
->
setPrev
(
p
);
// link to the pervious EOL vertex
nv
->
setPrev
(
p
);
// link to the pervious EOL vertex
p
->
setNext
(
nv
);
// And finally link the previous EOL vertex
p
->
setNext
(
nv
);
// And finally link the previous EOL vertex
// Segments
// Segments
segment
*
ns
=
nv
->
Nseg
();
// Get ref to the new next segment
segment
*
ns
=
nv
->
Nseg
();
// Get ref to the new next segment
segment
*
ps
=
p
->
Nseg
();
// Get ref to the previous segment
segment
*
ps
=
p
->
Nseg
();
// Get ref to the previous segment
n
->
setPseg
(
ns
);
// Set new previous seg for m_first
n
->
setPseg
(
ns
);
// Set new previous seg for m_first
nv
->
setPseg
(
ps
);
// Set previous seg of the new vertex
nv
->
setPseg
(
ps
);
// Set previous seg of the new vertex
}
}
m_cnt
++
;
// Increment the count of vertices
m_cnt
++
;
// Increment the count of vertices
}
}
/*
/*
** Create a vertex and then add it to the polygon
** Create a vertex and then add it to the polygon
*/
*/
void
polygon
::
addv
(
double
x
,
double
y
,
void
polygon
::
addv
(
double
x
,
double
y
,
double
xc
,
double
yc
,
int
d
)
double
xc
,
double
yc
,
int
d
)
{
{
vertex
*
nv
=
new
vertex
(
x
,
y
,
xc
,
yc
,
d
);
vertex
*
nv
=
new
vertex
(
x
,
y
,
xc
,
yc
,
d
);
add
(
nv
);
add
(
nv
);
}
}
/*
/*
** Delete a vertex object from the polygon. This is not used by the main algorithm
** Delete a vertex object from the polygon. This is not used by the main algorithm
** but instead is used to clean-up a polygon so that a second boolean operation can
** but instead is used to clean-up a polygon so that a second boolean operation can
** be performed.
** be performed.
*/
*/
vertex
*
polygon
::
del
(
vertex
*
v
)
vertex
*
polygon
::
del
(
vertex
*
v
)
{
{
// p <-> v <-> n Will delete v and ns
// p <-> v <-> n Will delete v and ns
// ps ns
// ps ns
vertex
*
p
=
v
->
Prev
();
// Get ref to previous vertex
vertex
*
p
=
v
->
Prev
();
// Get ref to previous vertex
vertex
*
n
=
v
->
Next
();
// Get ref to next vertex
vertex
*
n
=
v
->
Next
();
// Get ref to next vertex
p
->
setNext
(
n
);
// Link previous forward to next
p
->
setNext
(
n
);
// Link previous forward to next
n
->
setPrev
(
p
);
// Link next back to previous
n
->
setPrev
(
p
);
// Link next back to previous
// Segments
// Segments
segment
*
ps
=
p
->
Nseg
();
// Get ref to previous segment
segment
*
ps
=
p
->
Nseg
();
// Get ref to previous segment
segment
*
ns
=
v
->
Nseg
();
// Get ref to next segment
segment
*
ns
=
v
->
Nseg
();
// Get ref to next segment
n
->
setPseg
(
ps
);
// Link next back to previous segment
n
->
setPseg
(
ps
);
// Link next back to previous segment
delete
ns
;
//AMW
delete
ns
;
//AMW
v
->
m_nSeg
=
NULL
;
// AMW
v
->
m_nSeg
=
NULL
;
// AMW
delete
v
;
//AMW
delete
v
;
//AMW
// ns = NULL;
// ns = NULL;
// v = NULL; // Free the memory
// v = NULL; // Free the memory
m_cnt
--
;
// One less vertex
m_cnt
--
;
// One less vertex
return
n
;
// Return a ref to the next valid vertex
return
n
;
// Return a ref to the next valid vertex
}
}
/*
/*
** Reset Polygon - Deletes all intersection vertices. This is used to
** Reset Polygon - Deletes all intersection vertices. This is used to
** restore a polygon that has been processed by the boolean method
** restore a polygon that has been processed by the boolean method
** so that it can be processed again.
** so that it can be processed again.
*/
*/
void
polygon
::
res
()
void
polygon
::
res
()
{
{
vertex
*
v
=
getFirst
();
// Get the first vertex
vertex
*
v
=
getFirst
();
// Get the first vertex
do
do
{
{
v
=
v
->
Next
();
// Get the next vertex in the polygon
v
=
v
->
Next
();
// Get the next vertex in the polygon
while
(
v
->
isIntersect
())
// Delete all intersection vertices
while
(
v
->
isIntersect
())
// Delete all intersection vertices
v
=
del
(
v
);
v
=
del
(
v
);
}
}
while
(
v
->
id
()
!=
m_first
->
id
());
while
(
v
->
id
()
!=
m_first
->
id
());
}
}
/*
/*
** Copy Polygon - Returns a reference to a new copy of the poly object
** Copy Polygon - Returns a reference to a new copy of the poly object
** including all its vertices & their segments
** including all its vertices & their segments
*/
*/
polygon
*
polygon
::
copy_poly
()
polygon
*
polygon
::
copy_poly
()
{
{
polygon
*
n
=
new
polygon
;
// Create a new instance of this class
polygon
*
n
=
new
polygon
;
// Create a new instance of this class
vertex
*
v
=
getFirst
();
vertex
*
v
=
getFirst
();
do
do
{
{
n
->
addv
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(),
v
->
Yc
(),
v
->
d
());
n
->
addv
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(),
v
->
Yc
(),
v
->
d
());
v
=
v
->
Next
();
v
=
v
->
Next
();
}
}
while
(
v
->
id
()
!=
m_first
->
id
());
while
(
v
->
id
()
!=
m_first
->
id
());
return
n
;
return
n
;
}
}
/*
/*
** Insert and Sort a vertex between a specified pair of vertices (start and end)
** Insert and Sort a vertex between a specified pair of vertices (start and end)
**
**
** This function inserts a vertex (most likely an intersection point) between two
** This function inserts a vertex (most likely an intersection point) between two
** other vertices. These other vertices cannot be intersections (that is they must
** other vertices. These other vertices cannot be intersections (that is they must
** be actual vertices of the original polygon). If there are multiple intersection
** be actual vertices of the original polygon). If there are multiple intersection
** points between the two vertices then the new vertex is inserted based on its
** points between the two vertices then the new vertex is inserted based on its
** alpha value.
** alpha value.
*/
*/
void
polygon
::
insertSort
(
vertex
*
nv
,
vertex
*
s
,
vertex
*
e
)
void
polygon
::
insertSort
(
vertex
*
nv
,
vertex
*
s
,
vertex
*
e
)
{
{
vertex
*
c
=
s
;
// Set current to the starting vertex
vertex
*
c
=
s
;
// Set current to the starting vertex
// Move current past any intersections
// Move current past any intersections
// whose alpha is lower but don't go past
// whose alpha is lower but don't go past
// the end vertex
// the end vertex
while
(
c
->
id
()
!=
e
->
id
()
&&
c
->
Alpha
()
<
nv
->
Alpha
()
)
while
(
c
->
id
()
!=
e
->
id
()
&&
c
->
Alpha
()
<
nv
->
Alpha
()
)
c
=
c
->
Next
();
c
=
c
->
Next
();
// p <-> nv <-> c
// p <-> nv <-> c
nv
->
setNext
(
c
);
// Link new vertex forward to curent one
nv
->
setNext
(
c
);
// Link new vertex forward to curent one
vertex
*
p
=
c
->
Prev
();
// Get a link to the previous vertex
vertex
*
p
=
c
->
Prev
();
// Get a link to the previous vertex
nv
->
setPrev
(
p
);
// Link the new vertex back to the previous one
nv
->
setPrev
(
p
);
// Link the new vertex back to the previous one
p
->
setNext
(
nv
);
// Link previous vertex forward to new vertex
p
->
setNext
(
nv
);
// Link previous vertex forward to new vertex
c
->
setPrev
(
nv
);
// Link current vertex back to the new vertex
c
->
setPrev
(
nv
);
// Link current vertex back to the new vertex
// Segments
// Segments
segment
*
ps
=
p
->
Nseg
();
segment
*
ps
=
p
->
Nseg
();
nv
->
setPseg
(
ps
);
nv
->
setPseg
(
ps
);
segment
*
ns
=
nv
->
Nseg
();
segment
*
ns
=
nv
->
Nseg
();
c
->
setPseg
(
ns
);
c
->
setPseg
(
ns
);
m_cnt
++
;
// Just added a new vertex
m_cnt
++
;
// Just added a new vertex
}
}
/*
/*
** return the next non intersecting vertex after the one specified
** return the next non intersecting vertex after the one specified
*/
*/
vertex
*
polygon
::
nxt
(
vertex
*
v
)
vertex
*
polygon
::
nxt
(
vertex
*
v
)
{
{
vertex
*
c
=
v
;
// Initialize current vertex
vertex
*
c
=
v
;
// Initialize current vertex
while
(
c
&&
c
->
isIntersect
())
// Move until a non-intersection
while
(
c
&&
c
->
isIntersect
())
// Move until a non-intersection
c
=
c
->
Next
();
// vertex if found
c
=
c
->
Next
();
// vertex if found
return
c
;
// return that vertex
return
c
;
// return that vertex
}
}
/*
/*
** Check if any unchecked intersections remain in the polygon. The boolean
** Check if any unchecked intersections remain in the polygon. The boolean
** method is complete when all intersections have been checked.
** method is complete when all intersections have been checked.
*/
*/
BOOL
polygon
::
unckd_remain
()
BOOL
polygon
::
unckd_remain
()
{
{
BOOL
remain
=
FALSE
;
BOOL
remain
=
FALSE
;
vertex
*
v
=
m_first
;
vertex
*
v
=
m_first
;
do
do
{
{
if
(
v
->
isIntersect
()
&&
!
v
->
isChecked
())
if
(
v
->
isIntersect
()
&&
!
v
->
isChecked
())
remain
=
TRUE
;
// Set if an unchecked intersection is found
remain
=
TRUE
;
// Set if an unchecked intersection is found
v
=
v
->
Next
();
v
=
v
->
Next
();
}
}
while
(
v
->
id
()
!=
m_first
->
id
());
while
(
v
->
id
()
!=
m_first
->
id
());
return
remain
;
return
remain
;
}
}
/*
/*
** Return a ref to the first unchecked intersection point in the polygon.
** Return a ref to the first unchecked intersection point in the polygon.
** If none are found then just the first vertex is returned.
** If none are found then just the first vertex is returned.
*/
*/
vertex
*
polygon
::
first_unckd_intersect
()
vertex
*
polygon
::
first_unckd_intersect
()
{
{
vertex
*
v
=
m_first
;
vertex
*
v
=
m_first
;
do
// Do-While
do
// Do-While
{
// Not yet reached end of the polygon
{
// Not yet reached end of the polygon
v
=
v
->
Next
();
// AND the vertex if NOT an intersection
v
=
v
->
Next
();
// AND the vertex if NOT an intersection
}
// OR it IS an intersection, but has been checked already
}
// OR it IS an intersection, but has been checked already
while
(
v
->
id
()
!=
m_first
->
id
()
&&
(
!
v
->
isIntersect
()
||
(
v
->
isIntersect
()
&&
v
->
isChecked
()
)
)
);
while
(
v
->
id
()
!=
m_first
->
id
()
&&
(
!
v
->
isIntersect
()
||
(
v
->
isIntersect
()
&&
v
->
isChecked
()
)
)
);
return
v
;
return
v
;
}
}
/*
/*
** Return the distance between two points
** Return the distance between two points
*/
*/
double
polygon
::
dist
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
double
polygon
::
dist
(
double
x1
,
double
y1
,
double
x2
,
double
y2
)
{
{
return
sqrt
((
x1
-
x2
)
*
(
x1
-
x2
)
+
(
y1
-
y2
)
*
(
y1
-
y2
));
return
sqrt
((
x1
-
x2
)
*
(
x1
-
x2
)
+
(
y1
-
y2
)
*
(
y1
-
y2
));
}
}
/*
/*
** Calculate the angle between 2 points, where Xc,Yc is the center of a circle
** Calculate the angle between 2 points, where Xc,Yc is the center of a circle
** and x,y is a point on its circumference. All angles are relative to
** and x,y is a point on its circumference. All angles are relative to
** the 3 O'Clock position. Result returned in radians
** the 3 O'Clock position. Result returned in radians
*/
*/
double
polygon
::
angle
(
double
xc
,
double
yc
,
double
x1
,
double
y1
)
double
polygon
::
angle
(
double
xc
,
double
yc
,
double
x1
,
double
y1
)
{
{
double
d
=
dist
(
xc
,
yc
,
x1
,
y1
);
// calc distance between two points
double
d
=
dist
(
xc
,
yc
,
x1
,
y1
);
// calc distance between two points
double
a1
;
double
a1
;
if
(
asin
(
(
y1
-
yc
)
/
d
)
>=
0
)
if
(
asin
(
(
y1
-
yc
)
/
d
)
>=
0
)
a1
=
acos
(
(
x1
-
xc
)
/
d
);
a1
=
acos
(
(
x1
-
xc
)
/
d
);
else
else
a1
=
2
*
PI
-
acos
(
(
x1
-
xc
)
/
d
);
a1
=
2
*
PI
-
acos
(
(
x1
-
xc
)
/
d
);
return
a1
;
return
a1
;
}
}
/*
/*
** Return Alpha value for an Arc
** Return Alpha value for an Arc
**
**
** X1/Y1 & X2/Y2 are the end points of the arc, Xc/Yc is the center & Xi/Yi
** X1/Y1 & X2/Y2 are the end points of the arc, Xc/Yc is the center & Xi/Yi
** the intersection point on the arc. d is the direction of the arc
** the intersection point on the arc. d is the direction of the arc
*/
*/
double
polygon
::
aAlpha
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
polygon
::
aAlpha
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
xc
,
double
yc
,
double
xi
,
double
yi
,
double
d
)
double
xc
,
double
yc
,
double
xi
,
double
yi
,
double
d
)
{
{
double
sa
=
angle
(
xc
,
yc
,
x1
,
y1
);
// Start Angle
double
sa
=
angle
(
xc
,
yc
,
x1
,
y1
);
// Start Angle
double
ea
=
angle
(
xc
,
yc
,
x2
,
y2
);
// End Angle
double
ea
=
angle
(
xc
,
yc
,
x2
,
y2
);
// End Angle
double
ia
=
angle
(
xc
,
yc
,
xi
,
yi
);
// Intersection Angle
double
ia
=
angle
(
xc
,
yc
,
xi
,
yi
);
// Intersection Angle
double
arc
,
aint
;
double
arc
,
aint
;
if
(
d
==
1
)
// Anti-Clockwise
if
(
d
==
1
)
// Anti-Clockwise
{
{
arc
=
ea
-
sa
;
arc
=
ea
-
sa
;
aint
=
ia
-
sa
;
aint
=
ia
-
sa
;
}
}
else
// Clockwise
else
// Clockwise
{
{
arc
=
sa
-
ea
;
arc
=
sa
-
ea
;
aint
=
sa
-
ia
;
aint
=
sa
-
ia
;
}
}
if
(
arc
<
0
)
if
(
arc
<
0
)
arc
+=
2
*
PI
;
arc
+=
2
*
PI
;
if
(
aint
<
0
)
if
(
aint
<
0
)
aint
+=
2
*
PI
;
aint
+=
2
*
PI
;
double
a
=
aint
/
arc
;
double
a
=
aint
/
arc
;
return
a
;
return
a
;
}
}
/*
/*
** This function handles the degenerate case where a vertex of one
** This function handles the degenerate case where a vertex of one
** polygon lies directly on an edge of the other. This case can
** polygon lies directly on an edge of the other. This case can
** also occur during the isInside() function, where the search
** also occur during the isInside() function, where the search
** line exactly intersects with a vertex. The function works
** line exactly intersects with a vertex. The function works
** by shortening the line by a tiny amount.
** by shortening the line by a tiny amount.
*/
*/
void
polygon
::
perturb
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
void
polygon
::
perturb
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
double
aP
,
double
aQ
)
double
aP
,
double
aQ
)
{
{
// if (aP == 0) // Move vertex p1 closer to p2
// if (aP == 0) // Move vertex p1 closer to p2
if
(
abs
(
aP
)
<=
eps
)
// Move vertex p1 closer to p2
if
(
abs
(
aP
)
<=
eps
)
// Move vertex p1 closer to p2
{
{
p1
->
setX
(
p1
->
X
()
+
(
1
-
PT
)
*
(
p2
->
X
()
-
p1
->
X
()));
p1
->
setX
(
p1
->
X
()
+
(
1
-
PT
)
*
(
p2
->
X
()
-
p1
->
X
()));
p1
->
setY
(
p1
->
Y
()
+
(
1
-
PT
)
*
(
p2
->
Y
()
-
p1
->
Y
()));
p1
->
setY
(
p1
->
Y
()
+
(
1
-
PT
)
*
(
p2
->
Y
()
-
p1
->
Y
()));
}
}
// else if (aP == 1) // Move vertex p2 closer to p1
// else if (aP == 1) // Move vertex p2 closer to p1
else
if
(
abs
(
1
-
aP
)
<=
eps
)
// Move vertex p2 closer to p1
else
if
(
abs
(
1
-
aP
)
<=
eps
)
// Move vertex p2 closer to p1
{
{
p2
->
setX
(
p1
->
X
()
+
PT
*
(
p2
->
X
()
-
p1
->
X
()));
p2
->
setX
(
p1
->
X
()
+
PT
*
(
p2
->
X
()
-
p1
->
X
()));
p2
->
setY
(
p1
->
Y
()
+
PT
*
(
p2
->
Y
()
-
p1
->
Y
()));
p2
->
setY
(
p1
->
Y
()
+
PT
*
(
p2
->
Y
()
-
p1
->
Y
()));
}
}
//** else if (aQ == 0) // Move vertex q1 closer to q2
//** else if (aQ == 0) // Move vertex q1 closer to q2
if
(
abs
(
aQ
)
<=
eps
)
// Move vertex q1 closer to q2
if
(
abs
(
aQ
)
<=
eps
)
// Move vertex q1 closer to q2
{
{
q1
->
setX
(
q1
->
X
()
+
(
1
-
PT
)
*
(
q2
->
X
()
-
q1
->
X
()));
q1
->
setX
(
q1
->
X
()
+
(
1
-
PT
)
*
(
q2
->
X
()
-
q1
->
X
()));
q1
->
setY
(
q1
->
Y
()
+
(
1
-
PT
)
*
(
q2
->
Y
()
-
q1
->
Y
()));
q1
->
setY
(
q1
->
Y
()
+
(
1
-
PT
)
*
(
q2
->
Y
()
-
q1
->
Y
()));
}
}
//** else if (aQ == 1) // Move vertex q2 closer to q1
//** else if (aQ == 1) // Move vertex q2 closer to q1
else
if
(
abs
(
1
-
aQ
)
<=
eps
)
// Move vertex q2 closer to q1
else
if
(
abs
(
1
-
aQ
)
<=
eps
)
// Move vertex q2 closer to q1
{
{
q2
->
setX
(
q1
->
X
()
+
PT
*
(
q2
->
X
()
-
q1
->
X
()));
q2
->
setX
(
q1
->
X
()
+
PT
*
(
q2
->
X
()
-
q1
->
X
()));
q2
->
setY
(
q1
->
Y
()
+
PT
*
(
q2
->
Y
()
-
q1
->
Y
()));
q2
->
setY
(
q1
->
Y
()
+
PT
*
(
q2
->
Y
()
-
q1
->
Y
()));
}
}
}
}
/*
/*
** Determine the intersection between two pairs of vertices p1/p2, q1/q2
** Determine the intersection between two pairs of vertices p1/p2, q1/q2
**
**
** Either or both of the segments passed to this function could be arcs.
** Either or both of the segments passed to this function could be arcs.
** Thus we must first determine if the intersection is line/line, arc/line
** Thus we must first determine if the intersection is line/line, arc/line
** or arc/arc. Then apply the correct math to calculate the intersection(s).
** or arc/arc. Then apply the correct math to calculate the intersection(s).
**
**
** Line/Line can have 0 (no intersection) or 1 intersection
** Line/Line can have 0 (no intersection) or 1 intersection
** Line/Arc and Arc/Arc can have 0, 1 or 2 intersections
** Line/Arc and Arc/Arc can have 0, 1 or 2 intersections
**
**
** The function returns TRUE is any intersections are found
** The function returns TRUE is any intersections are found
** The number found is returned in n
** The number found is returned in n
** The arrays ix[], iy[], alphaP[] & alphaQ[] return the intersection points
** The arrays ix[], iy[], alphaP[] & alphaQ[] return the intersection points
** and their associated alpha values.
** and their associated alpha values.
*/
*/
BOOL
polygon
::
ints
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
BOOL
polygon
::
ints
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
int
*
n
,
double
ix
[],
double
iy
[],
double
alphaP
[],
double
alphaQ
[]
)
int
*
n
,
double
ix
[],
double
iy
[],
double
alphaP
[],
double
alphaQ
[]
)
{
{
BOOL
found
=
FALSE
;
BOOL
found
=
FALSE
;
*
n
=
0
;
// No intersections found yet
*
n
=
0
;
// No intersections found yet
int
pt
=
p1
->
d
();
int
pt
=
p1
->
d
();
int
qt
=
q1
->
d
();
// Do we have Arcs or Lines?
int
qt
=
q1
->
d
();
// Do we have Arcs or Lines?
if
(
pt
==
0
&&
qt
==
0
)
// Is it line/Line ?
if
(
pt
==
0
&&
qt
==
0
)
// Is it line/Line ?
{
{
/* LINE/LINE
/* LINE/LINE
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
*/
*/
double
x1
=
p1
->
X
();
double
x1
=
p1
->
X
();
double
y1
=
p1
->
Y
();
double
y1
=
p1
->
Y
();
double
x2
=
p2
->
X
();
double
x2
=
p2
->
X
();
double
y2
=
p2
->
Y
();
double
y2
=
p2
->
Y
();
double
x3
=
q1
->
X
();
double
x3
=
q1
->
X
();
double
y3
=
q1
->
Y
();
double
y3
=
q1
->
Y
();
double
x4
=
q2
->
X
();
double
x4
=
q2
->
X
();
double
y4
=
q2
->
Y
();
double
y4
=
q2
->
Y
();
double
d
=
((
y4
-
y3
)
*
(
x2
-
x1
)
-
(
x4
-
x3
)
*
(
y2
-
y1
));
double
d
=
((
y4
-
y3
)
*
(
x2
-
x1
)
-
(
x4
-
x3
)
*
(
y2
-
y1
));
if
(
d
!=
0
)
if
(
d
!=
0
)
{
// The lines intersect at a point somewhere
{
// The lines intersect at a point somewhere
double
ua
=
((
x4
-
x3
)
*
(
y1
-
y3
)
-
(
y4
-
y3
)
*
(
x1
-
x3
))
/
d
;
double
ua
=
((
x4
-
x3
)
*
(
y1
-
y3
)
-
(
y4
-
y3
)
*
(
x1
-
x3
))
/
d
;
double
ub
=
((
x2
-
x1
)
*
(
y1
-
y3
)
-
(
y2
-
y1
)
*
(
x1
-
x3
))
/
d
;
double
ub
=
((
x2
-
x1
)
*
(
y1
-
y3
)
-
(
y2
-
y1
)
*
(
x1
-
x3
))
/
d
;
TRACE
(
" ints: ua = %.17f, ub = %.17f
\n
"
,
ua
,
ub
);
TRACE
(
" ints: ua = %.17f, ub = %.17f
\n
"
,
ua
,
ub
);
// The values of $ua and $ub tell us where the intersection occurred.
// The values of $ua and $ub tell us where the intersection occurred.
// A value between 0 and 1 means the intersection occurred within the
// A value between 0 and 1 means the intersection occurred within the
// line segment.
// line segment.
// A value less than 0 or greater than 1 means the intersection occurred
// A value less than 0 or greater than 1 means the intersection occurred
// outside the line segment
// outside the line segment
// A value of exactly 0 or 1 means the intersection occurred right at the
// A value of exactly 0 or 1 means the intersection occurred right at the
// start or end of the line segment. For our purposes we will consider this
// start or end of the line segment. For our purposes we will consider this
// NOT to be an intersection and we will move the vertex a tiny distance
// NOT to be an intersection and we will move the vertex a tiny distance
// away from the intersecting line.
// away from the intersecting line.
// if( ua == 0 || ua == 1 || ub == 0 || ub == 1 )
// if( ua == 0 || ua == 1 || ub == 0 || ub == 1 )
if
(
abs
(
ua
)
<=
eps
||
abs
(
1.0
-
ua
)
<=
eps
||
abs
(
ub
)
<=
eps
||
abs
(
1.0
-
ub
)
<=
eps
)
if
(
abs
(
ua
)
<=
eps
||
abs
(
1.0
-
ua
)
<=
eps
||
abs
(
ub
)
<=
eps
||
abs
(
1.0
-
ub
)
<=
eps
)
{
{
// Degenerate case - vertex touches a line
// Degenerate case - vertex touches a line
perturb
(
p1
,
p2
,
q1
,
q2
,
ua
,
ub
);
perturb
(
p1
,
p2
,
q1
,
q2
,
ua
,
ub
);
//** for testing, see if we have successfully resolved the degeneracy
//** for testing, see if we have successfully resolved the degeneracy
{
{
double
tx1
=
p1
->
X
();
double
tx1
=
p1
->
X
();
double
ty1
=
p1
->
Y
();
double
ty1
=
p1
->
Y
();
double
tx2
=
p2
->
X
();
double
tx2
=
p2
->
X
();
double
ty2
=
p2
->
Y
();
double
ty2
=
p2
->
Y
();
double
tx3
=
q1
->
X
();
double
tx3
=
q1
->
X
();
double
ty3
=
q1
->
Y
();
double
ty3
=
q1
->
Y
();
double
tx4
=
q2
->
X
();
double
tx4
=
q2
->
X
();
double
ty4
=
q2
->
Y
();
double
ty4
=
q2
->
Y
();
double
td
=
((
ty4
-
ty3
)
*
(
tx2
-
tx1
)
-
(
tx4
-
tx3
)
*
(
ty2
-
ty1
));
double
td
=
((
ty4
-
ty3
)
*
(
tx2
-
tx1
)
-
(
tx4
-
tx3
)
*
(
ty2
-
ty1
));
if
(
td
!=
0
)
if
(
td
!=
0
)
{
{
// The lines intersect at a point somewhere
// The lines intersect at a point somewhere
double
tua
=
((
tx4
-
tx3
)
*
(
ty1
-
ty3
)
-
(
ty4
-
ty3
)
*
(
tx1
-
tx3
))
/
td
;
double
tua
=
((
tx4
-
tx3
)
*
(
ty1
-
ty3
)
-
(
ty4
-
ty3
)
*
(
tx1
-
tx3
))
/
td
;
double
tub
=
((
tx2
-
tx1
)
*
(
ty1
-
ty3
)
-
(
ty2
-
ty1
)
*
(
tx1
-
tx3
))
/
td
;
double
tub
=
((
tx2
-
tx1
)
*
(
ty1
-
ty3
)
-
(
ty2
-
ty1
)
*
(
tx1
-
tx3
))
/
td
;
if
(
abs
(
tua
)
<=
eps
||
abs
(
1.0
-
tua
)
<=
eps
||
abs
(
tub
)
<=
eps
||
abs
(
1.0
-
tub
)
<=
eps
)
if
(
abs
(
tua
)
<=
eps
||
abs
(
1.0
-
tua
)
<=
eps
||
abs
(
tub
)
<=
eps
||
abs
(
1.0
-
tub
)
<=
eps
)
ASSERT
(
0
);
ASSERT
(
0
);
else
if
(
(
tua
>
0
&&
tua
<
1
)
&&
(
tub
>
0
&&
tub
<
1
)
)
else
if
(
(
tua
>
0
&&
tua
<
1
)
&&
(
tub
>
0
&&
tub
<
1
)
)
ASSERT
(
0
);
ASSERT
(
0
);
TRACE
(
" perturb:
\n
new s = (%f,%f) to (%f,%f)
\n
new c = (%f,%f) to (%f,%f)
\n
new ua = %.17f, ub = %.17f
\n
"
,
TRACE
(
" perturb:
\n
new s = (%f,%f) to (%f,%f)
\n
new c = (%f,%f) to (%f,%f)
\n
new ua = %.17f, ub = %.17f
\n
"
,
tx1
,
ty1
,
tx2
,
ty2
,
tx3
,
ty3
,
tx4
,
ty4
,
tua
,
tub
);
tx1
,
ty1
,
tx2
,
ty2
,
tx3
,
ty3
,
tx4
,
ty4
,
tua
,
tub
);
}
}
}
}
//** end test
//** end test
found
=
FALSE
;
found
=
FALSE
;
}
}
else
if
((
ua
>
0
&&
ua
<
1
)
&&
(
ub
>
0
&&
ub
<
1
))
else
if
((
ua
>
0
&&
ua
<
1
)
&&
(
ub
>
0
&&
ub
<
1
))
{
{
// Intersection occurs on both line segments
// Intersection occurs on both line segments
double
x
=
x1
+
ua
*
(
x2
-
x1
);
double
x
=
x1
+
ua
*
(
x2
-
x1
);
double
y
=
y1
+
ua
*
(
y2
-
y1
);
double
y
=
y1
+
ua
*
(
y2
-
y1
);
iy
[
0
]
=
y
;
iy
[
0
]
=
y
;
ix
[
0
]
=
x
;
ix
[
0
]
=
x
;
alphaP
[
0
]
=
ua
;
alphaP
[
0
]
=
ua
;
alphaQ
[
0
]
=
ub
;
alphaQ
[
0
]
=
ub
;
*
n
=
1
;
*
n
=
1
;
found
=
TRUE
;
found
=
TRUE
;
}
}
else
else
{
{
// The lines do not intersect
// The lines do not intersect
found
=
FALSE
;
found
=
FALSE
;
}
}
}
}
else
else
{
{
// The lines do not intersect (they are parallel)
// The lines do not intersect (they are parallel)
found
=
FALSE
;
found
=
FALSE
;
}
}
}
// End of find Line/Line intersection
}
// End of find Line/Line intersection
else
if
(
pt
!=
0
&&
qt
!=
0
)
// Is it Arc/Arc?
else
if
(
pt
!=
0
&&
qt
!=
0
)
// Is it Arc/Arc?
{
{
/* ARC/ARC
/* ARC/ARC
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/2circle/
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/2circle/
*/
*/
double
x0
=
p1
->
Xc
();
double
x0
=
p1
->
Xc
();
double
y0
=
p1
->
Yc
();
// Center of first Arc
double
y0
=
p1
->
Yc
();
// Center of first Arc
double
r0
=
dist
(
x0
,
y0
,
p1
->
X
(),
p1
->
Y
());
// Calc the radius
double
r0
=
dist
(
x0
,
y0
,
p1
->
X
(),
p1
->
Y
());
// Calc the radius
double
x1
=
q1
->
Xc
();
double
x1
=
q1
->
Xc
();
double
y1
=
q1
->
Yc
();
// Center of second Arc
double
y1
=
q1
->
Yc
();
// Center of second Arc
double
r1
=
dist
(
x1
,
y1
,
q1
->
X
(),
q1
->
Y
());
// Calc the radius
double
r1
=
dist
(
x1
,
y1
,
q1
->
X
(),
q1
->
Y
());
// Calc the radius
double
dx
=
x1
-
x0
;
// dx and dy are the vertical and horizontal
double
dx
=
x1
-
x0
;
// dx and dy are the vertical and horizontal
double
dy
=
y1
-
y0
;
// distances between the circle centers.
double
dy
=
y1
-
y0
;
// distances between the circle centers.
double
d
=
sqrt
((
dy
*
dy
)
+
(
dx
*
dx
));
// Distance between the centers.
double
d
=
sqrt
((
dy
*
dy
)
+
(
dx
*
dx
));
// Distance between the centers.
if
(
d
>
(
r0
+
r1
))
// Check for solvability.
if
(
d
>
(
r0
+
r1
))
// Check for solvability.
{
// no solution. circles do not intersect.
{
// no solution. circles do not intersect.
found
=
FALSE
;
found
=
FALSE
;
}
}
else
if
(
d
<
abs
(
r0
-
r1
)
)
else
if
(
d
<
abs
(
r0
-
r1
)
)
{
// no solution. one circle inside the other
{
// no solution. one circle inside the other
found
=
FALSE
;
found
=
FALSE
;
}
}
else
else
{
{
/*
/*
** 'xy2' is the point where the line through the circle intersection
** 'xy2' is the point where the line through the circle intersection
** points crosses the line between the circle centers.
** points crosses the line between the circle centers.
*/
*/
double
a
=
((
r0
*
r0
)
-
(
r1
*
r1
)
+
(
d
*
d
))
/
(
2.0
*
d
);
// Calc the distance from xy0 to xy2.
double
a
=
((
r0
*
r0
)
-
(
r1
*
r1
)
+
(
d
*
d
))
/
(
2.0
*
d
);
// Calc the distance from xy0 to xy2.
double
x2
=
x0
+
(
dx
*
a
/
d
);
// Determine the coordinates of xy2.
double
x2
=
x0
+
(
dx
*
a
/
d
);
// Determine the coordinates of xy2.
double
y2
=
y0
+
(
dy
*
a
/
d
);
double
y2
=
y0
+
(
dy
*
a
/
d
);
if
(
d
==
(
r0
+
r1
))
// Arcs touch at xy2 exactly (unlikely)
if
(
d
==
(
r0
+
r1
))
// Arcs touch at xy2 exactly (unlikely)
{
{
alphaP
[
0
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x2
,
y2
,
pt
);
alphaP
[
0
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x2
,
y2
,
pt
);
alphaQ
[
0
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x2
,
y2
,
qt
);
alphaQ
[
0
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x2
,
y2
,
qt
);
if
((
alphaP
[
0
]
>
0
&&
alphaP
[
0
]
<
1
)
&&
(
alphaQ
[
0
]
>
0
&&
alphaQ
[
0
]
<
1
))
if
((
alphaP
[
0
]
>
0
&&
alphaP
[
0
]
<
1
)
&&
(
alphaQ
[
0
]
>
0
&&
alphaQ
[
0
]
<
1
))
{
{
ix
[
0
]
=
x2
;
ix
[
0
]
=
x2
;
iy
[
0
]
=
y2
;
iy
[
0
]
=
y2
;
*
n
=
1
;
found
=
TRUE
;
*
n
=
1
;
found
=
TRUE
;
}
}
}
}
else
// Arcs intersect at two points
else
// Arcs intersect at two points
{
{
double
alP
[
2
],
alQ
[
2
];
double
alP
[
2
],
alQ
[
2
];
double
h
=
sqrt
((
r0
*
r0
)
-
(
a
*
a
));
// Calc the distance from xy2 to either
double
h
=
sqrt
((
r0
*
r0
)
-
(
a
*
a
));
// Calc the distance from xy2 to either
// of the intersection points.
// of the intersection points.
double
rx
=
-
dy
*
(
h
/
d
);
// Now determine the offsets of the
double
rx
=
-
dy
*
(
h
/
d
);
// Now determine the offsets of the
double
ry
=
dx
*
(
h
/
d
);
double
ry
=
dx
*
(
h
/
d
);
// intersection points from xy2
// intersection points from xy2
double
x
[
2
],
y
[
2
];
double
x
[
2
],
y
[
2
];
x
[
0
]
=
x2
+
rx
;
x
[
1
]
=
x2
-
rx
;
// Calc the absolute intersection points.
x
[
0
]
=
x2
+
rx
;
x
[
1
]
=
x2
-
rx
;
// Calc the absolute intersection points.
y
[
0
]
=
y2
+
ry
;
y
[
1
]
=
y2
-
ry
;
y
[
0
]
=
y2
+
ry
;
y
[
1
]
=
y2
-
ry
;
alP
[
0
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x
[
0
],
y
[
0
],
pt
);
alP
[
0
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x
[
0
],
y
[
0
],
pt
);
alQ
[
0
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x
[
0
],
y
[
0
],
qt
);
alQ
[
0
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x
[
0
],
y
[
0
],
qt
);
alP
[
1
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x
[
1
],
y
[
1
],
pt
);
alP
[
1
]
=
aAlpha
(
p1
->
X
(),
p1
->
Y
(),
p2
->
X
(),
p2
->
Y
(),
x0
,
y0
,
x
[
1
],
y
[
1
],
pt
);
alQ
[
1
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x
[
1
],
y
[
1
],
qt
);
alQ
[
1
]
=
aAlpha
(
q1
->
X
(),
q1
->
Y
(),
q2
->
X
(),
q2
->
Y
(),
x1
,
y1
,
x
[
1
],
y
[
1
],
qt
);
for
(
int
i
=
0
;
i
<=
1
;
i
++
)
for
(
int
i
=
0
;
i
<=
1
;
i
++
)
if
((
alP
[
i
]
>
0
&&
alP
[
i
]
<
1
)
&&
(
alQ
[
i
]
>
0
&&
alQ
[
i
]
<
1
))
if
((
alP
[
i
]
>
0
&&
alP
[
i
]
<
1
)
&&
(
alQ
[
i
]
>
0
&&
alQ
[
i
]
<
1
))
{
{
ix
[
*
n
]
=
x
[
i
];
ix
[
*
n
]
=
x
[
i
];
iy
[
*
n
]
=
y
[
i
];
iy
[
*
n
]
=
y
[
i
];
alphaP
[
*
n
]
=
alP
[
i
];
alphaP
[
*
n
]
=
alP
[
i
];
alphaQ
[
*
n
]
=
alQ
[
i
];
alphaQ
[
*
n
]
=
alQ
[
i
];
*
n
++
;
*
n
++
;
found
=
TRUE
;
found
=
TRUE
;
}
}
}
}
}
}
}
// End of find Arc/Arc intersection
}
// End of find Arc/Arc intersection
else
// It must be Arc/Line
else
// It must be Arc/Line
{
{
/* ARC/LINE
/* ARC/LINE
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/sphereline/
** Algorithm from: http://astronomy.swin.edu.au/~pbourke/geometry/sphereline/
*/
*/
double
d
,
x1
,
x2
,
xc
,
xs
,
xe
;
double
d
,
x1
,
x2
,
xc
,
xs
,
xe
;
double
y1
,
y2
,
yc
,
ys
,
ye
;
double
y1
,
y2
,
yc
,
ys
,
ye
;
if
(
pt
==
0
)
// Segment p1,p2 is the line
if
(
pt
==
0
)
// Segment p1,p2 is the line
{
// Segment q1,q2 is the arc
{
// Segment q1,q2 is the arc
x1
=
p1
->
X
();
x1
=
p1
->
X
();
y1
=
p1
->
Y
();
y1
=
p1
->
Y
();
x2
=
p2
->
X
();
x2
=
p2
->
X
();
y2
=
p2
->
Y
();
y2
=
p2
->
Y
();
xc
=
q1
->
Xc
();
xc
=
q1
->
Xc
();
yc
=
q1
->
Yc
();
yc
=
q1
->
Yc
();
xs
=
q1
->
X
();
xs
=
q1
->
X
();
ys
=
q1
->
Y
();
ys
=
q1
->
Y
();
xe
=
q2
->
X
();
xe
=
q2
->
X
();
ye
=
q2
->
Y
();
ye
=
q2
->
Y
();
d
=
qt
;
d
=
qt
;
}
}
else
// Segment q1,q2 is the line
else
// Segment q1,q2 is the line
{
// Segment p1,p2 is the arc
{
// Segment p1,p2 is the arc
x1
=
q1
->
X
();
y1
=
q1
->
Y
();
x1
=
q1
->
X
();
y1
=
q1
->
Y
();
x2
=
q2
->
X
();
y2
=
q2
->
Y
();
x2
=
q2
->
X
();
y2
=
q2
->
Y
();
xc
=
p1
->
Xc
();
yc
=
p1
->
Yc
();
xc
=
p1
->
Xc
();
yc
=
p1
->
Yc
();
xs
=
p1
->
X
();
ys
=
p1
->
Y
();
xs
=
p1
->
X
();
ys
=
p1
->
Y
();
xe
=
p2
->
X
();
ye
=
p2
->
Y
();
xe
=
p2
->
X
();
ye
=
p2
->
Y
();
d
=
pt
;
d
=
pt
;
}
}
double
r
=
dist
(
xc
,
yc
,
xs
,
ys
);
double
r
=
dist
(
xc
,
yc
,
xs
,
ys
);
double
a
=
pow
((
x2
-
x1
),
2
)
+
pow
((
y2
-
y1
),
2
);
double
a
=
pow
((
x2
-
x1
),
2
)
+
pow
((
y2
-
y1
),
2
);
double
b
=
2
*
(
(
x2
-
x1
)
*
(
x1
-
xc
)
double
b
=
2
*
(
(
x2
-
x1
)
*
(
x1
-
xc
)
+
(
y2
-
y1
)
*
(
y1
-
yc
)
);
+
(
y2
-
y1
)
*
(
y1
-
yc
)
);
double
c
=
pow
(
xc
,
2
)
+
pow
(
yc
,
2
)
+
double
c
=
pow
(
xc
,
2
)
+
pow
(
yc
,
2
)
+
pow
(
x1
,
2
)
+
pow
(
y1
,
2
)
-
pow
(
x1
,
2
)
+
pow
(
y1
,
2
)
-
2
*
(
xc
*
x1
+
yc
*
y1
)
-
pow
(
r
,
2
);
2
*
(
xc
*
x1
+
yc
*
y1
)
-
pow
(
r
,
2
);
double
i
=
b
*
b
-
4
*
a
*
c
;
double
i
=
b
*
b
-
4
*
a
*
c
;
if
(
i
<
0.0
)
// no intersection
if
(
i
<
0.0
)
// no intersection
{
{
found
=
FALSE
;
found
=
FALSE
;
}
}
else
if
(
i
==
0.0
)
// one intersection
else
if
(
i
==
0.0
)
// one intersection
{
{
double
mu
=
-
b
/
(
2
*
a
);
double
mu
=
-
b
/
(
2
*
a
);
double
x
=
x1
+
mu
*
(
x2
-
x1
);
double
x
=
x1
+
mu
*
(
x2
-
x1
);
double
y
=
y1
+
mu
*
(
y2
-
y1
);
double
y
=
y1
+
mu
*
(
y2
-
y1
);
double
al
=
mu
;
// Line Alpha
double
al
=
mu
;
// Line Alpha
double
aa
=
this
->
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
,
y
,
d
);
// Arc Alpha
double
aa
=
this
->
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
,
y
,
d
);
// Arc Alpha
if
((
al
>
0
&&
al
<
1
)
&&
(
aa
>
0
&&
aa
<
1
))
if
((
al
>
0
&&
al
<
1
)
&&
(
aa
>
0
&&
aa
<
1
))
{
{
ix
[
0
]
=
x
;
iy
[
0
]
=
y
;
ix
[
0
]
=
x
;
iy
[
0
]
=
y
;
*
n
=
1
;
*
n
=
1
;
found
=
TRUE
;
found
=
TRUE
;
if
(
pt
==
0
)
if
(
pt
==
0
)
{
{
alphaP
[
0
]
=
al
;
alphaQ
[
0
]
=
aa
;
alphaP
[
0
]
=
al
;
alphaQ
[
0
]
=
aa
;
}
}
else
else
{
{
alphaP
[
0
]
=
aa
;
alphaQ
[
0
]
=
al
;
alphaP
[
0
]
=
aa
;
alphaQ
[
0
]
=
al
;
}
}
}
}
}
}
else
if
(
i
>
0.0
)
// two intersections
else
if
(
i
>
0.0
)
// two intersections
{
{
double
mu
[
2
],
x
[
2
],
y
[
2
],
al
[
2
],
aa
[
2
];
double
mu
[
2
],
x
[
2
],
y
[
2
],
al
[
2
],
aa
[
2
];
mu
[
0
]
=
(
-
b
+
sqrt
(
pow
(
b
,
2
)
-
4
*
a
*
c
))
/
(
2
*
a
);
// first intersection
mu
[
0
]
=
(
-
b
+
sqrt
(
pow
(
b
,
2
)
-
4
*
a
*
c
))
/
(
2
*
a
);
// first intersection
x
[
0
]
=
x1
+
mu
[
0
]
*
(
x2
-
x1
);
x
[
0
]
=
x1
+
mu
[
0
]
*
(
x2
-
x1
);
y
[
0
]
=
y1
+
mu
[
0
]
*
(
y2
-
y1
);
y
[
0
]
=
y1
+
mu
[
0
]
*
(
y2
-
y1
);
mu
[
1
]
=
(
-
b
-
sqrt
(
pow
(
b
,
2
)
-
4
*
a
*
c
))
/
(
2
*
a
);
// second intersection
mu
[
1
]
=
(
-
b
-
sqrt
(
pow
(
b
,
2
)
-
4
*
a
*
c
))
/
(
2
*
a
);
// second intersection
x
[
1
]
=
x1
+
mu
[
1
]
*
(
x2
-
x1
);
x
[
1
]
=
x1
+
mu
[
1
]
*
(
x2
-
x1
);
y
[
1
]
=
y1
+
mu
[
1
]
*
(
y2
-
y1
);
y
[
1
]
=
y1
+
mu
[
1
]
*
(
y2
-
y1
);
al
[
0
]
=
mu
[
0
];
al
[
0
]
=
mu
[
0
];
aa
[
0
]
=
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
[
0
],
y
[
0
],
d
);
aa
[
0
]
=
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
[
0
],
y
[
0
],
d
);
al
[
1
]
=
mu
[
1
];
al
[
1
]
=
mu
[
1
];
aa
[
1
]
=
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
[
1
],
y
[
1
],
d
);
aa
[
1
]
=
aAlpha
(
xs
,
ys
,
xe
,
ye
,
xc
,
yc
,
x
[
1
],
y
[
1
],
d
);
for
(
int
i
=
0
;
i
<=
1
;
i
++
)
for
(
int
i
=
0
;
i
<=
1
;
i
++
)
if
((
al
[
i
]
>
0
&&
al
[
i
]
<
1
)
&&
(
aa
[
i
]
>
0
&&
aa
[
i
]
<
1
))
if
((
al
[
i
]
>
0
&&
al
[
i
]
<
1
)
&&
(
aa
[
i
]
>
0
&&
aa
[
i
]
<
1
))
{
{
ix
[
*
n
]
=
x
[
i
];
ix
[
*
n
]
=
x
[
i
];
iy
[
*
n
]
=
y
[
i
];
iy
[
*
n
]
=
y
[
i
];
if
(
pt
==
0
)
if
(
pt
==
0
)
{
{
alphaP
[
*
n
]
=
al
[
i
];
alphaP
[
*
n
]
=
al
[
i
];
alphaQ
[
*
n
]
=
aa
[
i
];
alphaQ
[
*
n
]
=
aa
[
i
];
}
}
else
else
{
{
alphaP
[
*
n
]
=
aa
[
i
];
alphaP
[
*
n
]
=
aa
[
i
];
alphaQ
[
*
n
]
=
al
[
i
];
alphaQ
[
*
n
]
=
al
[
i
];
}
}
*
n
++
;
*
n
++
;
found
=
TRUE
;
found
=
TRUE
;
}
}
}
}
}
// End of find Arc/Line intersection
}
// End of find Arc/Line intersection
return
found
;
return
found
;
}
// end of intersect function
}
// end of intersect function
/*
/*
** Test if a vertex lies inside the polygon
** Test if a vertex lies inside the polygon
**
**
** This function calculates the "winding" number for the point. This number
** This function calculates the "winding" number for the point. This number
** represents the number of times a ray emitted from the point to infinity
** represents the number of times a ray emitted from the point to infinity
** intersects any edge of the polygon. An even winding number means the point
** intersects any edge of the polygon. An even winding number means the point
** lies OUTSIDE the polygon, an odd number means it lies INSIDE it.
** lies OUTSIDE the polygon, an odd number means it lies INSIDE it.
**
**
** Right now infinity is set to -10000000, some people might argue that infinity
** Right now infinity is set to -10000000, some people might argue that infinity
** actually is a bit bigger. Those people have no lives.
** actually is a bit bigger. Those people have no lives.
**
**
** Allan Wright 4/16/2006: I guess I have no life: I had to increase it to -1000000000
** Allan Wright 4/16/2006: I guess I have no life: I had to increase it to -1000000000
*/
*/
BOOL
polygon
::
isInside
(
vertex
*
v
)
BOOL
polygon
::
isInside
(
vertex
*
v
)
{
{
//** modified for testing
//** modified for testing
if
(
v
->
isIntersect
()
)
if
(
v
->
isIntersect
()
)
ASSERT
(
0
);
ASSERT
(
0
);
int
winding_number
=
0
;
int
winding_number
=
0
;
int
winding_number2
=
0
;
int
winding_number2
=
0
;
int
winding_number3
=
0
;
int
winding_number3
=
0
;
int
winding_number4
=
0
;
int
winding_number4
=
0
;
//** vertex * point_at_infinity = new vertex(-10000000,v->Y()); // Create point at infinity
//** vertex * point_at_infinity = new vertex(-10000000,v->Y()); // Create point at infinity
vertex
*
point_at_infinity
=
new
vertex
(
-
1000000000
,
-
50000000
);
// Create point at infinity
vertex
*
point_at_infinity
=
new
vertex
(
-
1000000000
,
-
50000000
);
// Create point at infinity
vertex
*
point_at_infinity2
=
new
vertex
(
1000000000
,
+
50000000
);
// Create point at infinity
vertex
*
point_at_infinity2
=
new
vertex
(
1000000000
,
+
50000000
);
// Create point at infinity
vertex
*
point_at_infinity3
=
new
vertex
(
500000000
,
1000000000
);
// Create point at infinity
vertex
*
point_at_infinity3
=
new
vertex
(
500000000
,
1000000000
);
// Create point at infinity
vertex
*
point_at_infinity4
=
new
vertex
(
-
500000000
,
1000000000
);
// Create point at infinity
vertex
*
point_at_infinity4
=
new
vertex
(
-
500000000
,
1000000000
);
// Create point at infinity
vertex
*
q
=
m_first
;
// End vertex of a line segment in polygon
vertex
*
q
=
m_first
;
// End vertex of a line segment in polygon
do
do
{
{
if
(
!
q
->
isIntersect
())
if
(
!
q
->
isIntersect
())
{
{
int
n
;
int
n
;
double
x
[
2
],
y
[
2
],
aP
[
2
],
aQ
[
2
];
double
x
[
2
],
y
[
2
],
aP
[
2
],
aQ
[
2
];
if
(
ints
(
point_at_infinity
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
if
(
ints
(
point_at_infinity
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
winding_number
+=
n
;
// Add number of intersections found
winding_number
+=
n
;
// Add number of intersections found
if
(
ints
(
point_at_infinity2
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
if
(
ints
(
point_at_infinity2
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
winding_number2
+=
n
;
// Add number of intersections found
winding_number2
+=
n
;
// Add number of intersections found
if
(
ints
(
point_at_infinity3
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
if
(
ints
(
point_at_infinity3
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
winding_number3
+=
n
;
// Add number of intersections found
winding_number3
+=
n
;
// Add number of intersections found
if
(
ints
(
point_at_infinity4
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
if
(
ints
(
point_at_infinity4
,
v
,
q
,
nxt
(
q
->
Next
()),
&
n
,
x
,
y
,
aP
,
aQ
)
)
winding_number4
+=
n
;
// Add number of intersections found
winding_number4
+=
n
;
// Add number of intersections found
}
}
q
=
q
->
Next
();
q
=
q
->
Next
();
}
}
while
(
q
->
id
()
!=
m_first
->
id
()
);
while
(
q
->
id
()
!=
m_first
->
id
()
);
delete
point_at_infinity
;
delete
point_at_infinity
;
delete
point_at_infinity2
;
delete
point_at_infinity2
;
if
(
winding_number
%
2
!=
winding_number2
%
2
if
(
winding_number
%
2
!=
winding_number2
%
2
||
winding_number3
%
2
!=
winding_number4
%
2
||
winding_number3
%
2
!=
winding_number4
%
2
||
winding_number
%
2
!=
winding_number3
%
2
)
||
winding_number
%
2
!=
winding_number3
%
2
)
ASSERT
(
0
);
ASSERT
(
0
);
if
(
winding_number
%
2
==
0
)
// Check even or odd
if
(
winding_number
%
2
==
0
)
// Check even or odd
return
FALSE
;
// even == outside
return
FALSE
;
// even == outside
else
else
return
TRUE
;
// odd == inside
return
TRUE
;
// odd == inside
}
}
/*
/*
** Execute a Boolean operation on a polygon
** Execute a Boolean operation on a polygon
**
**
** This is the key method. It allows you to AND/OR this polygon with another one
** This is the key method. It allows you to AND/OR this polygon with another one
** (equvalent to a UNION or INTERSECT operation. You may also subtract one from
** (equvalent to a UNION or INTERSECT operation. You may also subtract one from
** the other (same as DIFFERENCE). Given two polygons A, B the following operations
** the other (same as DIFFERENCE). Given two polygons A, B the following operations
** may be performed:
** may be performed:
**
**
** A|B ... A OR B (Union of A and B)
** A|B ... A OR B (Union of A and B)
** A&B ... A AND B (Intersection of A and B)
** A&B ... A AND B (Intersection of A and B)
** A\B ... A - B
** A\B ... A - B
** B\A ... B - A
** B\A ... B - A
**
**
** A is the object and B is the polygon passed to the method.
** A is the object and B is the polygon passed to the method.
*/
*/
polygon
*
polygon
::
boolean
(
polygon
*
polyB
,
int
oper
)
polygon
*
polygon
::
boolean
(
polygon
*
polyB
,
int
oper
)
{
{
polygon
*
last
=
NULL
;
polygon
*
last
=
NULL
;
vertex
*
s
=
m_first
;
// First vertex of the subject polygon
vertex
*
s
=
m_first
;
// First vertex of the subject polygon
vertex
*
c
=
polyB
->
getFirst
();
// First vertex of the "clip" polygon
vertex
*
c
=
polyB
->
getFirst
();
// First vertex of the "clip" polygon
/*
/*
** Phase 1 of the algoritm is to find all intersection points between the two
** Phase 1 of the algoritm is to find all intersection points between the two
** polygons. A new vertex is created for each intersection and it is added to
** polygons. A new vertex is created for each intersection and it is added to
** the linked lists for both polygons. The "neighbor" reference in each vertex
** the linked lists for both polygons. The "neighbor" reference in each vertex
** stores the link between the same intersection point in each polygon.
** stores the link between the same intersection point in each polygon.
*/
*/
TRACE
(
"boolean...phase 1
\n
"
);
TRACE
(
"boolean...phase 1
\n
"
);
do
do
{
{
TRACE
(
"s=(%f,%f) to (%f,%f) I=%d
\n
"
,
TRACE
(
"s=(%f,%f) to (%f,%f) I=%d
\n
"
,
s
->
m_x
,
s
->
m_y
,
s
->
m_nextV
->
m_x
,
s
->
m_nextV
->
m_y
,
s
->
m_intersect
);
s
->
m_x
,
s
->
m_y
,
s
->
m_nextV
->
m_x
,
s
->
m_nextV
->
m_y
,
s
->
m_intersect
);
if
(
!
s
->
isIntersect
())
if
(
!
s
->
isIntersect
())
{
{
do
do
{
{
TRACE
(
" c=(%f,%f) to (%f,%f) I=%d
\n
"
,
TRACE
(
" c=(%f,%f) to (%f,%f) I=%d
\n
"
,
c
->
m_x
,
c
->
m_y
,
c
->
m_nextV
->
m_x
,
c
->
m_nextV
->
m_y
,
c
->
m_intersect
);
c
->
m_x
,
c
->
m_y
,
c
->
m_nextV
->
m_x
,
c
->
m_nextV
->
m_y
,
c
->
m_intersect
);
if
(
!
c
->
isIntersect
())
if
(
!
c
->
isIntersect
())
{
{
int
n
;
int
n
;
double
ix
[
2
],
iy
[
2
],
alphaS
[
2
],
alphaC
[
2
];
double
ix
[
2
],
iy
[
2
],
alphaS
[
2
],
alphaC
[
2
];
BOOL
bInt
=
ints
(
s
,
nxt
(
s
->
Next
()),
c
,
polyB
->
nxt
(
c
->
Next
()),
&
n
,
ix
,
iy
,
alphaS
,
alphaC
);
BOOL
bInt
=
ints
(
s
,
nxt
(
s
->
Next
()),
c
,
polyB
->
nxt
(
c
->
Next
()),
&
n
,
ix
,
iy
,
alphaS
,
alphaC
);
if
(
bInt
)
if
(
bInt
)
{
{
TRACE
(
" int at (%f,%f) aS = %.17f, aC = %.17f
\n
"
,
ix
[
0
],
iy
[
0
],
alphaS
[
0
],
alphaC
[
0
]
);
TRACE
(
" int at (%f,%f) aS = %.17f, aC = %.17f
\n
"
,
ix
[
0
],
iy
[
0
],
alphaS
[
0
],
alphaC
[
0
]
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
{
vertex
*
is
=
new
vertex
(
ix
[
i
],
iy
[
i
],
s
->
Xc
(),
s
->
Yc
(),
s
->
d
(),
NULL
,
NULL
,
NULL
,
TRUE
,
NULL
,
alphaS
[
i
],
FALSE
,
FALSE
);
vertex
*
is
=
new
vertex
(
ix
[
i
],
iy
[
i
],
s
->
Xc
(),
s
->
Yc
(),
s
->
d
(),
NULL
,
NULL
,
NULL
,
TRUE
,
NULL
,
alphaS
[
i
],
FALSE
,
FALSE
);
vertex
*
ic
=
new
vertex
(
ix
[
i
],
iy
[
i
],
c
->
Xc
(),
c
->
Yc
(),
c
->
d
(),
NULL
,
NULL
,
NULL
,
TRUE
,
NULL
,
alphaC
[
i
],
FALSE
,
FALSE
);
vertex
*
ic
=
new
vertex
(
ix
[
i
],
iy
[
i
],
c
->
Xc
(),
c
->
Yc
(),
c
->
d
(),
NULL
,
NULL
,
NULL
,
TRUE
,
NULL
,
alphaC
[
i
],
FALSE
,
FALSE
);
is
->
setNeighbor
(
ic
);
is
->
setNeighbor
(
ic
);
ic
->
setNeighbor
(
is
);
ic
->
setNeighbor
(
is
);
insertSort
(
is
,
s
,
this
->
nxt
(
s
->
Next
()));
insertSort
(
is
,
s
,
this
->
nxt
(
s
->
Next
()));
polyB
->
insertSort
(
ic
,
c
,
polyB
->
nxt
(
c
->
Next
()));
polyB
->
insertSort
(
ic
,
c
,
polyB
->
nxt
(
c
->
Next
()));
}
}
}
}
}
// end if c is not an intersect point
}
// end if c is not an intersect point
c
=
c
->
Next
();
c
=
c
->
Next
();
}
}
while
(
c
->
id
()
!=
polyB
->
m_first
->
id
());
while
(
c
->
id
()
!=
polyB
->
m_first
->
id
());
}
// end if s not an intersect point
}
// end if s not an intersect point
s
=
s
->
Next
();
s
=
s
->
Next
();
}
}
while
(
s
->
id
()
!=
m_first
->
id
());
while
(
s
->
id
()
!=
m_first
->
id
());
//** for testing...check number of intersections in each poly
//** for testing...check number of intersections in each poly
TRACE
(
"boolean...phase 1 testing
\n
"
);
TRACE
(
"boolean...phase 1 testing
\n
"
);
int
n_ints
=
0
;
int
n_ints
=
0
;
s
=
m_first
;
s
=
m_first
;
do
do
{
{
if
(
s
->
isIntersect
()
)
if
(
s
->
isIntersect
()
)
n_ints
++
;
n_ints
++
;
s
=
s
->
Next
();
s
=
s
->
Next
();
}
while
(
s
->
id
()
!=
m_first
->
id
()
);
}
while
(
s
->
id
()
!=
m_first
->
id
()
);
int
n_polyB_ints
=
0
;
int
n_polyB_ints
=
0
;
s
=
polyB
->
m_first
;
s
=
polyB
->
m_first
;
do
do
{
{
if
(
s
->
isIntersect
()
)
if
(
s
->
isIntersect
()
)
n_polyB_ints
++
;
n_polyB_ints
++
;
s
=
s
->
Next
();
s
=
s
->
Next
();
}
while
(
s
->
id
()
!=
polyB
->
m_first
->
id
()
);
}
while
(
s
->
id
()
!=
polyB
->
m_first
->
id
()
);
if
(
n_ints
!=
n_polyB_ints
)
if
(
n_ints
!=
n_polyB_ints
)
ASSERT
(
0
);
ASSERT
(
0
);
if
(
n_ints
%
2
!=
0
)
if
(
n_ints
%
2
!=
0
)
ASSERT
(
0
);
ASSERT
(
0
);
//** end test
//** end test
/*
/*
** Phase 2 of the algorithm is to identify every intersection point as an
** Phase 2 of the algorithm is to identify every intersection point as an
** entry or exit point to the other polygon. This will set the entry bits
** entry or exit point to the other polygon. This will set the entry bits
** in each vertex object.
** in each vertex object.
**
**
** What is really stored in the entry record for each intersection is the
** What is really stored in the entry record for each intersection is the
** direction the algorithm should take when it arrives at that entry point.
** direction the algorithm should take when it arrives at that entry point.
** Depending in the operation requested (A&B, A|B, A/B, B/A) the direction is
** Depending in the operation requested (A&B, A|B, A/B, B/A) the direction is
** set as follows for entry points (f=foreward, b=Back), exit points are always set
** set as follows for entry points (f=foreward, b=Back), exit points are always set
** to the opposite:
** to the opposite:
** Enter Exit
** Enter Exit
** A B A B
** A B A B
** A|B b b f f
** A|B b b f f
** A&B f f b b
** A&B f f b b
** A\B b f f b
** A\B b f f b
** B\A f b b f
** B\A f b b f
**
**
** f = TRUE, b = FALSE when stored in the entry record
** f = TRUE, b = FALSE when stored in the entry record
*/
*/
BOOL
A
,
B
;
BOOL
A
,
B
;
switch
(
oper
)
switch
(
oper
)
{
{
case
A_OR_B
:
A
=
FALSE
;
B
=
FALSE
;
break
;
case
A_OR_B
:
A
=
FALSE
;
B
=
FALSE
;
break
;
case
A_AND_B
:
A
=
TRUE
;
B
=
TRUE
;
break
;
case
A_AND_B
:
A
=
TRUE
;
B
=
TRUE
;
break
;
case
A_MINUS_B
:
A
=
FALSE
;
B
=
TRUE
;
break
;
case
A_MINUS_B
:
A
=
FALSE
;
B
=
TRUE
;
break
;
case
B_MINUS_A
:
A
=
TRUE
;
B
=
FALSE
;
break
;
case
B_MINUS_A
:
A
=
TRUE
;
B
=
FALSE
;
break
;
default
:
A
=
TRUE
;
B
=
TRUE
;
break
;
default
:
A
=
TRUE
;
B
=
TRUE
;
break
;
}
}
s
=
m_first
;
s
=
m_first
;
//** testing
//** testing
if
(
s
->
isIntersect
()
)
if
(
s
->
isIntersect
()
)
ASSERT
(
0
);
ASSERT
(
0
);
//** end test
//** end test
BOOL
entry
;
BOOL
entry
;
if
(
polyB
->
isInside
(
s
))
// if we are already inside
if
(
polyB
->
isInside
(
s
))
// if we are already inside
entry
=
!
A
;
// next intersection must be an exit
entry
=
!
A
;
// next intersection must be an exit
else
// otherwise
else
// otherwise
entry
=
A
;
// next intersection must be an entry
entry
=
A
;
// next intersection must be an entry
do
do
{
{
if
(
s
->
isIntersect
())
if
(
s
->
isIntersect
())
{
{
s
->
setEntry
(
entry
);
s
->
setEntry
(
entry
);
entry
=
!
entry
;
entry
=
!
entry
;
}
}
s
=
s
->
Next
();
s
=
s
->
Next
();
}
}
while
(
s
->
id
()
!=
m_first
->
id
());
while
(
s
->
id
()
!=
m_first
->
id
());
/*
/*
** Repeat for other polygon
** Repeat for other polygon
*/
*/
c
=
polyB
->
m_first
;
c
=
polyB
->
m_first
;
if
(
this
->
isInside
(
c
))
// if we are already inside
if
(
this
->
isInside
(
c
))
// if we are already inside
entry
=
!
B
;
// next intersection must be an exit
entry
=
!
B
;
// next intersection must be an exit
else
// otherwise
else
// otherwise
entry
=
B
;
// next intersection must be an entry
entry
=
B
;
// next intersection must be an entry
do
do
{
{
if
(
c
->
isIntersect
())
if
(
c
->
isIntersect
())
{
{
c
->
setEntry
(
entry
);
c
->
setEntry
(
entry
);
entry
=
!
entry
;
entry
=
!
entry
;
}
}
c
=
c
->
Next
();
c
=
c
->
Next
();
}
}
while
(
c
->
id
()
!=
polyB
->
m_first
->
id
());
while
(
c
->
id
()
!=
polyB
->
m_first
->
id
());
/*
/*
** Phase 3 of the algorithm is to scan the linked lists of the
** Phase 3 of the algorithm is to scan the linked lists of the
** two input polygons an construct a linked list of result
** two input polygons an construct a linked list of result
** polygons. We start at the first intersection then depending
** polygons. We start at the first intersection then depending
** on whether it is an entry or exit point we continue building
** on whether it is an entry or exit point we continue building
** our result polygon by following the source or clip polygon
** our result polygon by following the source or clip polygon
** either forwards or backwards.
** either forwards or backwards.
*/
*/
while
(
this
->
unckd_remain
())
// Loop while unchecked intersections remain
while
(
this
->
unckd_remain
())
// Loop while unchecked intersections remain
{
{
vertex
*
v
=
first_unckd_intersect
();
// Get the first unchecked intersect point
vertex
*
v
=
first_unckd_intersect
();
// Get the first unchecked intersect point
polygon
*
r
=
new
polygon
;
// Create a new instance of that class
polygon
*
r
=
new
polygon
;
// Create a new instance of that class
do
do
{
{
v
->
setChecked
();
// Set checked flag true for this intersection
v
->
setChecked
();
// Set checked flag true for this intersection
if
(
v
->
isEntry
())
if
(
v
->
isEntry
())
{
{
do
do
{
{
v
=
v
->
Next
();
v
=
v
->
Next
();
vertex
*
nv
=
new
vertex
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(),
v
->
Yc
(),
v
->
d
());
vertex
*
nv
=
new
vertex
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(),
v
->
Yc
(),
v
->
d
());
r
->
add
(
nv
);
r
->
add
(
nv
);
}
}
while
(
!
v
->
isIntersect
());
while
(
!
v
->
isIntersect
());
}
}
else
else
{
{
do
do
{
{
v
=
v
->
Prev
();
v
=
v
->
Prev
();
vertex
*
nv
=
new
vertex
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(
FALSE
),
v
->
Yc
(
FALSE
),
v
->
d
(
FALSE
));
vertex
*
nv
=
new
vertex
(
v
->
X
(),
v
->
Y
(),
v
->
Xc
(
FALSE
),
v
->
Yc
(
FALSE
),
v
->
d
(
FALSE
));
r
->
add
(
nv
);
r
->
add
(
nv
);
}
}
while
(
!
v
->
isIntersect
());
while
(
!
v
->
isIntersect
());
}
}
v
=
v
->
Neighbor
();
v
=
v
->
Neighbor
();
}
}
while
(
!
v
->
isChecked
());
// until polygon closed
while
(
!
v
->
isChecked
());
// until polygon closed
if
(
last
)
// Check in case first time thru the loop
if
(
last
)
// Check in case first time thru the loop
r
->
m_first
->
setNextPoly
(
last
);
// Save ref to the last poly in the first vertex
r
->
m_first
->
setNextPoly
(
last
);
// Save ref to the last poly in the first vertex
// of this poly
// of this poly
last
=
r
;
// Save this polygon
last
=
r
;
// Save this polygon
}
// end of while there is another intersection to check
}
// end of while there is another intersection to check
/*
/*
** Clean up the input polygons by deleting the intersection points
** Clean up the input polygons by deleting the intersection points
*/
*/
res
();
res
();
polyB
->
res
();
polyB
->
res
();
/*
/*
** It is possible that no intersection between the polygons was found and
** It is possible that no intersection between the polygons was found and
** there is no result to return. In this case we make function fail
** there is no result to return. In this case we make function fail
** gracefully as follows (depending on the requested operation):
** gracefully as follows (depending on the requested operation):
**
**
** A|B : Return this with polyB in m_first->nextPoly
** A|B : Return this with polyB in m_first->nextPoly
** A&B : Return this
** A&B : Return this
** A\B : Return this
** A\B : Return this
** B\A : return polyB
** B\A : return polyB
*/
*/
polygon
*
p
;
polygon
*
p
;
if
(
!
last
)
if
(
!
last
)
{
{
switch
(
oper
)
switch
(
oper
)
{
{
case
A_OR_B
:
case
A_OR_B
:
last
=
copy_poly
();
last
=
copy_poly
();
p
=
polyB
->
copy_poly
();
p
=
polyB
->
copy_poly
();
last
->
m_first
->
setNextPoly
(
p
);
last
->
m_first
->
setNextPoly
(
p
);
break
;
break
;
case
A_AND_B
:
case
A_AND_B
:
last
=
copy_poly
();
last
=
copy_poly
();
break
;
break
;
case
A_MINUS_B
:
case
A_MINUS_B
:
last
=
copy_poly
();
last
=
copy_poly
();
break
;
break
;
case
B_MINUS_A
:
case
B_MINUS_A
:
last
=
polyB
->
copy_poly
();
last
=
polyB
->
copy_poly
();
break
;
break
;
default
:
default
:
last
=
copy_poly
();
last
=
copy_poly
();
break
;
break
;
}
}
}
}
else
if
(
m_first
->
m_nextPoly
)
else
if
(
m_first
->
m_nextPoly
)
{
{
last
->
m_first
->
m_nextPoly
=
m_first
->
NextPoly
();
last
->
m_first
->
m_nextPoly
=
m_first
->
NextPoly
();
}
}
return
last
;
return
last
;
}
// end of boolean function
}
// end of boolean function
/*
/*
** Test if a polygon lies entirly inside this polygon
** Test if a polygon lies entirly inside this polygon
**
**
** First every point in the polygon is tested to determine if it is
** First every point in the polygon is tested to determine if it is
** inside this polygon. If all points are inside, then the second
** inside this polygon. If all points are inside, then the second
** test is performed that looks for any intersections between the
** test is performed that looks for any intersections between the
** two polygons. If no intersections are found then the polygon
** two polygons. If no intersections are found then the polygon
** must be completely enclosed by this polygon.
** must be completely enclosed by this polygon.
*/
*/
#if 0
#if 0
function polygon::isPolyInside (p)
function polygon::isPolyInside (p)
{
{
inside = TRUE;
inside = TRUE;
c = p->getFirst(); // Get the first vertex in polygon p
c = p->getFirst(); // Get the first vertex in polygon p
do
do
{
{
if (!this->isInside(c)) // If vertex is NOT inside this polygon
if (!this->isInside(c)) // If vertex is NOT inside this polygon
inside = FALSE; // then set flag to false
inside = FALSE; // then set flag to false
c = c->Next(); // Get the next vertex in polygon p
c = c->Next(); // Get the next vertex in polygon p
}
}
while (c->id() != p->first->id());
while (c->id() != p->first->id());
if (inside)
if (inside)
{
{
c = p->getFirst(); // Get the first vertex in polygon p
c = p->getFirst(); // Get the first vertex in polygon p
s = getFirst(); // Get the first vertex in this polygon
s = getFirst(); // Get the first vertex in this polygon
do
do
{
{
do
do
{
{
if (this->ints(s, s->Next(),c, c->Next(), n, x, y, aS, aC))
if (this->ints(s, s->Next(),c, c->Next(), n, x, y, aS, aC))
inside = FALSE;
inside = FALSE;
c = c->Next();
c = c->Next();
}
}
while (c->id() != p->first->id());
while (c->id() != p->first->id());
s = s->Next();
s = s->Next();
}
}
while (s->id() != m_first->id());
while (s->id() != m_first->id());
}
}
return inside;
return inside;
} // end of isPolyInside
} // end of isPolyInside
/*
/*
** Move Polygon
** Move Polygon
**
**
** Translates polygon by delta X and delta Y
** Translates polygon by delta X and delta Y
*/
*/
function polygon::move (dx, dy)
function polygon::move (dx, dy)
{
{
v = getFirst();
v = getFirst();
do
do
{
{
v->setX(v->X() + dx);
v->setX(v->X() + dx);
v->setY(v->Y() + dy);
v->setY(v->Y() + dy);
if (v->d() != 0)
if (v->d() != 0)
{
{
v->setXc(v->Xc() + dx);
v->setXc(v->Xc() + dx);
v->setYc(v->Yc() + dy);
v->setYc(v->Yc() + dy);
}
}
v = v->Next();
v = v->Next();
}
}
while(v->id() != m_first->id());
while(v->id() != m_first->id());
} // end of move polygon
} // end of move polygon
/*
/*
** Rotate Polygon
** Rotate Polygon
**
**
** Rotates a polgon about point xr/yr by a radians
** Rotates a polgon about point xr/yr by a radians
*/
*/
function polygon::rotate (xr, yr, a)
function polygon::rotate (xr, yr, a)
{
{
this->move(-xr,-yr); // Move the polygon so that the point of
this->move(-xr,-yr); // Move the polygon so that the point of
// rotation is at the origin (0,0)
// rotation is at the origin (0,0)
if (a < 0) // We might be passed a negitive angle
if (a < 0) // We might be passed a negitive angle
a += 2*pi(); // make it positive
a += 2*pi(); // make it positive
v = m_first;
v = m_first;
do
do
{
{
x=v->X(); y=v->Y();
x=v->X(); y=v->Y();
v->setX(x*cos(a) - y*sin(a)); // x' = xCos(a)-ySin(a)
v->setX(x*cos(a) - y*sin(a)); // x' = xCos(a)-ySin(a)
v->setY(x*sin(a) + y*cos(a)); // y' = xSin(a)+yCos(a)
v->setY(x*sin(a) + y*cos(a)); // y' = xSin(a)+yCos(a)
if (v->d() != 0)
if (v->d() != 0)
{
{
x=v->Xc(); y=v->Yc();
x=v->Xc(); y=v->Yc();
v->setXc(x*cos(a) - y*sin(a));
v->setXc(x*cos(a) - y*sin(a));
v->setYc(x*sin(a) + y*cos(a));
v->setYc(x*sin(a) + y*cos(a));
}
}
v = v->Next();
v = v->Next();
}
}
while(v->id() != m_first->id());
while(v->id() != m_first->id());
this->move(xr,yr); // Move the rotated polygon back
this->move(xr,yr); // Move the rotated polygon back
} // end of rotate polygon
} // end of rotate polygon
/*
/*
** Return Bounding Rectangle for a Polygon
** Return Bounding Rectangle for a Polygon
**
**
** returns a polygon object that represents the bounding rectangle
** returns a polygon object that represents the bounding rectangle
** for this polygon. Arc segments are correctly handled.
** for this polygon. Arc segments are correctly handled.
*/
*/
function polygon::&bRect ()
function polygon::&bRect ()
{
{
minX = INF; minY = INF; maxX = -INF; maxY = -INF;
minX = INF; minY = INF; maxX = -INF; maxY = -INF;
v = m_first;
v = m_first;
do
do
{
{
if (v->d() != 0) // Is it an arc segment
if (v->d() != 0) // Is it an arc segment
{
{
vn = v->Next(); // end vertex of the arc segment
vn = v->Next(); // end vertex of the arc segment
v1 = new vertex(v->Xc(), -infinity); // bottom point of vertical line thru arc center
v1 = new vertex(v->Xc(), -infinity); // bottom point of vertical line thru arc center
v2 = new vertex(v->Xc(), +infinity); // top point of vertical line thru arc center
v2 = new vertex(v->Xc(), +infinity); // top point of vertical line thru arc center
if (this->ints(v, vn, v1, v2, n, x, y, aS, aC)) // Does line intersect the arc ?
if (this->ints(v, vn, v1, v2, n, x, y, aS, aC)) // Does line intersect the arc ?
{
{
for (i=0; i<n; i++) // check y portion of all intersections
for (i=0; i<n; i++) // check y portion of all intersections
{
{
minY = min(minY, y[i], v->Y());
minY = min(minY, y[i], v->Y());
maxY = max(maxY, y[i], v->Y());
maxY = max(maxY, y[i], v->Y());
}
}
}
}
else // There was no intersection so bounding rect is determined
else // There was no intersection so bounding rect is determined
{ // by the start point only, not teh edge of the arc
{ // by the start point only, not teh edge of the arc
minY = min(minY, v->Y());
minY = min(minY, v->Y());
maxY = max(maxY, v->Y());
maxY = max(maxY, v->Y());
}
}
v1 = NULL; v2 = NULL; // Free the memory used
v1 = NULL; v2 = NULL; // Free the memory used
h1 = new vertex(-infinity, v->Yc()); // left point of horozontal line thru arc center
h1 = new vertex(-infinity, v->Yc()); // left point of horozontal line thru arc center
h2 = new vertex(+infinity, v->Yc()); // right point of horozontal line thru arc center
h2 = new vertex(+infinity, v->Yc()); // right point of horozontal line thru arc center
if (this->ints(v, vn, h1, h2, n, x, y, aS, aC)) // Does line intersect the arc ?
if (this->ints(v, vn, h1, h2, n, x, y, aS, aC)) // Does line intersect the arc ?
{
{
for (i=0; i<n; i++) // check x portion of all intersections
for (i=0; i<n; i++) // check x portion of all intersections
{
{
minX = min(minX, x[i], v->X());
minX = min(minX, x[i], v->X());
maxX = max(maxX, x[i], v->X());
maxX = max(maxX, x[i], v->X());
}
}
}
}
else
else
{
{
minX = min(minX, v->X());
minX = min(minX, v->X());
maxX = max(maxX, v->X());
maxX = max(maxX, v->X());
}
}
h1 = NULL; h2 = NULL;
h1 = NULL; h2 = NULL;
}
}
else // Straight segment so just check the vertex
else // Straight segment so just check the vertex
{
{
minX = min(minX, v->X());
minX = min(minX, v->X());
minY = min(minY, v->Y());
minY = min(minY, v->Y());
maxX = max(maxX, v->X());
maxX = max(maxX, v->X());
maxY = max(maxY, v->Y());
maxY = max(maxY, v->Y());
}
}
v = v->Next();
v = v->Next();
}
}
while(v->id() != m_first->id());
while(v->id() != m_first->id());
//
//
// Now create an return a polygon with the bounding rectangle
// Now create an return a polygon with the bounding rectangle
//
//
this_class = get_class(this); // Findout the class I'm in (might be an extension of polygon)
this_class = get_class(this); // Findout the class I'm in (might be an extension of polygon)
p = new this_class; // Create a new instance of that class
p = new this_class; // Create a new instance of that class
p->addv(minX,minY);
p->addv(minX,minY);
p->addv(minX,maxY);
p->addv(minX,maxY);
p->addv(maxX,maxY);
p->addv(maxX,maxY);
p->addv(maxX,minY);
p->addv(maxX,minY);
return p;
return p;
} // end of bounding rectangle
} // end of bounding rectangle
#endif
#endif
polygon/php_polygon.h
View file @
4ce4631d
// file php_polygon.h
// file php_polygon.h
// See comments in php_polygon.cpp
// See comments in php_polygon.cpp
#ifndef PHP_POLYGON_H
#ifndef PHP_POLYGON_H
#define PHP_POLYGON_H
#define PHP_POLYGON_H
class
vertex
;
class
vertex
;
class
segment
;
class
segment
;
#define infinity 100000000 // for places that are far far away
#define infinity 100000000 // for places that are far far away
#define PI 3.14159265359
#define PI 3.14159265359
enum
{
A_OR_B
,
A_AND_B
,
A_MINUS_B
,
B_MINUS_A
};
enum
{
A_OR_B
,
A_AND_B
,
A_MINUS_B
,
B_MINUS_A
};
class
polygon
class
polygon
{
{
public
:
public
:
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
** This class manages a doubly linked list of vertex objects that represents
** This class manages a doubly linked list of vertex objects that represents
** a polygon. The class consists of basic methods to manage the list
** a polygon. The class consists of basic methods to manage the list
** and methods to implement boolean operations between polygon objects.
** and methods to implement boolean operations between polygon objects.
*/
*/
vertex
*
m_first
;
// Reference to first vertex in the linked list
vertex
*
m_first
;
// Reference to first vertex in the linked list
int
m_cnt
;
// Tracks number of vertices in the polygon
int
m_cnt
;
// Tracks number of vertices in the polygon
polygon
(
vertex
*
first
=
NULL
);
polygon
(
vertex
*
first
=
NULL
);
~
polygon
();
~
polygon
();
vertex
*
getFirst
();
vertex
*
getFirst
();
polygon
*
NextPoly
();
polygon
*
NextPoly
();
void
add
(
vertex
*
nv
);
void
add
(
vertex
*
nv
);
void
addv
(
double
x
,
double
y
,
void
addv
(
double
x
,
double
y
,
double
xc
=
0
,
double
yc
=
0
,
int
d
=
0
);
double
xc
=
0
,
double
yc
=
0
,
int
d
=
0
);
vertex
*
del
(
vertex
*
v
);
vertex
*
del
(
vertex
*
v
);
void
res
();
void
res
();
polygon
*
copy_poly
();
polygon
*
copy_poly
();
void
insertSort
(
vertex
*
nv
,
vertex
*
s
,
vertex
*
e
);
void
insertSort
(
vertex
*
nv
,
vertex
*
s
,
vertex
*
e
);
vertex
*
nxt
(
vertex
*
v
);
vertex
*
nxt
(
vertex
*
v
);
BOOL
unckd_remain
();
BOOL
unckd_remain
();
vertex
*
first_unckd_intersect
();
vertex
*
first_unckd_intersect
();
double
dist
(
double
x1
,
double
y1
,
double
x2
,
double
y2
);
double
dist
(
double
x1
,
double
y1
,
double
x2
,
double
y2
);
double
angle
(
double
xc
,
double
yc
,
double
x1
,
double
y1
);
double
angle
(
double
xc
,
double
yc
,
double
x1
,
double
y1
);
double
aAlpha
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
aAlpha
(
double
x1
,
double
y1
,
double
x2
,
double
y2
,
double
xc
,
double
yc
,
double
xi
,
double
yi
,
double
d
);
double
xc
,
double
yc
,
double
xi
,
double
yi
,
double
d
);
void
perturb
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
void
perturb
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
double
aP
,
double
aQ
);
double
aP
,
double
aQ
);
BOOL
ints
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
BOOL
ints
(
vertex
*
p1
,
vertex
*
p2
,
vertex
*
q1
,
vertex
*
q2
,
int
*
n
,
double
ix
[],
double
iy
[],
double
alphaP
[],
double
alphaQ
[]
);
int
*
n
,
double
ix
[],
double
iy
[],
double
alphaP
[],
double
alphaQ
[]
);
BOOL
isInside
(
vertex
*
v
);
BOOL
isInside
(
vertex
*
v
);
polygon
*
boolean
(
polygon
*
polyB
,
int
oper
);
polygon
*
boolean
(
polygon
*
polyB
,
int
oper
);
#if 0
#if 0
function isPolyInside (p);
function isPolyInside (p);
function move (dx, dy);
function move (dx, dy);
function rotate (xr, yr, a);
function rotate (xr, yr, a);
function &bRect ();
function &bRect ();
#endif
#endif
};
//end of class polygon
};
//end of class polygon
#endif // ifndef PHP_POLYGON_H
#endif // ifndef PHP_POLYGON_H
polygon/php_polygon_vertex.cpp
View file @
4ce4631d
// file php_polygon_vertex.cpp
// file php_polygon_vertex.cpp
// This is a port of a php class written by Brenor Brophy (see below)
// This is a port of a php class written by Brenor Brophy (see below)
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
** File: vertex.php
** File: vertex.php
** Description: PHP class for a polygon vertex. Used as the base object to
** Description: PHP class for a polygon vertex. Used as the base object to
** build a class of polygons.
** build a class of polygons.
** Version: 1.1
** Version: 1.1
** Author: Brenor Brophy
** Author: Brenor Brophy
** Email: brenor at sbcglobal dot net
** Email: brenor at sbcglobal dot net
** Homepage: www.brenorbrophy.com
** Homepage: www.brenorbrophy.com
**------------------------------------------------------------------------------
**------------------------------------------------------------------------------
** COPYRIGHT (c) 2005 BRENOR BROPHY
** COPYRIGHT (c) 2005 BRENOR BROPHY
**
**
** The source code included in this package is free software; you can
** The source code included in this package is free software; you can
** redistribute it and/or modify it under the terms of the GNU General Public
** redistribute it and/or modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation. This license can be
** License as published by the Free Software Foundation. This license can be
** read at:
** read at:
**
**
** http://www.opensource.org/licenses/gpl-license.php
** http://www.opensource.org/licenses/gpl-license.php
**
**
** This program is distributed in the hope that it will be useful, but WITHOUT
** This program is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
**------------------------------------------------------------------------------
**------------------------------------------------------------------------------
**
**
** Based on the paper "Efficient Clipping of Arbitary Polygons" by Gunther
** Based on the paper "Efficient Clipping of Arbitary Polygons" by Gunther
** Greiner (greiner at informatik dot uni-erlangen dot de) and Kai Hormann
** Greiner (greiner at informatik dot uni-erlangen dot de) and Kai Hormann
** (hormann at informatik dot tu-clausthal dot de), ACM Transactions on Graphics
** (hormann at informatik dot tu-clausthal dot de), ACM Transactions on Graphics
** 1998;17(2):71-83.
** 1998;17(2):71-83.
**
**
** Available at: www.in.tu-clausthal.de/~hormann/papers/clipping.pdf
** Available at: www.in.tu-clausthal.de/~hormann/papers/clipping.pdf
**
**
** Another useful site describing the algorithm and with some example
** Another useful site describing the algorithm and with some example
** C code by Ionel Daniel Stroe is at:
** C code by Ionel Daniel Stroe is at:
**
**
** http://davis.wpi.edu/~matt/courses/clipping/
** http://davis.wpi.edu/~matt/courses/clipping/
**
**
** The algorithm is extended by Brenor Brophy to allow polygons with
** The algorithm is extended by Brenor Brophy to allow polygons with
** arcs between vertices.
** arcs between vertices.
**
**
** Rev History
** Rev History
** -----------------------------------------------------------------------------
** -----------------------------------------------------------------------------
** 1.0 08/25/2005 Initial Release
** 1.0 08/25/2005 Initial Release
** 1.1 09/04/2005 Added software license language to header comments
** 1.1 09/04/2005 Added software license language to header comments
*/
*/
//#include "stdafx.h"
//#include "stdafx.h"
#include <math.h>
#include <math.h>
#include "php_polygon_vertex.h"
#include "php_polygon_vertex.h"
segment
::
segment
(
double
xc
,
double
yc
,
int
d
)
segment
::
segment
(
double
xc
,
double
yc
,
int
d
)
{
{
m_xc
=
xc
;
m_xc
=
xc
;
m_yc
=
yc
;
m_yc
=
yc
;
m_d
=
d
;
m_d
=
d
;
}
}
vertex
::
vertex
(
double
x
,
double
y
,
vertex
::
vertex
(
double
x
,
double
y
,
double
xc
,
double
yc
,
double
d
,
double
xc
,
double
yc
,
double
d
,
vertex
*
nextV
,
vertex
*
prevV
,
vertex
*
nextV
,
vertex
*
prevV
,
polygon
*
nextPoly
,
polygon
*
nextPoly
,
BOOL
intersect
,
BOOL
intersect
,
vertex
*
neighbor
,
vertex
*
neighbor
,
double
alpha
,
double
alpha
,
BOOL
entry
,
BOOL
entry
,
BOOL
checked
)
BOOL
checked
)
{
{
m_x
=
x
;
m_x
=
x
;
m_y
=
y
;
m_y
=
y
;
m_nextV
=
nextV
;
m_nextV
=
nextV
;
m_prevV
=
prevV
;
m_prevV
=
prevV
;
m_nextPoly
=
nextPoly
;
m_nextPoly
=
nextPoly
;
m_intersect
=
intersect
;
m_intersect
=
intersect
;
m_neighbor
=
neighbor
;
m_neighbor
=
neighbor
;
m_alpha
=
alpha
;
m_alpha
=
alpha
;
m_entry
=
entry
;
m_entry
=
entry
;
m_checked
=
checked
;
m_checked
=
checked
;
m_id
=
0
;
m_id
=
0
;
m_nSeg
=
new
segment
(
xc
,
yc
,
d
);
m_nSeg
=
new
segment
(
xc
,
yc
,
d
);
m_pSeg
=
NULL
;
m_pSeg
=
NULL
;
}
}
vertex
::~
vertex
()
vertex
::~
vertex
()
{
{
if
(
m_nSeg
)
if
(
m_nSeg
)
delete
m_nSeg
;
delete
m_nSeg
;
}
}
double
vertex
::
Xc
(
BOOL
g
)
double
vertex
::
Xc
(
BOOL
g
)
{
{
if
(
isIntersect
()
)
if
(
isIntersect
()
)
{
{
if
(
m_neighbor
->
isEntry
()
)
if
(
m_neighbor
->
isEntry
()
)
return
m_neighbor
->
m_nSeg
->
Xc
();
return
m_neighbor
->
m_nSeg
->
Xc
();
else
else
return
m_neighbor
->
m_pSeg
->
Xc
();
return
m_neighbor
->
m_pSeg
->
Xc
();
}
}
else
else
if
(
g
)
if
(
g
)
return
m_nSeg
->
Xc
();
return
m_nSeg
->
Xc
();
else
else
return
m_pSeg
->
Xc
();
return
m_pSeg
->
Xc
();
}
}
double
vertex
::
Yc
(
BOOL
g
)
double
vertex
::
Yc
(
BOOL
g
)
{
{
if
(
isIntersect
()
)
if
(
isIntersect
()
)
{
{
if
(
m_neighbor
->
isEntry
()
)
if
(
m_neighbor
->
isEntry
()
)
return
m_neighbor
->
m_nSeg
->
Yc
();
return
m_neighbor
->
m_nSeg
->
Yc
();
else
else
return
m_neighbor
->
m_pSeg
->
Yc
();
return
m_neighbor
->
m_pSeg
->
Yc
();
}
}
else
else
if
(
g
)
if
(
g
)
return
m_nSeg
->
Yc
();
return
m_nSeg
->
Yc
();
else
else
return
m_pSeg
->
Yc
();
return
m_pSeg
->
Yc
();
}
}
double
vertex
::
d
(
BOOL
g
)
double
vertex
::
d
(
BOOL
g
)
{
{
if
(
isIntersect
()
)
if
(
isIntersect
()
)
{
{
if
(
m_neighbor
->
isEntry
()
)
if
(
m_neighbor
->
isEntry
()
)
return
m_neighbor
->
m_nSeg
->
d
();
return
m_neighbor
->
m_nSeg
->
d
();
else
else
return
(
-
1
*
m_neighbor
->
m_pSeg
->
d
());
return
(
-
1
*
m_neighbor
->
m_pSeg
->
d
());
}
}
else
else
if
(
g
)
if
(
g
)
return
m_nSeg
->
d
();
return
m_nSeg
->
d
();
else
else
return
(
-
1
*
m_pSeg
->
d
());
return
(
-
1
*
m_pSeg
->
d
());
}
}
void
vertex
::
setChecked
(
BOOL
check
)
void
vertex
::
setChecked
(
BOOL
check
)
{
{
m_checked
=
check
;
m_checked
=
check
;
if
(
m_neighbor
)
if
(
m_neighbor
)
if
(
!
m_neighbor
->
isChecked
()
)
if
(
!
m_neighbor
->
isChecked
()
)
m_neighbor
->
setChecked
();
m_neighbor
->
setChecked
();
}
}
polygon/php_polygon_vertex.h
View file @
4ce4631d
// file php_polygon_vertex.h
// file php_polygon_vertex.h
// See comments in file php_polygon_vertex.cpp
// See comments in file php_polygon_vertex.cpp
#ifndef PHP_POLYGON_VERTEX_H
#ifndef PHP_POLYGON_VERTEX_H
#define PHP_POLYGON_VERTEX_H
#define PHP_POLYGON_VERTEX_H
#include "defs-macros.h"
#include "defs-macros.h"
class
vertex
;
class
vertex
;
class
polygon
;
class
polygon
;
class
segment
class
segment
{
{
public
:
public
:
segment
(
double
xc
=
0
.
0
,
double
yc
=
0
.
0
,
int
d
=
0
);
segment
(
double
xc
=
0
.
0
,
double
yc
=
0
.
0
,
int
d
=
0
);
double
Xc
(){
return
m_xc
;
};
double
Xc
(){
return
m_xc
;
};
double
Yc
(){
return
m_yc
;
};
double
Yc
(){
return
m_yc
;
};
int
d
(){
return
m_d
;
};
int
d
(){
return
m_d
;
};
void
setXc
(
double
xc
){
m_xc
=
xc
;
};
void
setXc
(
double
xc
){
m_xc
=
xc
;
};
void
setYc
(
double
yc
){
m_yc
=
yc
;
};
void
setYc
(
double
yc
){
m_yc
=
yc
;
};
double
m_xc
,
m_yc
;
// center of arc
double
m_xc
,
m_yc
;
// center of arc
int
m_d
;
// direction (-1=CW, 0=LINE, 1=CCW)
int
m_d
;
// direction (-1=CW, 0=LINE, 1=CCW)
};
};
class
vertex
class
vertex
{
{
public
:
public
:
vertex
(
double
x
,
double
y
,
vertex
(
double
x
,
double
y
,
double
xc
=
0
.
0
,
double
yc
=
0
.
0
,
double
d
=
0
.
0
,
double
xc
=
0
.
0
,
double
yc
=
0
.
0
,
double
d
=
0
.
0
,
vertex
*
nextV
=
NULL
,
vertex
*
prevV
=
NULL
,
vertex
*
nextV
=
NULL
,
vertex
*
prevV
=
NULL
,
polygon
*
nextPoly
=
NULL
,
polygon
*
nextPoly
=
NULL
,
BOOL
intersect
=
FALSE
,
BOOL
intersect
=
FALSE
,
vertex
*
neighbor
=
NULL
,
vertex
*
neighbor
=
NULL
,
double
alpha
=
0
.
0
,
double
alpha
=
0
.
0
,
BOOL
entry
=
TRUE
,
BOOL
entry
=
TRUE
,
BOOL
checked
=
FALSE
);
BOOL
checked
=
FALSE
);
~
vertex
();
~
vertex
();
int
id
()
{
return
m_id
;
};
int
id
()
{
return
m_id
;
};
double
X
()
{
return
m_x
;
};
double
X
()
{
return
m_x
;
};
void
setX
(
double
x
)
{
m_x
=
x
;
};
void
setX
(
double
x
)
{
m_x
=
x
;
};
double
Y
()
{
return
m_y
;
};
double
Y
()
{
return
m_y
;
};
void
setY
(
double
y
)
{
m_y
=
y
;
};
void
setY
(
double
y
)
{
m_y
=
y
;
};
double
Xc
(
BOOL
g
=
TRUE
);
double
Xc
(
BOOL
g
=
TRUE
);
double
Yc
(
BOOL
g
=
TRUE
);
double
Yc
(
BOOL
g
=
TRUE
);
double
d
(
BOOL
g
=
TRUE
);
double
d
(
BOOL
g
=
TRUE
);
void
setXc
(
double
xc
)
{
m_nSeg
->
setXc
(
xc
);
};
void
setXc
(
double
xc
)
{
m_nSeg
->
setXc
(
xc
);
};
void
setYc
(
double
yc
)
{
m_nSeg
->
setYc
(
yc
);
};
void
setYc
(
double
yc
)
{
m_nSeg
->
setYc
(
yc
);
};
void
setNext
(
vertex
*
nextV
){
m_nextV
=
nextV
;
};
void
setNext
(
vertex
*
nextV
){
m_nextV
=
nextV
;
};
vertex
*
Next
(){
return
m_nextV
;
};
vertex
*
Next
(){
return
m_nextV
;
};
void
setPrev
(
vertex
*
prevV
){
m_prevV
=
prevV
;
};
void
setPrev
(
vertex
*
prevV
){
m_prevV
=
prevV
;
};
vertex
*
Prev
(){
return
m_prevV
;
};
vertex
*
Prev
(){
return
m_prevV
;
};
void
setNseg
(
segment
*
nSeg
){
m_nSeg
=
nSeg
;
};
void
setNseg
(
segment
*
nSeg
){
m_nSeg
=
nSeg
;
};
segment
*
Nseg
(){
return
m_nSeg
;
};
segment
*
Nseg
(){
return
m_nSeg
;
};
void
setPseg
(
segment
*
pSeg
){
m_pSeg
=
pSeg
;
};
void
setPseg
(
segment
*
pSeg
){
m_pSeg
=
pSeg
;
};
segment
*
Pseg
(){
return
m_pSeg
;
};
segment
*
Pseg
(){
return
m_pSeg
;
};
void
setNextPoly
(
polygon
*
nextPoly
){
m_nextPoly
=
nextPoly
;
};
void
setNextPoly
(
polygon
*
nextPoly
){
m_nextPoly
=
nextPoly
;
};
polygon
*
NextPoly
(){
return
m_nextPoly
;
};
polygon
*
NextPoly
(){
return
m_nextPoly
;
};
void
setNeighbor
(
vertex
*
neighbor
){
m_neighbor
=
neighbor
;
};
void
setNeighbor
(
vertex
*
neighbor
){
m_neighbor
=
neighbor
;
};
vertex
*
Neighbor
(){
return
m_neighbor
;
};
vertex
*
Neighbor
(){
return
m_neighbor
;
};
double
Alpha
(){
return
m_alpha
;
};
double
Alpha
(){
return
m_alpha
;
};
BOOL
isIntersect
(){
return
m_intersect
;
};
BOOL
isIntersect
(){
return
m_intersect
;
};
void
setChecked
(
BOOL
check
=
TRUE
);
void
setChecked
(
BOOL
check
=
TRUE
);
BOOL
isChecked
()
{
return
m_checked
;
};
BOOL
isChecked
()
{
return
m_checked
;
};
void
setEntry
(
BOOL
entry
=
TRUE
){
m_entry
=
entry
;
}
void
setEntry
(
BOOL
entry
=
TRUE
){
m_entry
=
entry
;
}
BOOL
isEntry
(){
return
m_entry
;
};
BOOL
isEntry
(){
return
m_entry
;
};
double
m_x
,
m_y
;
// coords
double
m_x
,
m_y
;
// coords
vertex
*
m_nextV
;
// links to next and prev vertices
vertex
*
m_nextV
;
// links to next and prev vertices
vertex
*
m_prevV
;
// links to next and prev vertices
vertex
*
m_prevV
;
// links to next and prev vertices
segment
*
m_nSeg
,
*
m_pSeg
;
// links to next and prev segments
segment
*
m_nSeg
,
*
m_pSeg
;
// links to next and prev segments
polygon
*
m_nextPoly
;
polygon
*
m_nextPoly
;
BOOL
m_intersect
;
BOOL
m_intersect
;
vertex
*
m_neighbor
;
vertex
*
m_neighbor
;
double
m_alpha
;
double
m_alpha
;
BOOL
m_entry
;
BOOL
m_entry
;
BOOL
m_checked
;
BOOL
m_checked
;
int
m_id
;
int
m_id
;
};
};
#endif // ifndef PHP_POLYGON_VERTEX_H
#endif // ifndef PHP_POLYGON_VERTEX_H
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