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
b7db0ef8
Commit
b7db0ef8
authored
Oct 12, 2008
by
charras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
updating polygon lib code. A bug removed.
parent
7c5feb61
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
461 additions
and
117 deletions
+461
-117
zones_test_and_combine_areas.cpp
pcbnew/zones_test_and_combine_areas.cpp
+2
-14
PolyLine.cpp
polygon/PolyLine.cpp
+83
-100
PolyLine.h
polygon/PolyLine.h
+2
-2
math_for_graphics.cpp
polygon/math_for_graphics.cpp
+0
-1
polygon_test_point_inside.cpp
polygon/polygon_test_point_inside.cpp
+355
-0
polygon_test_point_inside.h
polygon/polygon_test_point_inside.h
+19
-0
No files found.
pcbnew/zones_test_and_combine_areas.cpp
View file @
b7db0ef8
...
...
@@ -169,16 +169,8 @@ int BOARD::TestAreaPolygon( ZONE_CONTAINER* CurrArea )
int
y2i
=
p
->
GetY
(
is2
);
int
x2f
=
p
->
GetX
(
is2_next
);
int
y2f
=
p
->
GetY
(
is2_next
);
int
ret
=
FindSegmentIntersections
(
x1i
,
y1i
,
x1f
,
y1f
,
style
,
x2i
,
y2i
,
x2f
,
y2f
,
style2
);
int
ret
=
FindSegmentIntersections
(
x1i
,
y1i
,
x1f
,
y1f
,
style
,
x2i
,
y2i
,
x2f
,
y2f
,
style2
);
if
(
ret
)
{
// intersection between non-adjacent sides
...
...
@@ -246,8 +238,6 @@ int BOARD::ClipAreaPolygon( ZONE_CONTAINER* CurrArea,
str
+=
wxT
(
"such as adding cutouts. It can't be fixed automatically.
\n
"
);
str
+=
wxT
(
"Manual correction is recommended."
);
wxMessageBox
(
str
);
// bDontShowSelfIntersectionArcsWarning = dlg.bDontShowBoxState;
}
return
-
1
;
// arcs intersect with other sides, error
}
...
...
@@ -427,8 +417,6 @@ int BOARD::CombineAllAreasInNet( int aNetCode, bool bMessageBox, bool bUseUtilit
curr_area
->
m_Netname
.
GetData
()
);
str
+=
wxT
(
"Therefore, these areas can't be combined."
);
wxMessageBox
(
str
);
// bDontShowIntersectionArcsWarning = dlg.bDontShowBoxState;
}
}
}
...
...
polygon/PolyLine.cpp
View file @
b7db0ef8
...
...
@@ -30,10 +30,11 @@ CPolyLine::CPolyLine()
CPolyLine
::~
CPolyLine
()
{
Undraw
();
if
(
m_Kbool_Poly_Engine
)
if
(
m_Kbool_Poly_Engine
)
delete
m_Kbool_Poly_Engine
;
}
/** Function NormalizeWithKbool
* Use the Kbool Library to clip contours: if outlines are crossing, the self-crossing polygon
* is converted to non self-crossing polygon by adding extra points at the crossing locations
...
...
@@ -83,8 +84,8 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
hole_array
.
push_back
(
hole
);
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
// store hole
{
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
hole
->
push_back
(
x
);
hole
->
push_back
(
y
);
}
...
...
@@ -99,8 +100,8 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
bool
first
=
true
;
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
{
// foreach point in the polygon
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
if
(
first
)
{
first
=
false
;
...
...
@@ -116,13 +117,13 @@ int CPolyLine::NormalizeWithKbool( std::vector<CPolyLine*> * aExtraPolyList, boo
}
else
if
(
aExtraPolyList
)
// a new outside contour is found: create a new CPolyLine
{
polyline
=
new
CPolyLine
;
// create new poly
polyline
=
new
CPolyLine
;
// create new poly
aExtraPolyList
->
push_back
(
polyline
);
// put it in array
bool
first
=
true
;
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
// read next external contour
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
// read next external contour
{
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
if
(
first
)
{
first
=
false
;
...
...
@@ -227,8 +228,8 @@ int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng,
{
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
{
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
aBooleng
->
AddPoint
(
x
,
y
);
count
++
;
}
...
...
@@ -259,7 +260,7 @@ int CPolyLine::AddPolygonsToBoolEng( Bool_Engine* aBooleng,
* @return error: 0 if Ok, 1 if error
*/
int
CPolyLine
::
MakeKboolPoly
(
int
aStart_contour
,
int
aEnd_contour
,
std
::
vector
<
CArc
>
*
arc_array
,
bool
aConvertHoles
)
bool
aConvertHoles
)
{
if
(
m_Kbool_Poly_Engine
)
{
...
...
@@ -300,8 +301,8 @@ int CPolyLine::MakeKboolPoly( int aStart_contour, int aEnd_contour, std::vector<
{
while
(
m_Kbool_Poly_Engine
->
PolygonHasMorePoints
()
)
{
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
int
x
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonXPoint
();
int
y
=
(
int
)
m_Kbool_Poly_Engine
->
GetPolygonYPoint
();
booleng
->
AddPoint
(
x
,
y
);
}
...
...
@@ -563,12 +564,12 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles )
}
int
CPolyLine
::
NormalizeAreaOutlines
(
std
::
vector
<
CPolyLine
*>
*
pa
,
bool
bRetainArcs
)
{
return
NormalizeWithKbool
(
pa
,
bRetainArcs
);
}
// Restore arcs to a polygon where they were replaced with steps
// If pa != NULL, also use polygons in pa array
//
...
...
@@ -1215,20 +1216,20 @@ void CPolyLine::Hatch()
if
(
corner
[
ic
].
end_contour
||
(
ic
==
(
int
)
(
corner
.
size
()
-
1
)
)
)
{
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
corner
[
i_start_contour
].
x
,
corner
[
i_start_contour
].
y
,
side_style
[
ic
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
ic
].
x
,
corner
[
ic
].
y
,
corner
[
i_start_contour
].
x
,
corner
[
i_start_contour
].
y
,
side_style
[
ic
],
&
x
,
&
y
,
&
x2
,
&
y2
);
i_start_contour
=
ic
+
1
;
}
else
{
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
corner
[
ic
+
1
].
x
,
corner
[
ic
+
1
].
y
,
side_style
[
ic
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
ic
].
x
,
corner
[
ic
].
y
,
corner
[
ic
+
1
].
x
,
corner
[
ic
+
1
].
y
,
side_style
[
ic
],
&
x
,
&
y
,
&
x2
,
&
y2
);
}
if
(
ok
)
{
...
...
@@ -1302,7 +1303,7 @@ void CPolyLine::Hatch()
double
y2
=
yy
[
ip
+
1
]
-
dx
*
slope
;
m_HatchLines
.
push_back
(
CSegment
(
xx
[
ip
],
yy
[
ip
],
to_int
(
x1
),
to_int
(
y1
)
)
);
m_HatchLines
.
push_back
(
CSegment
(
xx
[
ip
+
1
],
yy
[
ip
+
1
],
to_int
(
x2
),
to_int
(
y2
)
)
);
to_int
(
y2
)
)
);
}
}
}
...
...
@@ -1314,27 +1315,26 @@ void CPolyLine::Hatch()
// test to see if a point is inside polyline
//
bool
CPolyLine
::
TestPointInside
(
int
x
,
int
y
)
bool
CPolyLine
::
TestPointInside
(
int
px
,
int
p
y
)
{
enum
{
MAXPTS
=
100
};
if
(
!
GetClosed
()
)
wxASSERT
(
0
);
// define line passing through (x,y), with slope = 2/3;
// get intersection points
double
xx
[
MAXPTS
],
yy
[
MAXPTS
]
;
int
xx
,
yy
;
double
slope
=
(
double
)
2.0
/
3.0
;
double
a
=
y
-
slope
*
x
;
double
a
=
py
-
slope
*
p
x
;
int
nloops
=
0
;
int
npts
;
bool
inside
=
false
;
// make this a loop so if my homebrew algorithm screws up, we try it again
do
{
// now find all intersection points of line with polyline sides
npts
=
0
;
npts
=
0
;
inside
=
false
;
for
(
int
icont
=
0
;
icont
<
GetNumContours
();
icont
++
)
{
int
istart
=
GetContourStart
(
icont
);
...
...
@@ -1345,29 +1345,35 @@ bool CPolyLine::TestPointInside( int x, int y )
int
ok
;
if
(
ic
==
istart
)
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
iend
].
x
,
corner
[
iend
].
y
,
corner
[
istart
].
x
,
corner
[
istart
].
y
,
side_style
[
corner
.
size
()
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
iend
].
x
,
corner
[
iend
].
y
,
corner
[
istart
].
x
,
corner
[
istart
].
y
,
side_style
[
iend
],
&
x
,
&
y
,
&
x2
,
&
y2
);
else
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
ic
-
1
].
x
,
corner
[
ic
-
1
].
y
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
side_style
[
ic
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
ic
-
1
].
x
,
corner
[
ic
-
1
].
y
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
side_style
[
ic
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
if
(
ok
)
{
xx
[
npts
]
=
(
int
)
x
;
yy
[
npts
]
=
(
int
)
y
;
xx
=
(
int
)
x
;
yy
=
(
int
)
y
;
if
(
xx
==
px
&&
yy
==
py
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
>
px
)
inside
=
not
inside
;
npts
++
;
wxASSERT
(
npts
<
MAXPTS
);
// overflow
}
if
(
ok
==
2
)
{
xx
[
npts
]
=
(
int
)
x2
;
yy
[
npts
]
=
(
int
)
y2
;
xx
=
(
int
)
x2
;
yy
=
(
int
)
y2
;
if
(
xx
==
px
&&
yy
==
py
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
>
px
)
inside
=
not
inside
;
npts
++
;
wxASSERT
(
npts
<
MAXPTS
);
// overflow
}
}
}
...
...
@@ -1378,49 +1384,34 @@ bool CPolyLine::TestPointInside( int x, int y )
wxASSERT
(
npts
%
2
==
0
);
// odd number of intersection points, error
// count intersection points to right of (x,y), if odd (x,y) is inside polyline
int
ncount
=
0
;
for
(
int
ip
=
0
;
ip
<
npts
;
ip
++
)
{
if
(
xx
[
ip
]
==
x
&&
yy
[
ip
]
==
y
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
[
ip
]
>
x
)
ncount
++
;
}
if
(
ncount
%
2
)
return
TRUE
;
else
return
FALSE
;
return
inside
;
}
// test to see if a point is inside polyline contour
//
bool
CPolyLine
::
TestPointInsideContour
(
int
icont
,
int
x
,
int
y
)
bool
CPolyLine
::
TestPointInsideContour
(
int
icont
,
int
px
,
int
p
y
)
{
if
(
icont
>=
GetNumContours
()
)
return
FALSE
;
enum
{
MAXPTS
=
100
};
if
(
!
GetClosed
()
)
wxASSERT
(
0
);
// define line passing through (x,y), with slope = 2/3;
// get intersection points
double
xx
[
MAXPTS
],
yy
[
MAXPTS
]
;
// define line passing through (x,y), with slope = 2/3;
// get intersection points
int
xx
,
yy
;
double
slope
=
(
double
)
2.0
/
3.0
;
double
a
=
y
-
slope
*
x
;
double
a
=
py
-
slope
*
p
x
;
int
nloops
=
0
;
int
npts
;
bool
inside
=
false
;
// make this a loop so if my homebrew algorithm screws up, we try it again
// make this a loop so if my homebrew algorithm screws up, we try it again
do
{
// now find all intersection points of line with polyline sides
npts
=
0
;
npts
=
0
;
inside
=
false
;
int
istart
=
GetContourStart
(
icont
);
int
iend
=
GetContourEnd
(
icont
);
for
(
int
ic
=
istart
;
ic
<=
iend
;
ic
++
)
...
...
@@ -1429,29 +1420,35 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
int
ok
;
if
(
ic
==
istart
)
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
iend
].
x
,
corner
[
iend
].
y
,
corner
[
istart
].
x
,
corner
[
istart
].
y
,
side_style
[
corner
.
size
()
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
iend
].
x
,
corner
[
iend
].
y
,
corner
[
istart
].
x
,
corner
[
istart
].
y
,
side_style
[
iend
],
&
x
,
&
y
,
&
x2
,
&
y2
);
else
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
corner
[
ic
-
1
].
x
,
corner
[
ic
-
1
].
y
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
side_style
[
ic
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
corner
[
ic
-
1
].
x
,
corner
[
ic
-
1
].
y
,
corner
[
ic
].
x
,
corner
[
ic
].
y
,
side_style
[
ic
-
1
],
&
x
,
&
y
,
&
x2
,
&
y2
);
if
(
ok
)
{
xx
[
npts
]
=
(
int
)
x
;
yy
[
npts
]
=
(
int
)
y
;
xx
=
(
int
)
x
;
yy
=
(
int
)
y
;
npts
++
;
wxASSERT
(
npts
<
MAXPTS
);
// overflow
if
(
xx
==
px
&&
yy
==
py
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
>
px
)
inside
=
not
inside
;
}
if
(
ok
==
2
)
{
xx
[
npts
]
=
(
int
)
x2
;
yy
[
npts
]
=
(
int
)
y2
;
xx
=
(
int
)
x2
;
yy
=
(
int
)
y2
;
npts
++
;
wxASSERT
(
npts
<
MAXPTS
);
// overflow
if
(
xx
==
px
&&
yy
==
py
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
>
px
)
inside
=
not
inside
;
}
}
...
...
@@ -1461,20 +1458,7 @@ bool CPolyLine::TestPointInsideContour( int icont, int x, int y )
wxASSERT
(
npts
%
2
==
0
);
// odd number of intersection points, error
// count intersection points to right of (x,y), if odd (x,y) is inside polyline
int
ncount
=
0
;
for
(
int
ip
=
0
;
ip
<
npts
;
ip
++
)
{
if
(
xx
[
ip
]
==
x
&&
yy
[
ip
]
==
y
)
return
FALSE
;
// (x,y) is on a side, call it outside
else
if
(
xx
[
ip
]
>
x
)
ncount
++
;
}
if
(
ncount
%
2
)
return
TRUE
;
else
return
FALSE
;
return
inside
;
}
...
...
@@ -1545,7 +1529,6 @@ void CPolyLine::SetEndContour( int ic, bool end_contour )
}
void
CPolyLine
::
AppendArc
(
int
xi
,
int
yi
,
int
xf
,
int
yf
,
int
xc
,
int
yc
,
int
num
)
{
// get radius
...
...
polygon/PolyLine.h
View file @
b7db0ef8
...
...
@@ -47,10 +47,10 @@ void ArmBoolEng( Bool_Engine* aBooleng, bool aConvertHoles = false );
#define to_int( x ) (int) round( (x) )
#ifndef min
#define min( x1, x2 ) ( (x1) > (x2)
) ? (x2) : (x1
)
#define min( x1, x2 ) ( (x1) > (x2)
? (x2) : (x1)
)
#endif
#ifndef max
#define max( x1, x2 ) ( (x1) > (x2)
) ? (x1) : (x2
)
#define max( x1, x2 ) ( (x1) > (x2)
? (x1) : (x2)
)
#endif
class
CRect
...
...
polygon/math_for_graphics.cpp
View file @
b7db0ef8
...
...
@@ -639,7 +639,6 @@ bool TestForIntersectionOfStraightLineSegments( int x1i, int y1i, int x1f, int y
int
*
x
,
int
*
y
,
double
*
d
)
{
double
a
,
b
,
dist
;
// first, test for intersection
if
(
x1i
==
x1f
&&
x2i
==
x2f
)
{
...
...
polygon/polygon_test_point_inside.cpp
0 → 100644
View file @
b7db0ef8
/////////////////////////////////////////////////////////////////////////////
// Name: polygon_test_point_inside.cpp
/////////////////////////////////////////////////////////////////////////////
#include <math.h>
#include <vector>
#include "PolyLine.h"
using
namespace
std
;
/* this algo uses the the Jordan curve theorem to find if a point is inside or outside a polygon:
* It run a semi-infinite line horizontally (increasing x, fixed y)
* out from the test point, and count how many edges it crosses.
* At each crossing, the ray switches between inside and outside.
* If odd nimber, the test point is inside the polygon
* This is called the Jordan curve theorem, or sometimes referred to as the "even-odd" test.
*/
/* 2 versions are given.
* the second version is GPL (currently used)
* the first version is for explanations and tests (used to test the second version)
* both use the same algorithm.
*/
#if 0
/* This text and the algorithm come from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
*
* PNPOLY - Point Inclusion in Polygon Test
* W. Randolph Franklin (WRF)
*
* Table of Contents
*
* 1. The C Code <#The C Code>
* 2. The Method <#The Method>
* 3. Originality <#Originality>
* 4. The Inequality Tests are Tricky <#The Inequality Tests are Tricky>
* 5. C Semantics <#C Semantics>
* 6. Point on a (Boundary) Edge <#Point on an Edge>
* 7. Multiple Components and Holes <#Listing the Vertices>
* 8. Testing Which One of Many Polygons Contains the Point <#Testing a
* Point Against Many Polygons>
* 9. Explanation of /"for (i = 0, j = nvert-1; i < nvert; j = i++)"/
* <#Explanation>
* 10. Fortran Code for the Point in Polygon Test <#Fortran Code for the
* Point in Polygon Test>
* 11. Converting the Code to All Integers <#Converting the Code to All
* Integers>
* 12. License to Use <#License to Use>
*
* The C Code
*
* Here is the code, for reference. Excluding lines with only braces, there
* are only /7 lines/ of code.
*
* int pnpoly(int nvert, float *vertx, float *verty, float ref_pointX, float ref_pointY)
* {
* int i, j, c = 0;
* for (i = 0, j = nvert-1; i < nvert; j = i++) {
* if ( ((verty[i]>ref_pointY) != (verty[j]>ref_pointY)) &&
* (ref_pointX < (vertx[j]-vertx[i]) * (ref_pointY-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
* c = !c;
* }
* return c;
* }
*
* Argument Meaning
* nvert Number of vertices in the polygon. Whether to repeat the first
* vertex at the end is discussed below.
* vertx, verty Arrays containing the x- and y-coordinates of the
* polygon's vertices.
* ref_pointX, ref_pointY X- and y-coordinate of the test point.
*
*
* The Method
*
* I run a semi-infinite ray horizontally (increasing x, fixed y) out from
* the test point, and count how many edges it crosses. At each crossing,
* the ray switches between inside and outside. This is called the /Jordan
* curve theorem/.
*
* The case of the ray going thru a vertex is handled correctly via a
* careful selection of inequalities. Don't mess with this code unless
* you're familiar with the idea of /Simulation of Simplicity/. This
* pretends to shift the ray infinitesimally to one side so that it either
* clearly intersects, or clearly doesn't touch. Since this is merely a
* conceptual, infinitesimal, shift, it never creates an intersection that
* didn't exist before, and never destroys an intersection that clearly
* existed before.
*
* The ray is tested against each edge thus:
*
* 1. Is the point in the half-plane below the extended edge? and
* 2. Is the point's X coordinate within the edge's X-range?
*
* Handling endpoints here is tricky.
*
*
* Originality
*
* I make no claim to having invented the idea. However in 1970, I did
* produce the Fortran code given below on my own, and include it in a
* package of cartographic SW publicly-distributed by David Douglas, Dept
* of Geography, Simon Fraser U and U of Ottawa.
*
* Earlier implementations of point-in-polygon testing presumably exist,
* tho the code might never have been released. Pointers to prior art,
* especially publicly available code, are welcome. One early publication,
* which doesn't handle the point on an edge, and has a typo, is this:
*
* M Shimrat, "Algorithm 112, Position of Point Relative to Polygon",
* /Comm. ACM/ 5(8), Aug 1962, p 434.
*
* A well-written recent summary is this:
*
* E Haines, /Point in Polygon Strategies/,
* http://www.acm.org/pubs/tog/editors/erich/ptinpoly/, 1994.
*
*
* The Inequality Tests are Tricky
*
* If translating the program to another language, be sure to get the
* inequalities in the conditional correct. They were carefully chosen to
* make the program work correctly when the point is vertically below a vertex.
*
* Several people have thought that my program was wrong, when really
* /they/ had gotten the inequalities wrong.
*
*
* C Semantics
*
* My code uses the fact that, in the C language, when executing the code
|a&&b|, if |a| is false, then |b| must not be evaluated. If your
* compiler doesn't do this, then it's not implementing C, and you will get
* a divide-by-zero, i.a., when the test point is vertically in line with a
* vertical edge. When translating this code to another language with
* different semantics, then you must implement this test explicitly.
*
*
* Point on a (Boundary) Edge
*
* PNPOLY partitions the plane into points inside the polygon and points
* outside the polygon. Points that are on the boundary are classified as
* either inside or outside.
*
* 1.
*
* Any particular point is always classified consistently the same
* way. In the following figure, consider what PNPOLY would say when
* the red point, /P/, is tested against the two triangles, /T_L /
* and /T_R /. Depending on internal roundoff errors, PNPOLY may say
* that /P/ is in /T_L / or in /T_R /. However it will always give
* the same answer when /P/ is tested against those triangles. That
* is, if PNPOLY finds that /P/ is in /T_L /, then it will find that
* /P/ is not /T_R /. If PNPOLY finds that /P/ is not in /T_L /, then
* it will find that /P/ is in /T_R /.
*
* 2. If you want to know when a point is exactly on the boundary, you
* need another program. This is only one of many functions that
* PNPOLY lacks; it also doesn't predict tomorrow's weather. You are
* free to extend PNPOLY's source code.
*
* 3. The first reason for this is the numerical analysis position that
* you should not be testing exact equality unless your input is
* exact. Even then, computational roundoff error would often make
* the result wrong.
*
* 4. The second reason is that, if you partition a region of the plane
* into polygons, i.e., form a planar graph, then PNPOLY will locate
* each point into exactly one polygon. In other words, PNPOLY
* considers each polygon to be topologically a semi-open set. This
* makes things simpler, i.e., causes fewer special cases, if you use
* PNPOLY as part of a larger system. Examples of this include
* locating a point in a planar graph, and intersecting two planar
* graphs.
*
*
* Explanation of /"for (i = 0, j = nvert-1; i < nvert; j = i++)"/
*
* The intention is to execute the loop for each i from 0 to nvert-1. For
* each iteration, j is i-1. However that wraps, so if i=0 then j=nvert-1.
* Therefore the current edge runs between verts j and i, and the loop is
* done once per edge. In detail:
*
* 1. Start by setting i and j:
* i = 0
* j = nvert-1
* 2. If i<nvert is false then exit the loop.
* 3. Do the loop body.
* 4. Set j=i and then
* add 1 to i and then
* 5. Go back to step 2.
*
*
*
* Converting the Code to All Integers
*
* If you want to convert the code from floats to integers, consider these
* issues.
*
* 1. On many current processors floats are at least as fast as ints.
* 2. If you move the denominator over to the other side of the
* inequality, remember that, when the denominator is negative, the
* inequality will flip.
* 3. If coordinates are large enough, the multiplication will silently
* overflow.
*
*
* License to Use
* Copyright (c) 1970-2003, Wm. Randolph Franklin
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimers.
* 2. Redistributions in binary form must reproduce the above copyright
* notice in the documentation and/or other materials provided with
* the distribution.
* 3. The name of W. Randolph Franklin may not be used to endorse or
* promote products derived from this Software without specific prior
* written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
* Copyright © 1994-2006, W Randolph Franklin (WRF)
* <http://wrfranklin.org/> You may use my material for non-profit research
* and education, provided that you credit me, and link back to my home page.
* http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html,
* 05/20/2008 20:36:42
*/
bool TestPointInsidePolygon( std::vector <CPolyPt> aPolysList,
int istart,
int iend,
int refx,
int refy )
/** Function TestPointInsidePolygon
* test if a point is inside or outside a polygon.
* @param aPolysList: the list of polygons
* @param istart: the starting point of a given polygon in m_FilledPolysList.
* @param iend: the ending point of the polygon in m_FilledPolysList.
* @param refx, refy: the point coordinate to test
* @return true if the point is inside, false for outside
*/
{
double ref_pointX = refx;
double ref_pointY = refy;
bool inside = false;
for( int ii = istart, jj = iend; ii <= iend; jj = ii++ )
{
double seg_startX, seg_startY; // starting point for the segment to test
seg_startX = aPolysList[ii].x;
seg_startY = aPolysList[ii].y;
double seg_endX, seg_endY; // ending point for the segment to test
seg_endX = aPolysList[jj].x;
seg_endY = aPolysList[jj].y;
if( ( ( seg_startY > ref_pointY ) != (seg_endY > ref_pointY ) )
&& (ref_pointX <
(seg_endX -
seg_startX) * (ref_pointY - seg_startY) / (seg_endY - seg_startY) + seg_startX) )
inside = not inside;
}
return inside;
}
#else
/* this algo come from freePCB.
*/
bool
TestPointInsidePolygon
(
std
::
vector
<
CPolyPt
>
aPolysList
,
int
istart
,
int
iend
,
int
refx
,
int
refy
)
/** Function TestPointInsidePolygon
* test if a point is inside or outside a polygon.
* if a point is on a outline segment, it is considered outside the polygon
* @param aPolysList: the list of polygons
* @param istart: the starting point of a given polygon in m_FilledPolysList.
* @param iend: the ending point of the polygon in m_FilledPolysList.
* @param refx,refy: the point coordinate to test
* @return true if the point is inside, false for outside
* this algorithm come from FreePCB.
*/
{
#define OUTSIDE_IF_ON_SIDE 0 // = 1 if we consider point on a side outside the polygon
// define line passing through (x,y), with slope = 0 (horizontal line)
// get intersection points
// count intersection points to right of (x,y), if odd (x,y) is inside polyline
int
xx
,
yy
;
double
slope
=
0
;
double
a
=
refy
-
slope
*
refx
;
int
ics
,
ice
;
bool
inside
=
false
;
// find all intersection points of line with polyline sides
for
(
ics
=
istart
,
ice
=
iend
;
ics
<=
iend
;
ice
=
ics
++
)
{
double
x
,
y
,
x2
,
y2
;
int
ok
=
FindLineSegmentIntersection
(
a
,
slope
,
aPolysList
[
ics
].
x
,
aPolysList
[
ics
].
y
,
aPolysList
[
ice
].
x
,
aPolysList
[
ice
].
y
,
0
,
&
x
,
&
y
,
&
x2
,
&
y2
);
if
(
ok
)
{
xx
=
(
int
)
x
;
yy
=
(
int
)
y
;
#if OUTSIDE_IF_ON_SIDE
if
(
xx
==
refx
&&
yy
==
refy
)
return
false
;
// (x,y) is on a side, call it outside
else
#endif
if
(
xx
>
refx
)
inside
=
not
inside
;
}
if
(
ok
==
2
)
{
xx
=
(
int
)
x2
;
yy
=
(
int
)
y2
;
#if OUTSIDE_IF_ON_SIDE
if
(
xx
==
refx
&&
yy
==
refy
)
return
false
;
// (x,y) is on a side, call it outside
else
#endif
if
(
xx
>
refx
)
inside
=
not
inside
;
}
}
return
inside
;
}
#endif
polygon/polygon_test_point_inside.h
0 → 100644
View file @
b7db0ef8
/////////////////////////////////////////////////////////////////////////////
// Name: polygon_test_point_inside.h
/////////////////////////////////////////////////////////////////////////////
using
namespace
std
;
/** Function TestPointInsidePolygon
* test if a point is inside or outside a polygon.
* @param aPolysList: the list of polygons
* @param istart: the starting point of a given polygon in m_FilledPolysList.
* @param iend: the ending point of the polygon in m_FilledPolysList.
* @param refx, refy: the point coordinate to test
* @return true if the point is inside, false for outside
*/
bool
TestPointInsidePolygon
(
std
::
vector
<
CPolyPt
>
aPolysList
,
int
istart
,
int
iend
,
int
refx
,
int
refy
);
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