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
6ac8188f
Commit
6ac8188f
authored
Sep 10, 2013
by
tomasz.wlostowski@cern.ch
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
common: minimum version of the shape library
parent
b0357ce9
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
2372 additions
and
0 deletions
+2372
-0
CMakeLists.txt
common/CMakeLists.txt
+4
-0
seg.cpp
common/geometry/seg.cpp
+150
-0
shape_collisions.cpp
common/geometry/shape_collisions.cpp
+210
-0
shape_line_chain.cpp
common/geometry/shape_line_chain.cpp
+465
-0
seg.h
include/geometry/seg.h
+361
-0
shape.h
include/geometry/shape.h
+141
-0
shape_circle.h
include/geometry/shape_circle.h
+78
-0
shape_index.h
include/geometry/shape_index.h
+290
-0
shape_line_chain.h
include/geometry/shape_line_chain.h
+531
-0
shape_rect.h
include/geometry/shape_rect.h
+142
-0
No files found.
common/CMakeLists.txt
View file @
6ac8188f
...
...
@@ -162,6 +162,10 @@ set(COMMON_SRCS
tool/tool_event.cpp
tool/tool_interactive.cpp
tool/context_menu.cpp
geometry/seg.cpp
geometry/shape_line_chain.cpp
geometry/shape_collisions.cpp
)
add_library
(
common STATIC
${
COMMON_SRCS
}
)
...
...
common/geometry/seg.cpp
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <geometry/seg.h>
template
<
typename
T
>
int
sgn
(
T
val
)
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
));
}
bool
SEG
::
PointCloserThan
(
const
VECTOR2I
&
aP
,
int
dist
)
const
{
VECTOR2I
d
=
b
-
a
;
ecoord
dist_sq
=
(
ecoord
)
dist
*
dist
;
SEG
::
ecoord
l_squared
=
d
.
Dot
(
d
);
SEG
::
ecoord
t
=
d
.
Dot
(
aP
-
a
);
if
(
t
<=
0
||
!
l_squared
)
return
(
aP
-
a
).
SquaredEuclideanNorm
()
<
dist_sq
;
else
if
(
t
>=
l_squared
)
return
(
aP
-
b
).
SquaredEuclideanNorm
()
<
dist_sq
;
int
dxdy
=
abs
(
d
.
x
)
-
abs
(
d
.
y
);
if
(
(
dxdy
>=
-
1
&&
dxdy
<=
1
)
||
abs
(
d
.
x
)
<=
1
||
abs
(
d
.
y
)
<=
1
)
{
int
ca
=
-
sgn
(
d
.
y
);
int
cb
=
sgn
(
d
.
x
);
int
cc
=
-
ca
*
a
.
x
-
cb
*
a
.
y
;
ecoord
num
=
ca
*
aP
.
x
+
cb
*
aP
.
y
+
cc
;
num
*=
num
;
if
(
ca
&&
cb
)
num
>>=
1
;
if
(
num
>
(
dist_sq
+
100
))
return
false
;
else
if
(
num
<
(
dist_sq
-
100
))
return
true
;
}
VECTOR2I
nearest
;
nearest
.
x
=
a
.
x
+
rescale
(
t
,
(
ecoord
)
d
.
x
,
l_squared
);
nearest
.
y
=
a
.
y
+
rescale
(
t
,
(
ecoord
)
d
.
y
,
l_squared
);
return
(
nearest
-
aP
).
SquaredEuclideanNorm
()
<=
dist_sq
;
}
SEG
::
ecoord
SEG
::
SquaredDistance
(
const
SEG
&
aSeg
)
const
{
// fixme: rather inefficient....
if
(
Intersect
(
aSeg
))
return
0
;
const
VECTOR2I
pts
[
4
]
=
{
aSeg
.
NearestPoint
(
a
)
-
a
,
aSeg
.
NearestPoint
(
b
)
-
b
,
NearestPoint
(
aSeg
.
a
)
-
aSeg
.
a
,
NearestPoint
(
aSeg
.
b
)
-
aSeg
.
b
};
ecoord
m
=
VECTOR2I
::
ECOORD_MAX
;
for
(
int
i
=
0
;
i
<
4
;
i
++
)
m
=
std
::
min
(
m
,
pts
[
i
].
SquaredEuclideanNorm
());
return
m
;
}
OPT_VECTOR2I
SEG
::
Intersect
(
const
SEG
&
aSeg
,
bool
aIgnoreEndpoints
,
bool
aLines
)
const
{
const
VECTOR2I
e
(
b
-
a
);
const
VECTOR2I
f
(
aSeg
.
b
-
aSeg
.
a
);
const
VECTOR2I
ac
(
aSeg
.
a
-
a
);
ecoord
d
=
f
.
Cross
(
e
);
ecoord
p
=
f
.
Cross
(
ac
);
ecoord
q
=
e
.
Cross
(
ac
);
if
(
d
==
0
)
return
OPT_VECTOR2I
();
if
(
!
aLines
&&
d
>
0
&&
(
q
<
0
||
q
>
d
||
p
<
0
||
p
>
d
))
return
OPT_VECTOR2I
();
if
(
!
aLines
&&
d
<
0
&&
(
q
<
d
||
p
<
d
||
p
>
0
||
q
>
0
))
return
OPT_VECTOR2I
();
if
(
!
aLines
&&
aIgnoreEndpoints
&&
(
q
==
0
||
q
==
d
)
&&
(
p
==
0
||
p
==
d
))
return
OPT_VECTOR2I
();
VECTOR2I
ip
(
aSeg
.
a
.
x
+
rescale
(
q
,
(
ecoord
)
f
.
x
,
d
),
aSeg
.
a
.
y
+
rescale
(
q
,
(
ecoord
)
f
.
y
,
d
)
);
return
ip
;
}
bool
SEG
::
ccw
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
,
const
VECTOR2I
&
c
)
const
{
return
(
ecoord
)(
c
.
y
-
a
.
y
)
*
(
b
.
x
-
a
.
x
)
>
(
ecoord
)(
b
.
y
-
a
.
y
)
*
(
c
.
x
-
a
.
x
);
}
bool
SEG
::
Collide
(
const
SEG
&
aSeg
,
int
aClearance
)
const
{
// check for intersection
// fixme: move to a method
if
(
ccw
(
a
,
aSeg
.
a
,
aSeg
.
b
)
!=
ccw
(
b
,
aSeg
.
a
,
aSeg
.
b
)
&&
ccw
(
a
,
b
,
aSeg
.
a
)
!=
ccw
(
a
,
b
,
aSeg
.
b
)
)
return
true
;
#define CHK(_seg, _pt) \
if( (_seg).PointCloserThan (_pt, aClearance ) ) return true;
CHK
(
*
this
,
aSeg
.
a
);
CHK
(
*
this
,
aSeg
.
b
);
CHK
(
aSeg
,
a
);
CHK
(
aSeg
,
b
);
#undef CHK
return
false
;
}
bool
SEG
::
Contains
(
const
VECTOR2I
&
aP
)
const
{
return
PointCloserThan
(
aP
,
1
);
}
common/geometry/shape_collisions.cpp
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <math/vector2d.h>
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_circle.h>
#include <geometry/shape_rect.h>
typedef
typename
VECTOR2I
::
extended_type
ecoord
;
static
inline
bool
Collide
(
const
SHAPE_CIRCLE
&
a
,
const
SHAPE_CIRCLE
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
ecoord
min_dist
=
clearance
+
a
.
GetRadius
()
+
b
.
GetRadius
();
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
const
VECTOR2I
delta
=
b
.
GetCenter
()
-
a
.
GetCenter
();
ecoord
dist_sq
=
delta
.
SquaredEuclideanNorm
();
if
(
dist_sq
>=
min_dist_sq
)
return
false
;
if
(
needMTV
)
aMTV
=
delta
.
Resize
(
sqrt
(
abs
(
min_dist_sq
-
dist_sq
))
+
1
);
return
true
;
}
static
inline
bool
Collide
(
const
SHAPE_RECT
&
a
,
const
SHAPE_CIRCLE
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
const
VECTOR2I
c
=
b
.
GetCenter
();
const
VECTOR2I
p0
=
a
.
GetPosition
();
const
VECTOR2I
size
=
a
.
GetSize
();
const
ecoord
r
=
b
.
GetRadius
();
const
ecoord
min_dist
=
clearance
+
r
;
const
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
if
(
a
.
BBox
(
0
).
Contains
(
c
))
return
true
;
const
VECTOR2I
vts
[]
=
{
VECTOR2I
(
p0
.
x
,
p0
.
y
),
VECTOR2I
(
p0
.
x
,
p0
.
y
+
size
.
y
),
VECTOR2I
(
p0
.
x
+
size
.
x
,
p0
.
y
+
size
.
y
),
VECTOR2I
(
p0
.
x
+
size
.
x
,
p0
.
y
),
VECTOR2I
(
p0
.
x
,
p0
.
y
)
};
ecoord
nearest_seg_dist_sq
=
VECTOR2I
::
ECOORD_MAX
;
VECTOR2I
nearest
;
bool
inside
=
c
.
x
>=
p0
.
x
&&
c
.
x
<=
(
p0
.
x
+
size
.
x
)
&&
c
.
y
>=
p0
.
y
&&
c
.
y
<=
(
p0
.
y
+
size
.
y
);
if
(
!
inside
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
const
SEG
seg
(
vts
[
i
],
vts
[
i
+
1
]);
ecoord
dist_sq
=
seg
.
SquaredDistance
(
c
);
if
(
dist_sq
<
min_dist_sq
)
{
if
(
!
needMTV
)
return
true
;
else
{
nearest
=
seg
.
NearestPoint
(
c
);
nearest_seg_dist_sq
=
dist_sq
;
}
}
}
}
if
(
nearest_seg_dist_sq
>=
min_dist_sq
&&
!
inside
)
return
false
;
VECTOR2I
delta
=
c
-
nearest
;
if
(
!
needMTV
)
return
true
;
if
(
inside
)
aMTV
=
-
delta
.
Resize
(
sqrt
(
abs
(
r
*
r
+
nearest_seg_dist_sq
)
+
1
));
else
aMTV
=
delta
.
Resize
(
sqrt
(
abs
(
r
*
r
-
nearest_seg_dist_sq
)
+
1
));
return
true
;
}
static
inline
bool
Collide
(
const
SHAPE_CIRCLE
&
a
,
const
SHAPE_LINE_CHAIN
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
s
=
0
;
s
<
b
.
SegmentCount
();
s
++
)
{
if
(
a
.
Collide
(
b
.
CSegment
(
s
),
clearance
))
return
true
;
}
return
false
;
}
static
inline
bool
Collide
(
const
SHAPE_LINE_CHAIN
&
a
,
const
SHAPE_LINE_CHAIN
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
i
=
0
;
i
<
b
.
SegmentCount
()
;
i
++
)
if
(
a
.
Collide
(
b
.
CSegment
(
i
),
clearance
))
return
true
;
return
false
;
}
static
inline
bool
Collide
(
const
SHAPE_RECT
&
a
,
const
SHAPE_LINE_CHAIN
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
s
=
0
;
s
<
b
.
SegmentCount
();
s
++
)
{
SEG
seg
=
b
.
CSegment
(
s
);
if
(
a
.
Collide
(
seg
,
clearance
))
return
true
;
}
return
false
;
}
bool
CollideShapes
(
const
SHAPE
*
a
,
const
SHAPE
*
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
switch
(
a
->
Type
())
{
case
SH_RECT
:
switch
(
b
->
Type
())
{
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
a
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
a
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
default:
break
;
}
case
SH_CIRCLE
:
switch
(
b
->
Type
())
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
b
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
a
),
clearance
,
needMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
a
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
a
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
default:
break
;
}
case
SH_LINE_CHAIN
:
switch
(
b
->
Type
())
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
b
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
a
),
clearance
,
needMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
b
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
a
),
clearance
,
needMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
a
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
default:
break
;
}
default:
break
;
}
bool
unsupported_collision
=
true
;
assert
(
unsupported_collision
==
false
);
return
false
;
}
bool
SHAPE
::
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
,
VECTOR2I
&
aMTV
)
const
{
return
CollideShapes
(
this
,
aShape
,
aClerance
,
true
,
aMTV
);
}
bool
SHAPE
::
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
)
const
{
VECTOR2I
dummy
;
return
CollideShapes
(
this
,
aShape
,
aClerance
,
false
,
dummy
);
}
\ No newline at end of file
common/geometry/shape_line_chain.cpp
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <geometry/shape_line_chain.h>
#include <geometry/shape_circle.h>
using
namespace
std
;
using
boost
::
optional
;
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
)
const
{
assert
(
false
);
return
false
;
}
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
)
const
{
assert
(
false
);
return
false
;
}
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
SEG
&
aSeg
,
int
aClearance
)
const
{
BOX2I
box_a
(
aSeg
.
a
,
aSeg
.
b
-
aSeg
.
a
);
BOX2I
::
ecoord_type
dist_sq
=
(
BOX2I
::
ecoord_type
)
aClearance
*
aClearance
;
for
(
int
i
=
0
;
i
<
SegmentCount
()
;
i
++
)
{
const
SEG
&
s
=
CSegment
(
i
);
BOX2I
box_b
(
s
.
a
,
s
.
b
-
s
.
a
);
BOX2I
::
ecoord_type
d
=
box_a
.
SquaredDistance
(
box_b
);
if
(
d
<
dist_sq
)
{
if
(
s
.
Collide
(
aSeg
,
aClearance
))
return
true
;
}
}
return
false
;
}
const
SHAPE_LINE_CHAIN
SHAPE_LINE_CHAIN
::
Reverse
()
const
{
SHAPE_LINE_CHAIN
a
(
*
this
);
reverse
(
a
.
m_points
.
begin
(),
a
.
m_points
.
end
());
a
.
m_closed
=
m_closed
;
return
a
;
}
int
SHAPE_LINE_CHAIN
::
Length
()
const
{
int
l
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
l
+=
CSegment
(
i
).
Length
();
return
l
;
}
void
SHAPE_LINE_CHAIN
::
Replace
(
int
start_index
,
int
end_index
,
const
VECTOR2I
&
aP
)
{
if
(
end_index
<
0
)
end_index
+=
PointCount
();
if
(
start_index
<
0
)
start_index
+=
PointCount
();
if
(
start_index
==
end_index
)
m_points
[
start_index
]
=
aP
;
else
{
m_points
.
erase
(
m_points
.
begin
()
+
start_index
+
1
,
m_points
.
begin
()
+
end_index
+
1
);
m_points
[
start_index
]
=
aP
;
}
}
void
SHAPE_LINE_CHAIN
::
Replace
(
int
start_index
,
int
end_index
,
const
SHAPE_LINE_CHAIN
&
aLine
)
{
if
(
end_index
<
0
)
end_index
+=
PointCount
();
if
(
start_index
<
0
)
start_index
+=
PointCount
();
m_points
.
erase
(
m_points
.
begin
()
+
start_index
,
m_points
.
begin
()
+
end_index
+
1
);
m_points
.
insert
(
m_points
.
begin
()
+
start_index
,
aLine
.
m_points
.
begin
(),
aLine
.
m_points
.
end
());
}
void
SHAPE_LINE_CHAIN
::
Remove
(
int
start_index
,
int
end_index
)
{
if
(
end_index
<
0
)
end_index
+=
PointCount
();
if
(
start_index
<
0
)
start_index
+=
PointCount
();
m_points
.
erase
(
m_points
.
begin
()
+
start_index
,
m_points
.
begin
()
+
end_index
+
1
);
}
int
SHAPE_LINE_CHAIN
::
Distance
(
const
VECTOR2I
&
aP
)
const
{
int
d
=
INT_MAX
;
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
d
=
min
(
d
,
CSegment
(
s
).
Distance
(
aP
));
return
d
;
}
int
SHAPE_LINE_CHAIN
::
Split
(
const
VECTOR2I
&
aP
)
{
int
ii
=
-
1
;
int
min_dist
=
2
;
ii
=
Find
(
aP
);
if
(
ii
>=
0
)
return
ii
;
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
{
const
SEG
seg
=
CSegment
(
s
);
int
dist
=
seg
.
Distance
(
aP
);
// make sure we are not producing a 'slightly concave' primitive. This might happen
// if aP lies very close to one of already existing points.
if
(
dist
<
min_dist
&&
seg
.
a
!=
aP
&&
seg
.
b
!=
aP
)
{
min_dist
=
dist
;
ii
=
s
;
}
}
if
(
ii
>=
0
)
{
m_points
.
insert
(
m_points
.
begin
()
+
ii
+
1
,
aP
);
return
ii
+
1
;
}
return
-
1
;
}
int
SHAPE_LINE_CHAIN
::
Find
(
const
VECTOR2I
&
aP
)
const
{
for
(
int
s
=
0
;
s
<
PointCount
();
s
++
)
if
(
CPoint
(
s
)
==
aP
)
return
s
;
return
-
1
;
}
const
SHAPE_LINE_CHAIN
SHAPE_LINE_CHAIN
::
Slice
(
int
start_index
,
int
end_index
)
const
{
SHAPE_LINE_CHAIN
rv
;
if
(
end_index
<
0
)
end_index
+=
PointCount
();
if
(
start_index
<
0
)
start_index
+=
PointCount
();
for
(
int
i
=
start_index
;
i
<=
end_index
;
i
++
)
rv
.
Append
(
m_points
[
i
]);
return
rv
;
}
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
SHAPE_LINE_CHAIN
::
Intersection
&
a
,
const
SHAPE_LINE_CHAIN
::
Intersection
&
b
)
{
return
(
m_origin
-
a
.
p
).
EuclideanNorm
()
<
(
m_origin
-
b
.
p
).
EuclideanNorm
();
}
VECTOR2I
m_origin
;
};
int
SHAPE_LINE_CHAIN
::
Intersect
(
const
SEG
&
aSeg
,
Intersections
&
aIp
)
const
{
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
{
OPT_VECTOR2I
p
=
CSegment
(
s
).
Intersect
(
aSeg
);
if
(
p
)
{
Intersection
is
;
is
.
our
=
CSegment
(
s
);
is
.
their
=
aSeg
;
is
.
p
=
*
p
;
aIp
.
push_back
(
is
);
}
}
compareOriginDistance
comp
(
aSeg
.
a
);
sort
(
aIp
.
begin
(),
aIp
.
end
(),
comp
);
return
aIp
.
size
();
};
int
SHAPE_LINE_CHAIN
::
Intersect
(
const
SHAPE_LINE_CHAIN
&
aChain
,
Intersections
&
aIp
)
const
{
BOX2I
bb_other
=
aChain
.
BBox
();
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
{
const
SEG
&
a
=
CSegment
(
s1
);
const
BOX2I
bb_cur
(
a
.
a
,
a
.
b
-
a
.
a
);
if
(
!
bb_other
.
Intersects
(
bb_cur
))
continue
;
for
(
int
s2
=
0
;
s2
<
aChain
.
SegmentCount
();
s2
++
)
{
const
SEG
&
b
=
aChain
.
CSegment
(
s2
);
Intersection
is
;
if
(
a
.
Collinear
(
b
))
{
if
(
a
.
Contains
(
b
.
a
))
{
is
.
p
=
b
.
a
;
aIp
.
push_back
(
is
);
}
if
(
a
.
Contains
(
b
.
b
))
{
is
.
p
=
b
.
b
;
aIp
.
push_back
(
is
);
}
if
(
b
.
Contains
(
a
.
a
))
{
is
.
p
=
a
.
a
;
aIp
.
push_back
(
is
);
}
if
(
b
.
Contains
(
a
.
b
))
{
is
.
p
=
a
.
b
;
aIp
.
push_back
(
is
);
}
}
else
{
OPT_VECTOR2I
p
=
a
.
Intersect
(
b
);
if
(
p
)
{
is
.
p
=
*
p
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
}
}
}
}
return
aIp
.
size
();
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
for
(
int
s2
=
0
;
s2
<
aChain
.
SegmentCount
();
s2
++
)
{
const
SEG
&
a
=
CSegment
(
s1
);
const
SEG
&
b
=
aChain
.
CSegment
(
s2
);
OPT_VECTOR2I
p
=
a
.
Intersect
(
b
);
Intersection
is
;
if
(
p
)
{
is
.
p
=
*
p
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
}
else
if
(
a
.
Collinear
(
b
))
{
if
(
a
.
a
!=
b
.
a
&&
a
.
a
!=
b
.
b
&&
b
.
Contains
(
a
.
a
)
)
{
is
.
p
=
a
.
a
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
}
else
if
(
a
.
b
!=
b
.
a
&&
a
.
b
!=
b
.
b
&&
b
.
Contains
(
a
.
b
)
)
{
is
.
p
=
a
.
b
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
}
}
}
return
aIp
.
size
();
}
int
SHAPE_LINE_CHAIN
::
PathLength
(
const
VECTOR2I
&
aP
)
const
{
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
seg
=
CSegment
(
i
);
int
d
=
seg
.
Distance
(
aP
);
if
(
d
<=
1
)
{
sum
+=
(
aP
-
seg
.
a
).
EuclideanNorm
();
return
sum
;
}
else
sum
+=
seg
.
Length
();
}
return
-
1
;
}
bool
SHAPE_LINE_CHAIN
::
PointInside
(
const
VECTOR2I
&
aP
)
const
{
if
(
!
m_closed
||
SegmentCount
()
<
3
)
return
false
;
int
cur
=
CSegment
(
0
).
Side
(
aP
);
if
(
cur
==
0
)
return
false
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
s
=
CSegment
(
i
);
if
(
aP
==
s
.
a
||
aP
==
s
.
b
)
// edge does not belong to the interior!
return
false
;
if
(
s
.
Side
(
aP
)
!=
cur
)
return
false
;
}
return
true
;
}
bool
SHAPE_LINE_CHAIN
::
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
{
if
(
SegmentCount
()
<
1
)
return
m_points
[
0
]
==
aP
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
s
=
CSegment
(
i
);
if
(
s
.
a
==
aP
||
s
.
b
==
aP
)
return
true
;
if
(
s
.
Distance
(
aP
)
<=
1
)
return
true
;
}
return
false
;
}
const
optional
<
SHAPE_LINE_CHAIN
::
Intersection
>
SHAPE_LINE_CHAIN
::
SelfIntersecting
()
const
{
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
for
(
int
s2
=
s1
+
1
;
s2
<
SegmentCount
();
s2
++
)
{
const
VECTOR2I
s2a
=
CSegment
(
s2
).
a
,
s2b
=
CSegment
(
s2
).
b
;
if
(
s1
+
1
!=
s2
&&
CSegment
(
s1
).
Contains
(
s2a
))
{
Intersection
is
;
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
s2a
;
return
is
;
}
else
if
(
CSegment
(
s1
).
Contains
(
s2b
))
{
Intersection
is
;
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
s2b
;
return
is
;
}
else
{
OPT_VECTOR2I
p
=
CSegment
(
s1
).
Intersect
(
CSegment
(
s2
),
true
);
if
(
p
)
{
Intersection
is
;
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
*
p
;
return
is
;
}
}
}
return
optional
<
Intersection
>
();
}
SHAPE_LINE_CHAIN
&
SHAPE_LINE_CHAIN
::
Simplify
()
{
vector
<
VECTOR2I
>
pts_unique
;
if
(
PointCount
()
<
2
)
{
return
*
this
;
}
else
if
(
PointCount
()
==
2
)
{
if
(
m_points
[
0
]
==
m_points
[
1
])
m_points
.
erase
(
m_points
.
end
());
return
*
this
;
}
int
i
=
0
;
int
np
=
PointCount
();
// stage 1: eliminate duplicate vertices
while
(
i
<
np
)
{
int
j
=
i
+
1
;
while
(
j
<
np
&&
CPoint
(
i
)
==
CPoint
(
j
))
j
++
;
pts_unique
.
push_back
(
CPoint
(
i
));
i
=
j
;
}
m_points
.
clear
();
np
=
pts_unique
.
size
();
i
=
0
;
// stage 1: eliminate collinear segments
while
(
i
<
np
-
2
)
{
const
VECTOR2I
p0
=
pts_unique
[
i
];
const
VECTOR2I
p1
=
pts_unique
[
i
+
1
];
int
n
=
i
;
while
(
n
<
np
-
2
&&
SEG
(
p0
,
p1
).
LineDistance
(
pts_unique
[
n
+
2
])
<=
1
)
n
++
;
m_points
.
push_back
(
p0
);
if
(
n
>
i
)
i
=
n
;
if
(
n
==
np
)
{
m_points
.
push_back
(
pts_unique
[
n
-
1
]);
return
*
this
;
}
i
++
;
}
if
(
np
>
1
)
m_points
.
push_back
(
pts_unique
[
np
-
2
]);
m_points
.
push_back
(
pts_unique
[
np
-
1
]);
return
*
this
;
}
const
VECTOR2I
SHAPE_LINE_CHAIN
::
NearestPoint
(
const
VECTOR2I
&
aP
)
const
{
int
min_d
=
INT_MAX
;
int
nearest
;
for
(
int
i
=
0
;
i
<
SegmentCount
()
;
i
++
)
{
int
d
=
CSegment
(
i
).
Distance
(
aP
);
if
(
d
<
min_d
)
{
min_d
=
d
;
nearest
=
i
;
}
}
return
CSegment
(
nearest
).
NearestPoint
(
aP
);
}
const
string
SHAPE_LINE_CHAIN
::
Format
()
const
{
stringstream
ss
;
ss
<<
m_points
.
size
()
<<
" "
<<
(
m_closed
?
1
:
0
)
<<
" "
;
for
(
int
i
=
0
;
i
<
PointCount
();
i
++
)
ss
<<
m_points
[
i
].
x
<<
" "
<<
m_points
[
i
].
y
<<
" "
;
// Format() << " ";
return
ss
.
str
();
}
include/geometry/seg.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SEG_H
#define __SEG_H
#include <cstdio>
#include <climits>
#include <math/vector2d.h>
#include <boost/optional/optional.hpp>
typedef
boost
::
optional
<
VECTOR2I
>
OPT_VECTOR2I
;
class
SEG
{
private
:
typedef
VECTOR2I
::
extended_type
ecoord
;
public
:
friend
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
aStream
,
const
SEG
&
aSeg
);
/* Start and the of the segment. Public, to make access simpler. These are references
* to an object the segment belongs to (e.g. a line chain) or references to locally stored points
* (m_a, m_b).
*/
VECTOR2I
&
a
,
b
;
/** Default constructor
* Creates an empty (0, 0) segment, locally-referenced
*/
SEG
()
:
a
(
m_a
),
b
(
m_b
)
{
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
/**
* Constructor
* Creates a segment between (x1, y1) and (x2, y2), locally referenced
*/
SEG
(
int
x1
,
int
y1
,
int
x2
,
int
y2
)
:
a
(
m_a
),
b
(
m_b
)
{
m_a
=
VECTOR2I
(
x1
,
y1
);
m_b
=
VECTOR2I
(
x2
,
y2
);
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
/**
* Constructor
* Creates a segment between (aA) and (aB), locally referenced
*/
SEG
(
const
VECTOR2I
&
aA
,
const
VECTOR2I
&
aB
)
:
a
(
m_a
),
b
(
m_b
),
m_a
(
aA
),
m_b
(
aB
)
{
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
/**
* Constructor
* Creates a segment between (aA) and (aB), referenced to a multi-segment shape
* @param aA reference to the start point in the parent shape
* @param aB reference to the end point in the parent shape
* @param aIndex index of the segment within the parent shape
*/
SEG
(
VECTOR2I
&
aA
,
VECTOR2I
&
aB
,
int
aIndex
)
:
a
(
aA
),
b
(
aB
)
{
m_is_local
=
false
;
m_index
=
aIndex
;
}
/**
* Copy constructor
*/
SEG
(
const
SEG
&
seg
)
:
a
(
m_a
),
b
(
m_b
)
{
if
(
seg
.
m_is_local
)
{
m_a
=
seg
.
m_a
;
m_b
=
seg
.
m_b
;
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
else
{
a
=
seg
.
a
;
b
=
seg
.
b
;
m_index
=
seg
.
m_index
;
m_is_local
=
false
;
}
}
SEG
&
operator
=
(
const
SEG
&
seg
)
{
a
=
seg
.
a
;
b
=
seg
.
b
;
m_a
=
seg
.
m_a
;
m_b
=
seg
.
m_b
;
m_index
=
seg
.
m_index
;
m_is_local
=
seg
.
m_is_local
;
return
*
this
;
}
/**
* Function LineProject()
*
* Computes the perpendicular projection point of aP on a line passing through
* ends of the segment.
* @param aP point to project
* @return projected point
*/
VECTOR2I
LineProject
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function Side()
*
* Determines on which side of directed line passing via segment ends point aP lies.
* @param aP point to determine the orientation wrs to self
* @return: < 0: left, 0 : on the line, > 0 : right
*/
int
Side
(
const
VECTOR2I
&
aP
)
const
{
const
ecoord
det
=
(
b
-
a
).
Cross
(
aP
-
a
);
return
det
<
0
?
-
1
:
(
det
>
0
?
1
:
0
);
}
/**
* Function LineDistance()
*
* Returns the closest Euclidean distance between point aP and the line defined by
* the ends of segment (this).
* @param aDetermineSide: when true, the sign of the returned value indicates
* the side of the line at which we are (negative = left)
* @return the distance
*/
int
LineDistance
(
const
VECTOR2I
&
aP
,
bool
aDetermineSide
=
false
)
const
;
/**
* Function NearestPoint()
*
* Computes a point on the segment (this) that is closest to point aP.
* @return: nearest point
*/
const
VECTOR2I
NearestPoint
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function Intersect()
*
* Computes intersection point of segment (this) with segment aSeg.
* @param aSeg: segment to intersect with
* @param aIgnoreEndpoints: don't treat corner cases (i.e. end of one segment touching the other)
* as intersections.
* @param aLines: treat segments as infinite lines
* @return intersection point, if exists
*/
OPT_VECTOR2I
Intersect
(
const
SEG
&
aSeg
,
bool
aIgnoreEndpoints
=
false
,
bool
aLines
=
false
)
const
;
/**
* Function IntersectLines()
*
* Computes the intersection point of lines passing through ends of (this) and aSeg
* @param aSeg segment defining the line to intersect with
* @return intersection point, if exists
*/
OPT_VECTOR2I
IntersectLines
(
const
SEG
&
aSeg
)
const
{
return
Intersect
(
aSeg
,
false
,
true
);
}
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
)
const
;
/**
* Function Distance()
*
* Computes minimum Euclidean distance to segment aSeg.
* @param aSeg other segment
* @return minimum distance
*/
ecoord
SquaredDistance
(
const
SEG
&
aSeg
)
const
;
int
Distance
(
const
SEG
&
aSeg
)
const
{
return
sqrt
(
SquaredDistance
(
aSeg
)
);
}
/**
* Function Distance()
*
* Computes minimum Euclidean distance to point aP.
* @param aP the point
* @return minimum distance
*/
ecoord
SquaredDistance
(
const
VECTOR2I
&
aP
)
const
{
return
(
NearestPoint
(
aP
)
-
aP
).
SquaredEuclideanNorm
();
}
int
Distance
(
const
VECTOR2I
&
aP
)
const
{
return
sqrt
(
SquaredDistance
(
aP
)
);
}
/**
* Function Collinear()
*
* Checks if segment aSeg lies on the same line as (this).
* @param aSeg the segment to chech colinearity with
* @return true, when segments are collinear.
*/
bool
Collinear
(
const
SEG
&
aSeg
)
const
{
ecoord
qa1
=
a
.
y
-
b
.
y
;
ecoord
qb1
=
b
.
x
-
a
.
x
;
ecoord
qc1
=
-
qa1
*
a
.
x
-
qb1
*
a
.
y
;
ecoord
qa2
=
aSeg
.
a
.
y
-
aSeg
.
b
.
y
;
ecoord
qb2
=
aSeg
.
b
.
x
-
aSeg
.
a
.
x
;
ecoord
qc2
=
-
qa2
*
aSeg
.
a
.
x
-
qb2
*
aSeg
.
a
.
y
;
return
(
qa1
==
qa2
)
&&
(
qb1
==
qb2
)
&&
(
qc1
==
qc2
);
}
/**
* Function Length()
*
* Returns the length (this)
* @return length
*/
int
Length
()
const
{
return
(
a
-
b
).
EuclideanNorm
();
}
/**
* Function Index()
*
* Return the index of this segment in its parent shape (applicable only to non-local segments)
* @return index value
*/
int
Index
()
const
{
return
m_index
;
}
bool
Contains
(
const
VECTOR2I
&
aP
)
const
;
bool
PointCloserThan
(
const
VECTOR2I
&
aP
,
int
dist
)
const
;
// friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
private
:
bool
ccw
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
,
const
VECTOR2I
&
c
)
const
;
///> locally stored start/end coordinates (used when m_is_local == true)
VECTOR2I
m_a
,
m_b
;
///> index withing the parent shape (used when m_is_local == false)
int
m_index
;
///> locality flag
bool
m_is_local
;
};
inline
VECTOR2I
SEG
::
LineProject
(
const
VECTOR2I
&
aP
)
const
{
// fixme: numerical errors for large integers
assert
(
false
);
/*const VECTOR2I d = aB - aA;
ecoord det = d.Dot(d);
ecoord dxdy = (ecoord) d.x * d.y;
ecoord qx =
( (extended_type) aA.x * d.y * d.y + (extended_type) d.x * d.x * x - dxdy *
(aA.y - y) ) / det;
extended_type qy =
( (extended_type) aA.y * d.x * d.x + (extended_type) d.y * d.y * y - dxdy *
(aA.x - x) ) / det;
return VECTOR2<T> ( (T) qx, (T) qy );*/
}
inline
int
SEG
::
LineDistance
(
const
VECTOR2I
&
aP
,
bool
aDetermineSide
)
const
{
ecoord
p
=
a
.
y
-
b
.
y
;
ecoord
q
=
b
.
x
-
a
.
x
;
ecoord
r
=
-
p
*
a
.
x
-
q
*
a
.
y
;
ecoord
dist
=
(
p
*
aP
.
x
+
q
*
aP
.
y
+
r
)
/
sqrt
(
p
*
p
+
q
*
q
);
return
aDetermineSide
?
dist
:
abs
(
dist
);
}
inline
const
VECTOR2I
SEG
::
NearestPoint
(
const
VECTOR2I
&
aP
)
const
{
VECTOR2I
d
=
b
-
a
;
ecoord
l_squared
=
d
.
Dot
(
d
);
if
(
l_squared
==
0
)
return
a
;
ecoord
t
=
d
.
Dot
(
aP
-
a
);
if
(
t
<
0
)
return
a
;
else
if
(
t
>
l_squared
)
return
b
;
int
xp
=
rescale
(
t
,
(
ecoord
)
d
.
x
,
l_squared
);
int
yp
=
rescale
(
t
,
(
ecoord
)
d
.
y
,
l_squared
);
return
a
+
VECTOR2I
(
xp
,
yp
);
}
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
aStream
,
const
SEG
&
aSeg
)
{
if
(
aSeg
.
m_is_local
)
aStream
<<
"[ local "
<<
aSeg
.
a
<<
" - "
<<
aSeg
.
b
<<
" ]"
;
return
aStream
;
}
#endif // __SEG_H
include/geometry/shape.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_H
#define __SHAPE_H
#include <math/vector2d.h>
#include <math/box2.h>
#include <geometry/seg.h>
/**
* Enum ShapeType
* Lists all supported shapes
*/
enum
ShapeType
{
SH_RECT
=
0
,
///> axis-aligned rectangle
SH_SEGMENT
,
///> line segment
SH_LINE_CHAIN
,
///> line chain (polyline)
SH_CIRCLE
///> circle
};
/**
* Class SHAPE
*
* Represents an abstract shape on 2D plane. All SHAPEs implement SHAPE interface.
*/
class
SHAPE
{
protected
:
typedef
typename
VECTOR2I
::
extended_type
ecoord
;
public
:
/**
* Constructor
*
* Creates an empty shape of type aType
*/
SHAPE
(
ShapeType
aType
)
:
m_type
(
aType
)
{
};
// Destructor
virtual
~
SHAPE
()
{};
/**
* Function Type()
*
* Returns the type of the shape.
* @retval the type
*/
ShapeType
Type
()
const
{
return
m_type
;
}
/**
* Function Clone()
*
* Returns a dynamically allocated copy of the shape
* @retval copy of the shape
*/
virtual
SHAPE
*
Clone
()
const
{
assert
(
false
);
};
/**
* Function Collide()
*
* Checks if the boundary of shape (this) lies closer to the point aP than aClearance, indicating
* a collision.
* @return true, if there is a collision.
*/
virtual
bool
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
=
0
)
const
{
return
Collide
(
SEG
(
aP
,
aP
),
aClearance
);
}
/**
* Function Collide()
*
* Checks if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating
* a collision.
* @return true, if there is a collision.
*/
virtual
bool
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
,
VECTOR2I
&
aMTV
)
const
;
virtual
bool
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
=
0
)
const
;
/**
* Function Collide()
*
* Checks if the boundary of shape (this) lies closer to the segment aSeg than aClearance, indicating
* a collision.
* @return true, if there is a collision.
*/
virtual
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
=
0
;
/**
* Function Collide()
*
* Computes a bounding box of the shape, with a margin of aClearance
* a collision.
* @aClearance how much the bounding box is expanded wrs to the minimum enclosing rectangle for the shape.
* @return the bounding box.
*/
virtual
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
=
0
;
/**
* Function Centre()
*
* Computes a center-of-mass of the shape
* @return the center-of-mass point
*/
virtual
VECTOR2I
Centre
()
const
{
return
BBox
(
0
).
Centre
();
// if nothing better is available....
}
private
:
///> type of our shape
ShapeType
m_type
;
};
bool
CollideShapes
(
const
SHAPE
*
a
,
const
SHAPE
*
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
);
#endif // __SHAPE_H
include/geometry/shape_circle.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_CIRCLE_H
#define __SHAPE_CIRCLE_H
#include "shape.h"
class
SHAPE_CIRCLE
:
public
SHAPE
{
public
:
SHAPE_CIRCLE
()
:
SHAPE
(
SH_CIRCLE
),
m_radius
(
0
)
{};
SHAPE_CIRCLE
(
const
VECTOR2I
&
aCenter
,
int
aRadius
)
:
SHAPE
(
SH_CIRCLE
),
m_radius
(
aRadius
),
m_center
(
aCenter
)
{};
~
SHAPE_CIRCLE
()
{};
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
const
VECTOR2I
rc
(
m_radius
+
aClearance
,
m_radius
+
aClearance
);
return
BOX2I
(
m_center
-
rc
,
rc
*
2
);
}
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
{
int
rc
=
aClearance
+
m_radius
;
return
aSeg
.
Distance
(
m_center
)
<=
rc
;
}
void
SetRadius
(
int
aRadius
)
{
m_radius
=
aRadius
;
}
void
SetCenter
(
const
VECTOR2I
&
aCenter
)
{
m_center
=
aCenter
;
}
int
GetRadius
()
const
{
return
m_radius
;
}
const
VECTOR2I
GetCenter
()
const
{
return
m_center
;
}
private
:
int
m_radius
;
VECTOR2I
m_center
;
};
#endif
include/geometry/shape_index.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_INDEX_H
#define __SHAPE_INDEX_H
#include <boost/unordered_map.hpp>
template
<
class
T
>
const
SHAPE
*
defaultShapeFunctor
(
const
T
aItem
)
{
return
aItem
->
GetShape
();
}
template
<
class
T
,
const
SHAPE
*
(
ShapeFunctor
)(
const
T
)
=
defaultShapeFunctor
<
T
>
>
class
SHAPE_INDEX_LIST
{
struct
ShapeEntry
{
ShapeEntry
(
T
aParent
)
{
shape
=
ShapeFunctor
(
aParent
);
bbox
=
shape
->
BBox
(
0
);
parent
=
aParent
;
}
~
ShapeEntry
()
{
}
T
parent
;
const
SHAPE
*
shape
;
BOX2I
bbox
;
};
typedef
std
::
vector
<
ShapeEntry
>
ShapeVec
;
typedef
typename
std
::
vector
<
ShapeEntry
>::
iterator
ShapeVecIter
;
public
:
// "Normal" iterator interface, for STL algorithms.
class
iterator
{
public
:
iterator
()
{};
iterator
(
ShapeVecIter
aCurrent
)
:
m_current
(
aCurrent
)
{};
iterator
(
const
iterator
&
b
)
:
m_current
(
b
.
m_current
)
{};
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
void
operator
++
()
{
++
m_current
;
}
iterator
&
operator
++
(
int
dummy
)
{
++
m_current
;
return
*
this
;
}
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
m_current
==
rhs
.
m_current
;
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
m_current
!=
rhs
.
m_current
;
}
const
iterator
&
operator
=
(
const
iterator
&
rhs
)
{
m_current
=
rhs
.
m_current
;
return
*
this
;
}
private
:
ShapeVecIter
m_current
;
};
// "Query" iterator, for iterating over a set of spatially matching shapes.
class
query_iterator
{
public
:
query_iterator
()
{
}
query_iterator
(
ShapeVecIter
aCurrent
,
ShapeVecIter
aEnd
,
SHAPE
*
aShape
,
int
aMinDistance
,
bool
aExact
)
:
m_end
(
aEnd
),
m_current
(
aCurrent
),
m_shape
(
aShape
),
m_minDistance
(
aMinDistance
),
m_exact
(
aExact
)
{
if
(
aShape
)
{
m_refBBox
=
aShape
->
BBox
();
next
();
}
}
query_iterator
(
const
query_iterator
&
b
)
:
m_end
(
b
.
m_end
),
m_current
(
b
.
m_current
),
m_shape
(
b
.
m_shape
),
m_minDistance
(
b
.
m_minDistance
),
m_exact
(
b
.
m_exact
),
m_refBBox
(
b
.
m_refBBox
)
{
}
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
query_iterator
&
operator
++
()
{
++
m_current
;
next
();
return
*
this
;
}
query_iterator
&
operator
++
(
int
dummy
)
{
++
m_current
;
next
();
return
*
this
;
}
bool
operator
==
(
const
query_iterator
&
rhs
)
const
{
return
m_current
==
rhs
.
m_current
;
}
bool
operator
!=
(
const
query_iterator
&
rhs
)
const
{
return
m_current
!=
rhs
.
m_current
;
}
const
query_iterator
&
operator
=
(
const
query_iterator
&
rhs
)
{
m_end
=
rhs
.
m_end
;
m_current
=
rhs
.
m_current
;
m_shape
=
rhs
.
m_shape
;
m_minDistance
=
rhs
.
m_minDistance
;
m_exact
=
rhs
.
m_exact
;
m_refBBox
=
rhs
.
m_refBBox
;
return
*
this
;
}
private
:
void
next
()
{
while
(
m_current
!=
m_end
)
{
if
(
m_refBBox
.
Distance
(
m_current
->
bbox
)
<=
m_minDistance
)
{
if
(
!
m_exact
||
m_current
->
shape
->
Collide
(
m_shape
,
m_minDistance
))
return
;
}
++
m_current
;
}
}
ShapeVecIter
m_end
;
ShapeVecIter
m_current
;
BOX2I
m_refBBox
;
bool
m_exact
;
SHAPE
*
m_shape
;
int
m_minDistance
;
};
void
Add
(
T
aItem
)
{
ShapeEntry
s
(
aItem
);
m_shapes
.
push_back
(
s
);
}
void
Remove
(
const
T
aItem
)
{
ShapeVecIter
i
;
for
(
i
=
m_shapes
.
begin
();
i
!=
m_shapes
.
end
();
++
i
)
{
if
(
i
->
parent
==
aItem
)
break
;
}
if
(
i
==
m_shapes
.
end
())
return
;
m_shapes
.
erase
(
i
);
}
int
Size
()
const
{
return
m_shapes
.
size
();
}
template
<
class
Visitor
>
int
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
Visitor
&
v
,
bool
aExact
=
true
)
//const
{
ShapeVecIter
i
;
int
n
=
0
;
VECTOR2I
::
extended_type
minDistSq
=
(
VECTOR2I
::
extended_type
)
aMinDistance
*
aMinDistance
;
BOX2I
refBBox
=
aShape
->
BBox
();
for
(
i
=
m_shapes
.
begin
();
i
!=
m_shapes
.
end
();
++
i
)
{
if
(
refBBox
.
SquaredDistance
(
i
->
bbox
)
<=
minDistSq
)
{
if
(
!
aExact
||
i
->
shape
->
Collide
(
aShape
,
aMinDistance
))
{
n
++
;
if
(
!
v
(
i
->
parent
))
return
n
;
}
}
}
return
n
;
}
void
Clear
()
{
m_shapes
.
clear
();
}
query_iterator
qbegin
(
SHAPE
*
aShape
,
int
aMinDistance
,
bool
aExact
)
{
return
query_iterator
(
m_shapes
.
begin
(),
m_shapes
.
end
(),
aShape
,
aMinDistance
,
aExact
);
}
const
query_iterator
qend
()
{
return
query_iterator
(
m_shapes
.
end
(),
m_shapes
.
end
(),
NULL
,
0
,
false
);
}
iterator
begin
()
{
return
iterator
(
m_shapes
.
begin
()
);
}
iterator
end
()
{
return
iterator
(
m_shapes
.
end
()
);
}
private
:
ShapeVec
m_shapes
;
};
#endif
include/geometry/shape_line_chain.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_LINE_CHAIN
#define __SHAPE_LINE_CHAIN
#include <vector>
#include <sstream>
#include <boost/optional.hpp>
#include <math/vector2d.h>
#include <geometry/shape.h>
#include <geometry/seg.h>
/**
* Class SHAPE_LINE_CHAIN
*
* Represents a polyline (an zero-thickness chain of connected line segments).
* I purposedly didn't name it "polyline" to avoid confusion with the existing CPolyLine class in pcbnew.
*
* SHAPE_LINE_CHAIN class shall not be used for polygons!
*/
class
SHAPE_LINE_CHAIN
:
public
SHAPE
{
private
:
typedef
std
::
vector
<
VECTOR2I
>::
iterator
point_iter
;
typedef
std
::
vector
<
VECTOR2I
>::
const_iterator
point_citer
;
public
:
/**
* Struct Intersection
*
* Represents an intersection between two line segments
*/
struct
Intersection
{
/// segment belonging from the (this) argument of Intersect()
SEG
our
;
/// segment belonging from the aOther argument of Intersect()
SEG
their
;
/// point of intersection between our and their.
VECTOR2I
p
;
};
typedef
std
::
vector
<
Intersection
>
Intersections
;
/**
* Constructor
* Initializes an empty line chain.
*/
SHAPE_LINE_CHAIN
()
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{};
/**
* Copy Constructor
*/
SHAPE_LINE_CHAIN
(
const
SHAPE_LINE_CHAIN
&
aShape
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_points
(
aShape
.
m_points
),
m_closed
(
aShape
.
m_closed
)
{};
/**
* Constructor
* Initializes a 2-point line chain (a single segment)
*/
SHAPE_LINE_CHAIN
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
2
);
m_points
[
0
]
=
a
;
m_points
[
1
]
=
b
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
,
const
VECTOR2I
&
c
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
3
);
m_points
[
0
]
=
a
;
m_points
[
1
]
=
b
;
m_points
[
2
]
=
c
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
*
v
,
int
count
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
count
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
m_points
[
i
]
=
*
v
++
;
}
~
SHAPE_LINE_CHAIN
()
{};
/**
* Function Clear()
* Removes all points from the line chain.
*/
void
Clear
()
{
m_points
.
clear
();
m_closed
=
false
;
}
/**
* Function SetClosed()
*
* Marks the line chain as closed (i.e. with a segment connecting the last point with the first point).
* @param aClosed: whether the line chain is to be closed or not.
*/
void
SetClosed
(
bool
aClosed
)
{
m_closed
=
aClosed
;
}
/**
* Function IsClosed()
*
* @return aClosed: true, when our line is closed.
*/
bool
IsClosed
()
const
{
return
m_closed
;
}
/**
* Function SegmentCount()
*
* Returns number of segments in this line chain.
* @return number of segments
*/
int
SegmentCount
()
const
{
int
c
=
m_points
.
size
()
-
1
;
if
(
m_closed
)
c
++
;
return
std
::
max
(
0
,
c
);
}
/**
* Function PointCount()
*
* Returns the number of points (vertices) in this line chain
* @return number of points
*/
int
PointCount
()
const
{
return
m_points
.
size
();
};
/**
* Function Segment()
*
* Returns a segment referencing to the segment (index) in the line chain.
* Modifying ends of the returned segment will modify corresponding points in the line chain.
* @param index: index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means
* the last segment in the line chain)
* @return SEG referenced to given segment in the line chain
*/
SEG
Segment
(
int
index
)
{
if
(
index
<
0
)
index
+=
SegmentCount
();
if
(
index
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
m_points
[
index
],
m_points
[
0
],
index
);
else
return
SEG
(
m_points
[
index
],
m_points
[
index
+
1
],
index
);
}
/**
* Function CSegment()
*
* Returns a read-only segment referencing to the segment (index) in the line chain.
* @param index: index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means
* the last segment in the line chain)
* @return SEG referenced to given segment in the line chain
*/
const
SEG
CSegment
(
int
index
)
const
{
if
(
index
<
0
)
index
+=
SegmentCount
();
if
(
index
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
index
]),
const_cast
<
VECTOR2I
&>
(
m_points
[
0
]),
index
);
else
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
index
]),
const_cast
<
VECTOR2I
&>
(
m_points
[
index
+
1
]),
index
);
}
/**
* Function Point()
*
* Returns a reference to a given point in the line chain.
* @param index index of the point
* @return reference to the point
*/
VECTOR2I
&
Point
(
int
index
)
{
if
(
index
<
0
)
index
+=
PointCount
();
return
m_points
[
index
];
}
/**
* Function CPoint()
*
* Returns a const reference to a given point in the line chain.
* @param index index of the point
* @return const reference to the point
*/
const
VECTOR2I
&
CPoint
(
int
index
)
const
{
if
(
index
<
0
)
index
+=
PointCount
();
return
m_points
[
index
];
}
/// @copydoc SHAPE::BBox()
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
BOX2I
bbox
;
bbox
.
Compute
(
m_points
);
return
bbox
;
}
/**
* Function Collide()
*
* Checks if point aP lies closer to us than aClearance.
* @param aP the point to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found
*/
bool
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
=
0
)
const
;
/**
* Function Collide()
*
* Checks if box aBox lies closer to us than aClearance.
* @param aP the box to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found
*/
bool
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
=
0
)
const
;
/**
* Function Collide()
*
* Checks if segment aSeg lies closer to us than aClearance.
* @param aSeg the segment to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found
*/
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
;
/**
* Function Distance()
*
* Computes the minimum distance between the line chain and a point aP.
* @param aP the point
* @return minimum distance.
*/
int
Distance
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function Reverse()
*
* Reverses point order in the line chain.
* @return line chain with reversed point order (original A-B-C-D: returned D-C-B-A)
*/
const
SHAPE_LINE_CHAIN
Reverse
()
const
;
/**
* Function Length()
*
* Returns length of the line chain in Euclidean metric.
* @return length of the line chain
*/
int
Length
()
const
;
/**
* Function Append()
*
* Appends a new point at the end of the line chain.
* @param x X coordinate of the new point
* @param y Y coordinate of the new point
*/
void
Append
(
int
x
,
int
y
)
{
VECTOR2I
v
(
x
,
y
);
Append
(
v
);
}
/**
* Function Append()
*
* Appends a new point at the end of the line chain.
* @param aP the new point
*/
void
Append
(
const
VECTOR2I
&
aP
)
{
if
(
m_points
.
size
()
==
0
)
m_bbox
=
BOX2I
(
aP
,
VECTOR2I
(
0
,
0
));
if
(
m_points
.
size
()
==
0
||
CPoint
(
-
1
)
!=
aP
)
{
m_points
.
push_back
(
aP
);
m_bbox
.
Merge
(
aP
);
}
}
/**
* Function Append()
*
* Appends another line chain at the end.
* @param aOtherLine the line chain to be appended.
*/
void
Append
(
const
SHAPE_LINE_CHAIN
&
aOtherLine
)
{
if
(
aOtherLine
.
PointCount
()
==
0
)
return
;
else
if
(
PointCount
()
==
0
||
aOtherLine
.
CPoint
(
0
)
!=
CPoint
(
-
1
))
{
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
0
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
}
for
(
int
i
=
1
;
i
<
aOtherLine
.
PointCount
();
i
++
)
{
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
i
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
}
}
/**
* Function Replace()
*
* Replaces points with indices in range [start_index, end_index] with a single
* point aP.
* @param start_index start of the point range to be replaced (inclusive)
* @param end_index end of the point range to be replaced (inclusive)
* @param aP replacement point
*/
void
Replace
(
int
start_index
,
int
end_index
,
const
VECTOR2I
&
aP
);
/**
* Function Replace()
*
* Replaces points with indices in range [start_index, end_index] with the points from line chain aLine.
* @param start_index start of the point range to be replaced (inclusive)
* @param end_index end of the point range to be replaced (inclusive)
* @param aLine replacement line chain.
*/
void
Replace
(
int
start_index
,
int
end_index
,
const
SHAPE_LINE_CHAIN
&
aLine
);
/**
* Function Remove()
*
* Removes the range of points [start_index, end_index] from the line chain.
* @param start_index start of the point range to be replaced (inclusive)
* @param end_index end of the point range to be replaced (inclusive)
*/
void
Remove
(
int
start_index
,
int
end_index
);
/**
* Function Split()
*
* Inserts the point aP belonging to one of the our segments, splitting the adjacent
* segment in two.
* @param aP the point to be inserted
* @return index of the newly inserted point (or a negative value if aP does not lie on our line)
*/
int
Split
(
const
VECTOR2I
&
aP
);
/**
* Function Find()
*
* Searches for point aP.
* @param aP the point to be looked for
* @return index of the correspoinding point in the line chain or negative when not found.
*/
int
Find
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function Slice()
*
* Returns a subset of this line chain containing the [start_index, end_index] range of points.
* @param start_index start of the point range to be returned (inclusive)
* @param end_index end of the point range to be returned (inclusive)
* @return cut line chain.
*/
const
SHAPE_LINE_CHAIN
Slice
(
int
start_index
,
int
end_index
=
-
1
)
const
;
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
Intersection
&
a
,
const
Intersection
&
b
)
{
return
(
m_origin
-
a
.
p
).
EuclideanNorm
()
<
(
m_origin
-
b
.
p
).
EuclideanNorm
();
}
VECTOR2I
m_origin
;
};
/**
* Function Intersect()
*
* Finds all intersection points between our line chain and the segment aSeg.
* @param aSeg the segment chain to find intersections with
* @param aIp reference to a vector to store found intersections. Intersection points
* are sorted with increasing distances from point aSeg.a.
* @return number of intersections found
*/
int
Intersect
(
const
SEG
&
aSeg
,
Intersections
&
aIp
)
const
;
/**
* Function Intersect()
*
* Finds all intersection points between our line chain and the line chain aChain.
* @param aChain the line chain to find intersections with
* @param aIp reference to a vector to store found intersections. Intersection points
* are sorted with increasing path lengths from the starting point of aChain.
* @return number of intersections found
*/
int
Intersect
(
const
SHAPE_LINE_CHAIN
&
aChain
,
Intersections
&
aIp
)
const
;
/**
* Function PathLength()
*
* Computes the walk path length from the beginning of the line chain and
* the point aP belonging to our line.
* @return: path length in Euclidean metric or negative if aP does not belong to the line chain.
*/
int
PathLength
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function PointInside()
*
* Checks if point aP lies inside a convex polygon defined by the line chain. For closed
* shapes only.
* @param aP point to check
* @return true if the point is inside the shape (edge is not treated as being inside).
*/
bool
PointInside
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function PointOnEdge()
*
* Checks if point aP lies on an edge or vertex of the line chain.
* @param aP point to check
* @return true if the point lies on the edge.
*/
bool
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function SelfIntersecting()
*
* Checks if the line chain is self-intersecting.
* @return (optional) first found self-intersection point.
*/
const
boost
::
optional
<
Intersection
>
SelfIntersecting
()
const
;
/**
* Function Simplify()
*
* Simplifies the line chain by removing colinear adjacent segments and duplicate vertices.
* @return reference to self.
*/
SHAPE_LINE_CHAIN
&
Simplify
();
/**
* Function NearestPoint()
*
* Finds a point on the line chain that is closest to point aP.
* @return the nearest point.
*/
const
VECTOR2I
NearestPoint
(
const
VECTOR2I
&
aP
)
const
;
/// @copydoc SHAPE::Format()
const
std
::
string
Format
()
const
;
bool
operator
!=
(
const
SHAPE_LINE_CHAIN
&
rhs
)
const
{
if
(
PointCount
()
!=
rhs
.
PointCount
())
return
true
;
for
(
int
i
=
0
;
i
<
PointCount
();
i
++
)
if
(
CPoint
(
i
)
!=
rhs
.
CPoint
(
i
)
)
return
true
;
return
false
;
}
private
:
/// array of vertices
std
::
vector
<
VECTOR2I
>
m_points
;
/// is the line chain closed?
bool
m_closed
;
/// cached bounding box
BOX2I
m_bbox
;
};
#endif // __SHAPE_LINE_CHAIN
include/geometry/shape_rect.h
0 → 100644
View file @
6ac8188f
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __SHAPE_RECT_H
#define __SHAPE_RECT_H
#include <geometry/shape.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_circle.h>
#include <geometry/seg.h>
class
SHAPE_RECT
:
public
SHAPE
{
public
:
/**
* Constructor
* Creates an empty (0-sized) rectangle
*/
SHAPE_RECT
()
:
SHAPE
(
SH_RECT
),
m_w
(
0
),
m_h
(
0
)
{};
/**
* Constructor
* Creates a rectangle defined by top-left corner (x0, y0), width w and height h.
*/
SHAPE_RECT
(
int
x0
,
int
y0
,
int
w
,
int
h
)
:
SHAPE
(
SH_RECT
),
m_p0
(
x0
,
y0
),
m_w
(
w
),
m_h
(
h
)
{};
/**
* Constructor
* Creates a rectangle defined by top-left corner p0, width w and height h.
*/
SHAPE_RECT
(
const
VECTOR2I
&
p0
,
int
w
,
int
h
)
:
SHAPE
(
SH_RECT
),
m_p0
(
p0
),
m_w
(
w
),
m_h
(
h
)
{};
/// @copydoc SHAPE::BBox()
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
BOX2I
bbox
(
VECTOR2I
(
m_p0
.
x
-
aClearance
,
m_p0
.
y
-
aClearance
),
VECTOR2I
(
m_w
+
2
*
aClearance
,
m_h
+
2
*
aClearance
));
//printf("bb : %s\n",bbox.Format().c_str());
return
bbox
;
}
/**
* Function Diagonal()
*
* Returns length of the diagonal of the rectangle
* @return diagonal length
*/
int
Diagonal
()
const
{
return
VECTOR2I
(
m_w
,
m_h
).
EuclideanNorm
();
}
/// @copydoc SHAPE::Collide()
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
{
//VECTOR2I pmin = VECTOR2I(std::min(aSeg.a.x, aSeg.b.x), std::min(aSeg.a.y, aSeg.b.y));
//VECTOR2I pmax = VECTOR2I(std::max(aSeg.a.x, aSeg.b.x), std::max(aSeg.a.y, aSeg.b.y));
//BOX2I r(pmin, VECTOR2I(pmax.x - pmin.x, pmax.y - pmin.y));
//if (BBox(0).SquaredDistance(r) > aClearance * aClearance)
// return false;
if
(
BBox
(
0
).
Contains
(
aSeg
.
a
)
||
BBox
(
0
).
Contains
(
aSeg
.
b
))
return
true
;
VECTOR2I
vts
[]
=
{
VECTOR2I
(
m_p0
.
x
,
m_p0
.
y
),
VECTOR2I
(
m_p0
.
x
,
m_p0
.
y
+
m_h
),
VECTOR2I
(
m_p0
.
x
+
m_w
,
m_p0
.
y
+
m_h
),
VECTOR2I
(
m_p0
.
x
+
m_w
,
m_p0
.
y
),
VECTOR2I
(
m_p0
.
x
,
m_p0
.
y
)
};
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
SEG
s
(
vts
[
i
],
vts
[
i
+
1
],
i
);
if
(
s
.
Distance
(
aSeg
)
<=
aClearance
)
return
true
;
}
return
false
;
};
/**
* Function GetPosition()
*
* @return top-left corner of the rectangle
*/
const
VECTOR2I
&
GetPosition
()
const
{
return
m_p0
;
}
/**
* Function GetSize()
*
* @return size of the rectangle
*/
const
VECTOR2I
GetSize
()
const
{
return
VECTOR2I
(
m_w
,
m_h
);
}
/**
* Function GetWidth()
*
* @return width of the rectangle
*/
const
int
GetWidth
()
const
{
return
m_w
;
}
/**
* Function GetHeight()
*
* @return height of the rectangle
*/
const
int
GetHeight
()
const
{
return
m_h
;
}
private
:
///> Top-left corner
VECTOR2I
m_p0
;
///> Width
int
m_w
;
///> Height
int
m_h
;
};
#endif // __SHAPE_RECT_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