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
3f320e4d
Commit
3f320e4d
authored
Sep 27, 2013
by
Maciej Suminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some more comments and code formatting.
parent
6e0c7a93
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
852 additions
and
538 deletions
+852
-538
drawpanel_gal.cpp
common/drawpanel_gal.cpp
+0
-11
seg.cpp
common/geometry/seg.cpp
+63
-61
shape_collisions.cpp
common/geometry/shape_collisions.cpp
+71
-48
shape_index.cpp
common/geometry/shape_index.cpp
+0
-1
shape_line_chain.cpp
common/geometry/shape_line_chain.cpp
+225
-170
action_manager.cpp
common/tool/action_manager.cpp
+4
-3
context_menu.cpp
common/tool/context_menu.cpp
+13
-1
tool_dispatcher.cpp
common/tool/tool_dispatcher.cpp
+26
-12
tool_event.cpp
common/tool/tool_event.cpp
+1
-1
tool_manager.cpp
common/tool/tool_manager.cpp
+3
-7
shape_index.h
include/geometry/shape_index.h
+75
-59
shape_line_chain.h
include/geometry/shape_line_chain.h
+124
-114
action_manager.h
include/tool/action_manager.h
+11
-4
context_menu.h
include/tool/context_menu.h
+53
-5
tool_base.h
include/tool/tool_base.h
+53
-6
tool_dispatcher.h
include/tool/tool_dispatcher.h
+38
-3
tool_event.h
include/tool/tool_event.h
+53
-7
tool_interactive.h
include/tool/tool_interactive.h
+12
-8
move_tool.cpp
pcbnew/tools/move_tool.cpp
+11
-5
selection_area.h
pcbnew/tools/selection_area.h
+1
-0
selection_tool.cpp
pcbnew/tools/selection_tool.cpp
+15
-12
No files found.
common/drawpanel_gal.cpp
View file @
3f320e4d
...
...
@@ -121,11 +121,6 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
m_pendingRefresh
=
false
;
m_lastRefresh
=
wxGetLocalTimeMillis
();
#ifdef __WXDEBUG__
prof_counter
time
;
prof_start
(
&
time
,
false
);
#endif
/* __WXDEBUG__ */
m_gal
->
BeginDrawing
();
m_gal
->
SetBackgroundColor
(
KiGfx
::
COLOR4D
(
0.0
,
0.0
,
0.0
,
1.0
)
);
m_gal
->
ClearScreen
();
...
...
@@ -138,12 +133,6 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
m_gal
->
DrawCursor
(
m_viewControls
->
GetCursorPosition
()
);
m_gal
->
EndDrawing
();
#ifdef __WXDEBUG__
prof_end
(
&
time
);
wxLogDebug
(
wxT
(
"EDA_DRAW_PANEL_GAL::Refresh: %.0f ms (%.0f fps)"
),
static_cast
<
double
>
(
time
.
value
)
/
1000.0
,
1000000.0
/
static_cast
<
double
>
(
time
.
value
)
);
#endif
/* __WXDEBUG__ */
}
...
...
common/geometry/seg.cpp
View file @
3f320e4d
...
...
@@ -25,126 +25,128 @@
#include <geometry/seg.h>
template
<
typename
T
>
int
sgn
(
T
val
)
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
)
);
template
<
typename
T
>
int
sgn
(
T
val
)
{
return
(
T
(
0
)
<
val
)
-
(
val
<
T
(
0
)
);
}
bool
SEG
::
PointCloserThan
(
const
VECTOR2I
&
aP
,
int
dist
)
const
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
);
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
;
return
(
aP
-
a
).
SquaredEuclideanNorm
()
<
dist_sq
;
else
if
(
t
>=
l_squared
)
return
(
aP
-
b
).
SquaredEuclideanNorm
()
<
dist_sq
;
return
(
aP
-
b
).
SquaredEuclideanNorm
()
<
dist_sq
;
int
dxdy
=
abs
(
d
.
x
)
-
abs
(
d
.
y
);
int
dxdy
=
abs
(
d
.
x
)
-
abs
(
d
.
y
);
if
(
(
dxdy
>=
-
1
&&
dxdy
<=
1
)
||
abs
(
d
.
x
)
<=
1
||
abs
(
d
.
y
)
<=
1
)
if
(
(
dxdy
>=
-
1
&&
dxdy
<=
1
)
||
abs
(
d
.
x
)
<=
1
||
abs
(
d
.
y
)
<=
1
)
{
int
ca
=
-
sgn
(
d
.
y
);
int
cb
=
sgn
(
d
.
x
);
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
)
if
(
ca
&&
cb
)
num
>>=
1
;
if
(
num
>
(
dist_sq
+
100
)
)
if
(
num
>
(
dist_sq
+
100
)
)
return
false
;
else
if
(
num
<
(
dist_sq
-
100
)
)
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
);
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
;
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
;
// 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
);
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
);
ecoord
d
=
f
.
Cross
(
e
);
ecoord
p
=
f
.
Cross
(
ac
);
ecoord
q
=
e
.
Cross
(
ac
);
if
(
d
==
0
)
if
(
d
==
0
)
return
OPT_VECTOR2I
();
if
(
!
aLines
&&
d
>
0
&&
(
q
<
0
||
q
>
d
||
p
<
0
||
p
>
d
)
)
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
)
)
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
)
)
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
)
);
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
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
);
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
)
)
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
);
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
);
}
bool
SEG
::
Contains
(
const
VECTOR2I
&
aP
)
const
{
return
PointCloserThan
(
aP
,
1
);
}
common/geometry/shape_collisions.cpp
View file @
3f320e4d
...
...
@@ -31,7 +31,8 @@
typedef
VECTOR2I
::
extended_type
ecoord
;
static
inline
bool
Collide
(
const
SHAPE_CIRCLE
&
a
,
const
SHAPE_CIRCLE
&
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
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
;
...
...
@@ -44,12 +45,13 @@ static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_CIRCLE& b, int cl
return
false
;
if
(
needMTV
)
aMTV
=
delta
.
Resize
(
sqrt
(
abs
(
min_dist_sq
-
dist_sq
))
+
1
);
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
)
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
();
...
...
@@ -58,7 +60,7 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
const
ecoord
min_dist
=
clearance
+
r
;
const
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
if
(
a
.
BBox
(
0
).
Contains
(
c
)
)
if
(
a
.
BBox
(
0
).
Contains
(
c
)
)
return
true
;
const
VECTOR2I
vts
[]
=
{
...
...
@@ -71,73 +73,77 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
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
);
bool
inside
=
c
.
x
>=
p0
.
x
&&
c
.
x
<=
(
p0
.
x
+
size
.
x
)
&&
c
.
y
>=
p0
.
y
&&
c
.
y
<=
(
p0
.
y
+
size
.
y
);
if
(
!
inside
)
if
(
!
inside
)
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
const
SEG
seg
(
vts
[
i
],
vts
[
i
+
1
]
);
ecoord
dist_sq
=
seg
.
SquaredDistance
(
c
);
const
SEG
seg
(
vts
[
i
],
vts
[
i
+
1
]
);
ecoord
dist_sq
=
seg
.
SquaredDistance
(
c
);
if
(
dist_sq
<
min_dist_sq
)
if
(
dist_sq
<
min_dist_sq
)
{
if
(
!
needMTV
)
if
(
!
needMTV
)
return
true
;
else
{
nearest
=
seg
.
NearestPoint
(
c
);
nearest
=
seg
.
NearestPoint
(
c
);
nearest_seg_dist_sq
=
dist_sq
;
}
}
}
}
if
(
nearest_seg_dist_sq
>=
min_dist_sq
&&
!
inside
)
if
(
nearest_seg_dist_sq
>=
min_dist_sq
&&
!
inside
)
return
false
;
VECTOR2I
delta
=
c
-
nearest
;
if
(
!
needMTV
)
if
(
!
needMTV
)
return
true
;
if
(
inside
)
aMTV
=
-
delta
.
Resize
(
sqrt
(
abs
(
r
*
r
+
nearest_seg_dist_sq
)
+
1
)
);
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
)
);
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
)
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
++
)
for
(
int
s
=
0
;
s
<
b
.
SegmentCount
();
s
++
)
{
if
(
a
.
Collide
(
b
.
CSegment
(
s
),
clearance
)
)
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
)
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
)
)
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
)
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
++
)
for
(
int
s
=
0
;
s
<
b
.
SegmentCount
();
s
++
)
{
SEG
seg
=
b
.
CSegment
(
s
);
if
(
a
.
Collide
(
seg
,
clearance
)
)
SEG
seg
=
b
.
CSegment
(
s
);
if
(
a
.
Collide
(
seg
,
clearance
)
)
return
true
;
}
...
...
@@ -145,66 +151,83 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int
}
bool
CollideShapes
(
const
SHAPE
*
a
,
const
SHAPE
*
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
bool
CollideShapes
(
const
SHAPE
*
a
,
const
SHAPE
*
b
,
int
clearance
,
bool
needMTV
,
VECTOR2I
&
aMTV
)
{
switch
(
a
->
Type
()
)
switch
(
a
->
Type
()
)
{
case
SH_RECT
:
switch
(
b
->
Type
()
)
switch
(
b
->
Type
()
)
{
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
a
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
b
),
clearance
,
needMTV
,
aMTV
);
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
);
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
()
)
switch
(
b
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
b
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
a
),
clearance
,
needMTV
,
aMTV
);
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
);
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
);
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
()
)
switch
(
b
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
b
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
a
),
clearance
,
needMTV
,
aMTV
);
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
);
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
);
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
);
assert
(
unsupported_collision
==
false
);
return
false
;
}
bool
SHAPE
::
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
,
VECTOR2I
&
aMTV
)
const
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
bool
SHAPE
::
Collide
(
const
SHAPE
*
aShape
,
int
aClerance
)
const
{
VECTOR2I
dummy
;
return
CollideShapes
(
this
,
aShape
,
aClerance
,
false
,
dummy
);
return
CollideShapes
(
this
,
aShape
,
aClerance
,
false
,
dummy
);
}
common/geometry/shape_index.cpp
View file @
3f320e4d
...
...
@@ -30,4 +30,3 @@ const SHAPE* shapeFunctor( SHAPE* aItem )
{
return
aItem
;
}
common/geometry/shape_line_chain.cpp
View file @
3f320e4d
...
...
@@ -28,43 +28,46 @@
using
namespace
std
;
using
boost
::
optional
;
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
)
const
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
)
const
{
assert
(
false
);
assert
(
false
);
return
false
;
}
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
)
const
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
)
const
{
assert
(
false
);
assert
(
false
);
return
false
;
}
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
SEG
&
aSeg
,
int
aClearance
)
const
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
SEG
&
aSeg
,
int
aClearance
)
const
{
BOX2I
box_a
(
aSeg
.
a
,
aSeg
.
b
-
aSeg
.
a
);
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
++
)
for
(
int
i
=
0
;
i
<
SegmentCount
()
;
i
++
)
{
const
SEG
&
s
=
CSegment
(
i
);
BOX2I
box_b
(
s
.
a
,
s
.
b
-
s
.
a
);
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
(
d
<
dist_sq
)
{
if
(
s
.
Collide
(
aSeg
,
aClearance
)
)
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
()
);
SHAPE_LINE_CHAIN
a
(
*
this
);
reverse
(
a
.
m_points
.
begin
(),
a
.
m_points
.
end
()
);
a
.
m_closed
=
m_closed
;
return
a
;
...
...
@@ -74,176 +77,195 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
int
SHAPE_LINE_CHAIN
::
Length
()
const
{
int
l
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
l
+=
CSegment
(
i
).
Length
();
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
)
void
SHAPE_LINE_CHAIN
::
Replace
(
int
aStartIndex
,
int
aEndIndex
,
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
;
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
if
(
aStartIndex
==
aEndIndex
)
m_points
[
aStartIndex
]
=
aP
;
else
{
m_points
.
erase
(
m_points
.
begin
()
+
aStartIndex
+
1
,
m_points
.
begin
()
+
aEndIndex
+
1
);
m_points
[
aStartIndex
]
=
aP
;
}
}
void
SHAPE_LINE_CHAIN
::
Replace
(
int
start_index
,
int
end_index
,
const
SHAPE_LINE_CHAIN
&
aLine
)
void
SHAPE_LINE_CHAIN
::
Replace
(
int
aStartIndex
,
int
aEndIndex
,
const
SHAPE_LINE_CHAIN
&
aLine
)
{
if
(
end_index
<
0
)
end_i
ndex
+=
PointCount
();
if
(
start_index
<
0
)
start_i
ndex
+=
PointCount
();
if
(
aEndIndex
<
0
)
aEndI
ndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartI
ndex
+=
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
()
);
m_points
.
erase
(
m_points
.
begin
()
+
aStartIndex
,
m_points
.
begin
()
+
aEndIndex
+
1
);
m_points
.
insert
(
m_points
.
begin
()
+
aStartIndex
,
aLine
.
m_points
.
begin
(),
aLine
.
m_points
.
end
()
);
}
void
SHAPE_LINE_CHAIN
::
Remove
(
int
start_index
,
int
end_index
)
void
SHAPE_LINE_CHAIN
::
Remove
(
int
aStartIndex
,
int
aEndIndex
)
{
if
(
end_i
ndex
<
0
)
end_i
ndex
+=
PointCount
();
if
(
start_i
ndex
<
0
)
start_i
ndex
+=
PointCount
();
if
(
aEndI
ndex
<
0
)
aEndI
ndex
+=
PointCount
();
if
(
aStartI
ndex
<
0
)
aStartI
ndex
+=
PointCount
();
m_points
.
erase
(
m_points
.
begin
()
+
start_index
,
m_points
.
begin
()
+
end_index
+
1
);
m_points
.
erase
(
m_points
.
begin
()
+
aStartIndex
,
m_points
.
begin
()
+
aEndIndex
+
1
);
}
int
SHAPE_LINE_CHAIN
::
Distance
(
const
VECTOR2I
&
aP
)
const
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
));
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
SHAPE_LINE_CHAIN
::
Split
(
const
VECTOR2I
&
aP
)
{
int
ii
=
-
1
;
int
min_dist
=
2
;
ii
=
Find
(
aP
);
ii
=
Find
(
aP
);
if
(
ii
>=
0
)
if
(
ii
>=
0
)
return
ii
;
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
{
const
SEG
seg
=
CSegment
(
s
);
int
dist
=
seg
.
Distance
(
aP
);
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
)
if
(
dist
<
min_dist
&&
seg
.
a
!=
aP
&&
seg
.
b
!=
aP
)
{
min_dist
=
dist
;
ii
=
s
;
}
}
if
(
ii
>=
0
)
if
(
ii
>=
0
)
{
m_points
.
insert
(
m_points
.
begin
()
+
ii
+
1
,
aP
);
m_points
.
insert
(
m_points
.
begin
()
+
ii
+
1
,
aP
);
return
ii
+
1
;
}
return
-
1
;
}
int
SHAPE_LINE_CHAIN
::
Find
(
const
VECTOR2I
&
aP
)
const
int
SHAPE_LINE_CHAIN
::
Find
(
const
VECTOR2I
&
aP
)
const
{
for
(
int
s
=
0
;
s
<
PointCount
();
s
++
)
if
(
CPoint
(
s
)
==
aP
)
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
const
SHAPE_LINE_CHAIN
SHAPE_LINE_CHAIN
::
Slice
(
int
aStartIndex
,
int
aEndIndex
)
const
{
SHAPE_LINE_CHAIN
rv
;
if
(
end_index
<
0
)
end_index
+=
PointCount
();
if
(
start_index
<
0
)
start_index
+=
PointCount
();
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
for
(
int
i
=
aStartIndex
;
i
<=
aEndIndex
;
i
++
)
rv
.
Append
(
m_points
[
i
]
);
for
(
int
i
=
start_index
;
i
<=
end_index
;
i
++
)
rv
.
Append
(
m_points
[
i
]);
return
rv
;
}
struct
compareOriginDistance
{
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
SHAPE_LINE_CHAIN
::
Intersection
&
a
,
const
SHAPE_LINE_CHAIN
::
Intersection
&
b
)
bool
operator
()(
const
SHAPE_LINE_CHAIN
::
Intersection
&
aA
,
const
SHAPE_LINE_CHAIN
::
Intersection
&
aB
)
{
return
(
m_origin
-
a
.
p
).
EuclideanNorm
()
<
(
m_origin
-
b
.
p
).
EuclideanNorm
();
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
p
).
EuclideanNorm
();
}
VECTOR2I
m_origin
;
};
int
SHAPE_LINE_CHAIN
::
Intersect
(
const
SEG
&
aSeg
,
Intersections
&
aIp
)
const
int
SHAPE_LINE_CHAIN
::
Intersect
(
const
SEG
&
aSeg
,
Intersections
&
aIp
)
const
{
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
{
OPT_VECTOR2I
p
=
CSegment
(
s
).
Intersect
(
aSeg
);
if
(
p
)
OPT_VECTOR2I
p
=
CSegment
(
s
).
Intersect
(
aSeg
);
if
(
p
)
{
Intersection
is
;
is
.
our
=
CSegment
(
s
);
is
.
our
=
CSegment
(
s
);
is
.
their
=
aSeg
;
is
.
p
=
*
p
;
aIp
.
push_back
(
is
);
aIp
.
push_back
(
is
);
}
}
compareOriginDistance
comp
(
aSeg
.
a
);
sort
(
aIp
.
begin
(),
aIp
.
end
(),
comp
);
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
int
SHAPE_LINE_CHAIN
::
Intersect
(
const
SHAPE_LINE_CHAIN
&
aChain
,
Intersections
&
aIp
)
const
{
BOX2I
bb_other
=
aChain
.
BBox
();
BOX2I
bb_other
=
aChain
.
BBox
();
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
{
const
SEG
&
a
=
CSegment
(
s1
);
const
BOX2I
bb_cur
(
a
.
a
,
a
.
b
-
a
.
a
);
const
SEG
&
a
=
CSegment
(
s1
);
const
BOX2I
bb_cur
(
a
.
a
,
a
.
b
-
a
.
a
);
if
(
!
bb_other
.
Intersects
(
bb_cur
)
)
if
(
!
bb_other
.
Intersects
(
bb_cur
)
)
continue
;
for
(
int
s2
=
0
;
s2
<
aChain
.
SegmentCount
();
s2
++
)
for
(
int
s2
=
0
;
s2
<
aChain
.
SegmentCount
();
s2
++
)
{
const
SEG
&
b
=
aChain
.
CSegment
(
s2
);
const
SEG
&
b
=
aChain
.
CSegment
(
s2
);
Intersection
is
;
if
(
a
.
Collinear
(
b
))
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
{
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
);
OPT_VECTOR2I
p
=
a
.
Intersect
(
b
);
if
(
p
)
if
(
p
)
{
is
.
p
=
*
p
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
aIp
.
push_back
(
is
);
}
}
}
...
...
@@ -251,130 +273,152 @@ BOX2I bb_other = aChain.BBox();
return
aIp
.
size
();
for
(
int
s1
=
0
;
s1
<
SegmentCount
();
s1
++
)
for
(
int
s2
=
0
;
s2
<
aChain
.
SegmentCount
();
s2
++
)
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
);
const
SEG
&
a
=
CSegment
(
s1
);
const
SEG
&
b
=
aChain
.
CSegment
(
s2
);
OPT_VECTOR2I
p
=
a
.
Intersect
(
b
);
Intersection
is
;
if
(
p
)
if
(
p
)
{
is
.
p
=
*
p
;
is
.
our
=
a
;
is
.
their
=
b
;
aIp
.
push_back
(
is
);
}
else
if
(
a
.
Collinear
(
b
))
aIp
.
push_back
(
is
);
}
else
if
(
a
.
Collinear
(
b
)
)
{
if
(
a
.
a
!=
b
.
a
&&
a
.
a
!=
b
.
b
&&
b
.
Contains
(
a
.
a
)
)
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
);
aIp
.
push_back
(
is
);
}
else
if
(
a
.
b
!=
b
.
a
&&
a
.
b
!=
b
.
b
&&
b
.
Contains
(
a
.
b
)
)
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
);
aIp
.
push_back
(
is
);
}
}
}
}
return
aIp
.
size
();
}
int
SHAPE_LINE_CHAIN
::
PathLength
(
const
VECTOR2I
&
aP
)
const
int
SHAPE_LINE_CHAIN
::
PathLength
(
const
VECTOR2I
&
aP
)
const
{
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
seg
=
CSegment
(
i
);
int
d
=
seg
.
Distance
(
aP
);
if
(
d
<=
1
)
const
SEG
seg
=
CSegment
(
i
);
int
d
=
seg
.
Distance
(
aP
);
if
(
d
<=
1
)
{
sum
+=
(
aP
-
seg
.
a
).
EuclideanNorm
();
sum
+=
(
aP
-
seg
.
a
).
EuclideanNorm
();
return
sum
;
}
else
sum
+=
seg
.
Length
();
}
return
-
1
;
}
bool
SHAPE_LINE_CHAIN
::
PointInside
(
const
VECTOR2I
&
aP
)
const
bool
SHAPE_LINE_CHAIN
::
PointInside
(
const
VECTOR2I
&
aP
)
const
{
if
(
!
m_closed
||
SegmentCount
()
<
3
)
if
(
!
m_closed
||
SegmentCount
()
<
3
)
return
false
;
int
cur
=
CSegment
(
0
).
Side
(
aP
);
if
(
cur
==
0
)
int
cur
=
CSegment
(
0
).
Side
(
aP
);
if
(
cur
==
0
)
return
false
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
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!
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
)
if
(
s
.
Side
(
aP
)
!=
cur
)
return
false
;
}
}
return
true
;
}
bool
SHAPE_LINE_CHAIN
::
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
bool
SHAPE_LINE_CHAIN
::
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
{
if
(
SegmentCount
()
<
1
)
if
(
SegmentCount
()
<
1
)
return
m_points
[
0
]
==
aP
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
s
=
CSegment
(
i
);
if
(
s
.
a
==
aP
||
s
.
b
==
aP
)
const
SEG
s
=
CSegment
(
i
);
if
(
s
.
a
==
aP
||
s
.
b
==
aP
)
return
true
;
if
(
s
.
Distance
(
aP
)
<=
1
)
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
++
)
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
)
)
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
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
s2a
;
return
is
;
}
else
if
(
CSegment
(
s1
).
Contains
(
s2b
))
{
}
else
if
(
CSegment
(
s1
).
Contains
(
s2b
)
)
{
Intersection
is
;
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
s2b
;
return
is
;
}
else
{
OPT_VECTOR2I
p
=
CSegment
(
s1
).
Intersect
(
CSegment
(
s2
),
true
);
}
else
{
OPT_VECTOR2I
p
=
CSegment
(
s1
).
Intersect
(
CSegment
(
s2
),
true
);
if
(
p
)
if
(
p
)
{
Intersection
is
;
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
our
=
CSegment
(
s1
);
is
.
their
=
CSegment
(
s2
);
is
.
p
=
*
p
;
return
is
;
}
}
}
}
return
optional
<
Intersection
>
();
}
...
...
@@ -383,12 +427,15 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
{
vector
<
VECTOR2I
>
pts_unique
;
if
(
PointCount
()
<
2
)
if
(
PointCount
()
<
2
)
{
return
*
this
;
}
else
if
(
PointCount
()
==
2
)
{
if
(
m_points
[
0
]
==
m_points
[
1
])
m_points
.
erase
(
m_points
.
end
());
}
else
if
(
PointCount
()
==
2
)
{
if
(
m_points
[
0
]
==
m_points
[
1
]
)
m_points
.
erase
(
m_points
.
end
()
);
return
*
this
;
}
...
...
@@ -398,10 +445,11 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
// 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
));
int
j
=
i
+
1
;
while
(
j
<
np
&&
CPoint
(
i
)
==
CPoint
(
j
)
)
j
++
;
pts_unique
.
push_back
(
CPoint
(
i
)
);
i
=
j
;
}
...
...
@@ -410,56 +458,63 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
i
=
0
;
// stage 1: eliminate collinear segments
while
(
i
<
np
-
2
)
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
)
while
(
n
<
np
-
2
&&
SEG
(
p0
,
p1
).
LineDistance
(
pts_unique
[
n
+
2
]
)
<=
1
)
n
++
;
m_points
.
push_back
(
p0
);
if
(
n
>
i
)
m_points
.
push_back
(
p0
);
if
(
n
>
i
)
i
=
n
;
if
(
n
==
np
)
if
(
n
==
np
)
{
m_points
.
push_back
(
pts_unique
[
n
-
1
]
);
m_points
.
push_back
(
pts_unique
[
n
-
1
]
);
return
*
this
;
}
i
++
;
i
++
;
}
if
(
np
>
1
)
m_points
.
push_back
(
pts_unique
[
np
-
2
]);
m_points
.
push_back
(
pts_unique
[
np
-
1
]);
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
const
VECTOR2I
SHAPE_LINE_CHAIN
::
NearestPoint
(
const
VECTOR2I
&
aP
)
const
{
int
min_d
=
INT_MAX
;
int
nearest
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
()
;
i
++
)
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
{
int
d
=
CSegment
(
i
).
Distance
(
aP
);
int
d
=
CSegment
(
i
).
Distance
(
aP
);
if
(
d
<
min_d
)
{
min_d
=
d
;
nearest
=
i
;
}
}
return
CSegment
(
nearest
).
NearestPoint
(
aP
);
return
CSegment
(
nearest
).
NearestPoint
(
aP
);
}
const
string
SHAPE_LINE_CHAIN
::
Format
()
const
{
stringstream
ss
;
ss
<<
m_points
.
size
()
<<
" "
<<
(
m_closed
?
1
:
0
)
<<
" "
;
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() << " ";
for
(
int
i
=
0
;
i
<
PointCount
();
i
++
)
ss
<<
m_points
[
i
].
x
<<
" "
<<
m_points
[
i
].
y
<<
" "
;
// Format() << " ";
return
ss
.
str
();
}
common/tool/action_manager.cpp
View file @
3f320e4d
...
...
@@ -52,8 +52,9 @@ void ACTION_MANAGER::RegisterAction( TOOL_ACTION* aAction )
void
ACTION_MANAGER
::
UnregisterAction
(
TOOL_ACTION
*
aAction
)
{
// Indicate that
we
no longer care about the object
// Indicate that
the ACTION_MANAGER
no longer care about the object
aAction
->
setActionMgr
(
NULL
);
aAction
->
setId
(
-
1
);
m_actionNameIndex
.
erase
(
aAction
->
m_name
);
m_actionIdIndex
.
erase
(
aAction
->
m_id
);
...
...
@@ -75,7 +76,7 @@ bool ACTION_MANAGER::RunAction( const std::string& aActionName ) const
std
::
map
<
std
::
string
,
TOOL_ACTION
*>::
const_iterator
it
=
m_actionNameIndex
.
find
(
aActionName
);
if
(
it
==
m_actionNameIndex
.
end
()
)
return
false
;
return
false
;
// no action with given name found
runAction
(
it
->
second
);
...
...
@@ -88,7 +89,7 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const
std
::
map
<
int
,
TOOL_ACTION
*>::
const_iterator
it
=
m_actionHotKeys
.
find
(
aHotKey
);
if
(
it
==
m_actionHotKeys
.
end
()
)
return
false
;
return
false
;
// no appropriate action found for the hotkey
runAction
(
it
->
second
);
...
...
common/tool/context_menu.cpp
View file @
3f320e4d
...
...
@@ -62,13 +62,15 @@ CONTEXT_MENU::CONTEXT_MENU( const CONTEXT_MENU& aMenu ) :
wxEmptyString
,
wxITEM_NORMAL
)
);
}
// Copy tool actions that are available to choose from menu
// Copy tool actions that are available to choose from
context
menu
m_toolActions
=
aMenu
.
m_toolActions
;
}
void
CONTEXT_MENU
::
SetTitle
(
const
wxString
&
aTitle
)
{
// TODO handle an empty string (remove title and separator)
// Unfortunately wxMenu::SetTitle() does nothing..
if
(
m_titleSet
)
{
...
...
@@ -85,12 +87,18 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle )
void
CONTEXT_MENU
::
Add
(
const
wxString
&
aLabel
,
int
aId
)
{
#ifdef DEBUG
if
(
m_menu
.
FindItem
(
aId
)
!=
NULL
)
wxLogWarning
(
wxT
(
"Adding more than one menu entry with the same ID may result in"
"undefined behaviour"
)
);
#endif
m_menu
.
Append
(
new
wxMenuItem
(
&
m_menu
,
aId
,
aLabel
,
wxEmptyString
,
wxITEM_NORMAL
)
);
}
void
CONTEXT_MENU
::
Add
(
const
TOOL_ACTION
&
aAction
)
{
/// ID numbers for tool actions need to have a value higher than m_actionId
int
id
=
m_actionId
+
aAction
.
GetId
();
wxString
menuEntry
;
...
...
@@ -110,6 +118,7 @@ void CONTEXT_MENU::Clear()
{
m_titleSet
=
false
;
// Remove all the entries from context menu
for
(
unsigned
i
=
0
;
i
<
m_menu
.
GetMenuItemCount
();
++
i
)
m_menu
.
Destroy
(
m_menu
.
FindItemByPosition
(
0
)
);
...
...
@@ -144,15 +153,18 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
if
(
type
==
wxEVT_MENU_HIGHLIGHT
)
evt
=
TOOL_EVENT
(
TC_Command
,
TA_ContextMenuUpdate
,
aEvent
.
GetId
()
);
else
if
(
type
==
wxEVT_COMMAND_MENU_SELECTED
)
{
if
(
aEvent
.
GetId
()
>
m_actionId
)
{
// Handling TOOL_ACTIONs
if
(
m_menu
->
m_toolActions
.
count
(
aEvent
.
GetId
()
)
==
1
)
evt
=
m_menu
->
m_toolActions
[
aEvent
.
GetId
()]
->
GetEvent
();
}
else
{
// Handling common menu entries
evt
=
TOOL_EVENT
(
TC_Command
,
TA_ContextMenuChoice
,
aEvent
.
GetId
()
);
}
}
...
...
common/tool/tool_dispatcher.cpp
View file @
3f320e4d
...
...
@@ -42,28 +42,41 @@ using boost::optional;
struct
TOOL_DISPATCHER
::
ButtonState
{
ButtonState
(
TOOL_MouseButtons
aButton
,
const
wxEventType
&
aDownEvent
,
const
wxEventType
&
aUpEvent
,
bool
aTriggerMenu
=
false
)
:
const
wxEventType
&
aUpEvent
)
:
button
(
aButton
),
downEvent
(
aDownEvent
),
upEvent
(
aUpEvent
),
triggerContextMenu
(
aTriggerMenu
)
upEvent
(
aUpEvent
)
{};
///> Flag indicating that dragging is active for the given button.
bool
dragging
;
///> Flag indicating that the given button is pressed.
bool
pressed
;
///> Point where dragging has started (in world coordinates).
VECTOR2D
dragOrigin
;
///> Point where click event has occurred.
VECTOR2D
downPosition
;
///> Difference between drag origin point and current mouse position (expressed as distance in
///> pixels).
double
dragMaxDelta
;
///> Determines the mouse button for which information are stored.
TOOL_MouseButtons
button
;
///> The type of wxEvent that determines mouse button press.
wxEventType
downEvent
;
///> The type of wxEvent that determines mouse button release.
wxEventType
upEvent
;
bool
triggerContextMenu
;
///> Time stamp for the last mouse button press event.
wxLongLong
downTimestamp
;
///> Restores initial state.
void
Reset
()
{
dragging
=
false
;
...
...
@@ -76,7 +89,7 @@ TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditF
m_toolMgr
(
aToolMgr
),
m_editFrame
(
aEditFrame
)
{
m_buttons
.
push_back
(
new
ButtonState
(
MB_Left
,
wxEVT_LEFT_DOWN
,
wxEVT_LEFT_UP
)
);
m_buttons
.
push_back
(
new
ButtonState
(
MB_Right
,
wxEVT_RIGHT_DOWN
,
wxEVT_RIGHT_UP
,
true
)
);
m_buttons
.
push_back
(
new
ButtonState
(
MB_Right
,
wxEVT_RIGHT_DOWN
,
wxEVT_RIGHT_UP
)
);
m_buttons
.
push_back
(
new
ButtonState
(
MB_Middle
,
wxEVT_MIDDLE_DOWN
,
wxEVT_MIDDLE_UP
)
);
ResetState
();
...
...
@@ -124,14 +137,14 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
wxEventType
type
=
aEvent
.
GetEventType
();
optional
<
TOOL_EVENT
>
evt
;
bool
isClick
=
false
;
bool
up
=
type
==
st
->
upEvent
;
bool
down
=
type
==
st
->
downEvent
;
int
mods
=
decodeModifiers
(
static_cast
<
wxMouseEvent
*>
(
&
aEvent
)
);
int
args
=
st
->
button
|
mods
;
if
(
down
)
if
(
down
)
// Handle mouse button press
{
st
->
downTimestamp
=
wxGetLocalTimeMillis
();
st
->
dragOrigin
=
m_lastMousePos
;
...
...
@@ -140,7 +153,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
st
->
pressed
=
true
;
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseDown
,
args
);
}
else
if
(
up
)
else
if
(
up
)
// Handle mouse button release
{
st
->
pressed
=
false
;
...
...
@@ -148,6 +161,7 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
{
wxLongLong
t
=
wxGetLocalTimeMillis
();
// Determine if it was just a single click or beginning of dragging
if
(
t
-
st
->
downTimestamp
<
DragTimeThreshold
&&
st
->
dragMaxDelta
<
DragDistanceThreshold
)
isClick
=
true
;
...
...
@@ -156,7 +170,6 @@ bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMoti
}
else
isClick
=
true
;
if
(
isClick
)
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseClick
,
args
);
...
...
@@ -208,6 +221,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
{
VECTOR2D
screenPos
=
m_toolMgr
->
GetViewControls
()
->
GetCursorPosition
();
VECTOR2D
pos
=
getView
()
->
ToWorld
(
screenPos
);
if
(
pos
!=
m_lastMousePos
||
type
==
KiGfx
::
WX_VIEW_CONTROLS
::
EVT_REFRESH_MOUSE
)
{
motion
=
true
;
...
...
@@ -251,7 +265,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
}
void
TOOL_DISPATCHER
::
DispatchWxCommand
(
wxCommandEvent
&
aEvent
)
void
TOOL_DISPATCHER
::
DispatchWxCommand
(
const
wxCommandEvent
&
aEvent
)
{
bool
activateTool
=
false
;
std
::
string
toolName
;
...
...
common/tool/tool_event.cpp
View file @
3f320e4d
...
...
@@ -25,7 +25,7 @@
#include <cstring>
#include <string>
#include <base_struct.h>
//
#include <base_struct.h>
#include <tool/tool_event.h>
#include <tool/tool_manager.h>
...
...
common/tool/tool_manager.cpp
View file @
3f320e4d
...
...
@@ -288,10 +288,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
st
->
pendingWait
=
false
;
st
->
waitEvents
.
clear
();
if
(
st
->
cofunc
&&
!
st
->
cofunc
->
Resume
()
)
{
// The couroutine has finished
finishTool
(
st
);
}
finishTool
(
st
);
// The couroutine has finished
// If the tool did not request to propagate
// the event to other tools, we should stop it now
...
...
@@ -303,6 +300,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
BOOST_FOREACH
(
TOOL_STATE
*
st
,
m_toolState
|
boost
::
adaptors
::
map_values
)
{
// the tool state handler is waiting for events (i.e. called Wait() method)
if
(
!
st
->
pendingWait
)
{
// no state handler in progress - check if there are any transitions (defined by
...
...
@@ -324,9 +322,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
st
->
cofunc
->
Call
(
aEvent
);
if
(
!
st
->
cofunc
->
Running
()
)
{
finishTool
(
st
);
}
finishTool
(
st
);
// The couroutine has finished
}
}
}
...
...
include/geometry/shape_index.h
View file @
3f320e4d
...
...
@@ -93,28 +93,27 @@ void acceptVisitor( T object, V visitor )
* @param minDistance minimum collision distance
* @return if object and anotherObject collide
*/
template
<
class
T
,
class
U
>
template
<
class
T
,
class
U
>
bool
collide
(
T
object
,
U
anotherObject
,
int
minDistance
)
{
return
shapeFunctor
(
object
)
->
Collide
(
anotherObject
,
minDistance
);
return
shapeFunctor
(
object
)
->
Collide
(
anotherObject
,
minDistance
);
}
template
<
class
T
,
class
V
>
bool
queryCallback
(
T
shape
,
void
*
context
)
{
bool
queryCallback
(
T
shape
,
void
*
context
)
{
V
*
visitor
=
(
V
*
)
context
;
acceptVisitor
<
T
,
V
>
(
shape
,
*
visitor
);
acceptVisitor
<
T
,
V
>
(
shape
,
*
visitor
);
return
true
;
}
template
<
class
T
=
SHAPE
*>
template
<
class
T
=
SHAPE
*>
class
SHAPE_INDEX
{
public
:
class
Iterator
{
private
:
typedef
typename
RTree
<
T
,
int
,
2
,
float
>::
Iterator
RTreeIterator
;
RTreeIterator
iterator
;
...
...
@@ -124,20 +123,21 @@ class SHAPE_INDEX {
* Setup the internal tree iterator.
* @param tree pointer to a RTREE object
*/
void
Init
(
RTree
<
T
,
int
,
2
,
float
>*
tree
)
{
tree
->
GetFirst
(
iterator
);
void
Init
(
RTree
<
T
,
int
,
2
,
float
>*
tree
)
{
tree
->
GetFirst
(
iterator
);
}
public
:
/**
* Iterator constructor
*
* Creates an iterator for the index object
* @param index SHAPE_INDEX object to iterate
*/
Iterator
(
SHAPE_INDEX
*
index
)
{
Init
(
index
->
m_tree
);
Iterator
(
SHAPE_INDEX
*
index
)
{
Init
(
index
->
m_tree
);
}
/**
...
...
@@ -145,7 +145,8 @@ class SHAPE_INDEX {
*
* Returns the next data element.
*/
T
operator
*
()
{
T
operator
*
()
{
return
*
iterator
;
}
...
...
@@ -154,7 +155,8 @@ class SHAPE_INDEX {
*
* Shifts the iterator to the next element.
*/
bool
operator
++
()
{
bool
operator
++
()
{
return
++
iterator
;
}
...
...
@@ -163,7 +165,8 @@ class SHAPE_INDEX {
*
* Shifts the iterator to the next element.
*/
bool
operator
++
(
int
)
{
bool
operator
++
(
int
)
{
return
++
iterator
;
}
...
...
@@ -173,7 +176,8 @@ class SHAPE_INDEX {
* Checks if the iterator has reached the end.
* @return true if it is in an invalid position (data finished)
*/
bool
IsNull
()
{
bool
IsNull
()
{
return
iterator
.
IsNull
();
}
...
...
@@ -183,7 +187,8 @@ class SHAPE_INDEX {
* Checks if the iterator has not reached the end.
* @return true if it is in an valid position (data not finished)
*/
bool
IsNotNull
()
{
bool
IsNotNull
()
{
return
iterator
.
IsNotNull
();
}
...
...
@@ -192,12 +197,13 @@ class SHAPE_INDEX {
*
* Returns the current element of the iterator and moves to the next
* position.
* @return SHAPE object pointed by the iterator before moving to the
* next position.
* @return SHAPE object pointed by the iterator before moving to the next position.
*/
T
Next
()
{
T
Next
()
{
T
object
=
*
iterator
;
++
iterator
;
return
object
;
}
};
...
...
@@ -210,17 +216,17 @@ class SHAPE_INDEX {
* Function Add()
*
* Adds a SHAPE to the index.
* @param
shape the new SHAPE
* @param
aShape is the new SHAPE.
*/
void
Add
(
T
s
hape
);
void
Add
(
T
aS
hape
);
/**
* Function Remove()
*
* Removes a SHAPE to the index.
* @param
shape the new SHAPE
* @param
aShape is the new SHAPE.
*/
void
Remove
(
T
s
hape
);
void
Remove
(
T
aS
hape
);
/**
* Function RemoveAll()
...
...
@@ -236,12 +242,14 @@ class SHAPE_INDEX {
* @param visitor Visitor object to be run
*/
template
<
class
V
>
void
Accept
(
V
v
isitor
)
void
Accept
(
V
aV
isitor
)
{
Iterator
iter
=
this
->
Begin
();
while
(
!
iter
.
IsNull
())
{
while
(
!
iter
.
IsNull
()
)
{
T
shape
=
*
iter
;
acceptVisitor
(
shape
,
visitor
);
acceptVisitor
(
shape
,
aVisitor
);
iter
++
;
}
}
...
...
@@ -262,17 +270,16 @@ class SHAPE_INDEX {
* @param minDistance distance threshold
* @param visitor object to be invoked on every object contained in the search area.
*/
template
<
class
V
>
int
Query
(
const
SHAPE
*
shape
,
int
minDistance
,
V
&
visitor
,
bool
aExact
)
template
<
class
V
>
int
Query
(
const
SHAPE
*
aShape
,
int
aMinDistance
,
V
&
aVisitor
,
bool
aExact
)
{
BOX2I
box
=
s
hape
->
BBox
();
box
.
Inflate
(
minDistance
);
BOX2I
box
=
aS
hape
->
BBox
();
box
.
Inflate
(
aMinDistance
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
return
this
->
m_tree
->
Search
(
min
,
max
,
visitor
);
return
this
->
m_tree
->
Search
(
min
,
max
,
aVisitor
);
}
/**
...
...
@@ -284,7 +291,6 @@ class SHAPE_INDEX {
Iterator
Begin
();
private
:
RTree
<
T
,
int
,
2
,
float
>*
m_tree
;
};
...
...
@@ -293,58 +299,68 @@ class SHAPE_INDEX {
*/
template
<
class
T
>
SHAPE_INDEX
<
T
>::
SHAPE_INDEX
()
{
SHAPE_INDEX
<
T
>::
SHAPE_INDEX
()
{
this
->
m_tree
=
new
RTree
<
T
,
int
,
2
,
float
>
();
}
template
<
class
T
>
SHAPE_INDEX
<
T
>::~
SHAPE_INDEX
()
{
SHAPE_INDEX
<
T
>::~
SHAPE_INDEX
()
{
delete
this
->
m_tree
;
}
template
<
class
T
>
void
SHAPE_INDEX
<
T
>::
Add
(
T
shape
)
{
BOX2I
box
=
boundingBox
(
shape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()};
this
->
m_tree
->
Insert
(
min
,
max
,
shape
);
void
SHAPE_INDEX
<
T
>::
Add
(
T
aShape
)
{
BOX2I
box
=
boundingBox
(
aShape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
this
->
m_tree
->
Insert
(
min
,
max
,
aShape
);
}
template
<
class
T
>
void
SHAPE_INDEX
<
T
>::
Remove
(
T
shape
)
{
BOX2I
box
=
boundingBox
(
shape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()};
this
->
m_tree
->
Remove
(
min
,
max
,
shape
);
void
SHAPE_INDEX
<
T
>::
Remove
(
T
aShape
)
{
BOX2I
box
=
boundingBox
(
aShape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
this
->
m_tree
->
Remove
(
min
,
max
,
aShape
);
}
template
<
class
T
>
void
SHAPE_INDEX
<
T
>::
RemoveAll
()
{
void
SHAPE_INDEX
<
T
>::
RemoveAll
()
{
this
->
m_tree
->
RemoveAll
();
}
template
<
class
T
>
void
SHAPE_INDEX
<
T
>::
Reindex
()
{
void
SHAPE_INDEX
<
T
>::
Reindex
()
{
RTree
<
T
,
int
,
2
,
float
>*
newTree
;
newTree
=
new
RTree
<
T
,
int
,
2
,
float
>
();
Iterator
iter
=
this
->
Begin
();
while
(
!
iter
.
IsNull
())
{
while
(
!
iter
.
IsNull
()
)
{
T
shape
=
*
iter
;
BOX2I
box
=
boundingBox
(
shape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
newTree
->
Insert
(
min
,
max
,
shape
);
BOX2I
box
=
boundingBox
(
shape
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
newTree
->
Insert
(
min
,
max
,
shape
);
iter
++
;
}
delete
this
->
m_tree
;
this
->
m_tree
=
newTree
;
}
template
<
class
T
>
typename
SHAPE_INDEX
<
T
>::
Iterator
SHAPE_INDEX
<
T
>::
Begin
()
{
return
Iterator
(
this
);
typename
SHAPE_INDEX
<
T
>::
Iterator
SHAPE_INDEX
<
T
>::
Begin
()
{
return
Iterator
(
this
);
}
#endif
include/geometry/shape_line_chain.h
View file @
3f320e4d
...
...
@@ -43,7 +43,6 @@
* 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
;
...
...
@@ -55,7 +54,8 @@ class SHAPE_LINE_CHAIN : public SHAPE {
*
* Represents an intersection between two line segments
*/
struct
Intersection
{
struct
Intersection
{
/// segment belonging from the (this) argument of Intersect()
SEG
our
;
/// segment belonging from the aOther argument of Intersect()
...
...
@@ -71,45 +71,45 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Initializes an empty line chain.
*/
SHAPE_LINE_CHAIN
()
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{};
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
)
{};
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
)
SHAPE_LINE_CHAIN
(
const
VECTOR2I
&
aA
,
const
VECTOR2I
&
aB
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
2
);
m_points
[
0
]
=
a
;
m_points
[
1
]
=
b
;
m_points
.
resize
(
2
);
m_points
[
0
]
=
a
A
;
m_points
[
1
]
=
aB
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
&
a
,
const
VECTOR2I
&
b
,
const
VECTOR2I
&
c
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
SHAPE_LINE_CHAIN
(
const
VECTOR2I
&
aA
,
const
VECTOR2I
&
aB
,
const
VECTOR2I
&
aC
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
3
);
m_points
[
0
]
=
a
;
m_points
[
1
]
=
b
;
m_points
[
2
]
=
c
;
m_points
.
resize
(
3
);
m_points
[
0
]
=
a
A
;
m_points
[
1
]
=
aB
;
m_points
[
2
]
=
aC
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
*
v
,
int
count
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
SHAPE_LINE_CHAIN
(
const
VECTOR2I
*
aV
,
int
aCount
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
count
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
m_points
[
i
]
=
*
v
++
;
m_points
.
resize
(
aCount
);
for
(
int
i
=
0
;
i
<
aCount
;
i
++
)
m_points
[
i
]
=
*
aV
++
;
}
~
SHAPE_LINE_CHAIN
()
{};
...
...
@@ -118,7 +118,8 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Function Clear()
* Removes all points from the line chain.
*/
void
Clear
()
{
void
Clear
()
{
m_points
.
clear
();
m_closed
=
false
;
}
...
...
@@ -129,7 +130,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* 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
)
void
SetClosed
(
bool
aClosed
)
{
m_closed
=
aClosed
;
}
...
...
@@ -153,9 +154,10 @@ class SHAPE_LINE_CHAIN : public SHAPE {
int
SegmentCount
()
const
{
int
c
=
m_points
.
size
()
-
1
;
if
(
m_closed
)
if
(
m_closed
)
c
++
;
return
std
::
max
(
0
,
c
);
return
std
::
max
(
0
,
c
);
}
/**
...
...
@@ -167,86 +169,88 @@ class SHAPE_LINE_CHAIN : public SHAPE {
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
i
ndex: index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means
* @param
aI
ndex: 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
)
SEG
Segment
(
int
aIndex
)
{
if
(
index
<
0
)
i
ndex
+=
SegmentCount
();
if
(
aIndex
<
0
)
aI
ndex
+=
SegmentCount
();
if
(
index
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
m_points
[
index
],
m_points
[
0
],
i
ndex
);
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
m_points
[
aIndex
],
m_points
[
0
],
aI
ndex
);
else
return
SEG
(
m_points
[
index
],
m_points
[
index
+
1
],
i
ndex
);
return
SEG
(
m_points
[
aIndex
],
m_points
[
aIndex
+
1
],
aI
ndex
);
}
/**
* Function CSegment()
*
* Returns a read-only segment referencing to the segment (index) in the line chain.
* @param
i
ndex: index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means
* @param
aI
ndex: 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
i
ndex
)
const
const
SEG
CSegment
(
int
aI
ndex
)
const
{
if
(
index
<
0
)
i
ndex
+=
SegmentCount
();
if
(
aIndex
<
0
)
aI
ndex
+=
SegmentCount
();
if
(
index
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
index
]),
const_cast
<
VECTOR2I
&>
(
m_points
[
0
]),
i
ndex
);
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
0
]
),
aI
ndex
);
else
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
index
]),
const_cast
<
VECTOR2I
&>
(
m_points
[
index
+
1
]),
i
ndex
);
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
+
1
]
),
aI
ndex
);
}
/**
* Function Point()
*
* Returns a reference to a given point in the line chain.
* @param
i
ndex index of the point
* @param
aI
ndex index of the point
* @return reference to the point
*/
VECTOR2I
&
Point
(
int
index
)
VECTOR2I
&
Point
(
int
aIndex
)
{
if
(
index
<
0
)
index
+=
PointCount
();
return
m_points
[
index
];
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/**
* Function CPoint()
*
* Returns a const reference to a given point in the line chain.
* @param
i
ndex index of the point
* @param
aI
ndex index of the point
* @return const reference to the point
*/
const
VECTOR2I
&
CPoint
(
int
i
ndex
)
const
const
VECTOR2I
&
CPoint
(
int
aI
ndex
)
const
{
if
(
index
<
0
)
index
+=
PointCount
();
return
m_points
[
index
];
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/// @copydoc SHAPE::BBox()
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
BOX2I
bbox
;
bbox
.
Compute
(
m_points
);
bbox
.
Compute
(
m_points
);
return
bbox
;
}
/**
* Function Collide()
*
...
...
@@ -255,7 +259,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @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
;
bool
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
=
0
)
const
;
/**
* Function Collide()
...
...
@@ -265,7 +269,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @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
;
bool
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
=
0
)
const
;
/**
* Function Collide()
...
...
@@ -275,9 +279,8 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @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
;
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
;
/**
* Function Distance()
*
...
...
@@ -285,7 +288,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @param aP the point
* @return minimum distance.
*/
int
Distance
(
const
VECTOR2I
&
aP
)
const
;
int
Distance
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function Reverse()
...
...
@@ -307,13 +310,13 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* 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
* @param
aX is
X coordinate of the new point
* @param
aY is
Y coordinate of the new point
*/
void
Append
(
int
x
,
int
y
)
void
Append
(
int
aX
,
int
aY
)
{
VECTOR2I
v
(
x
,
y
);
Append
(
v
);
VECTOR2I
v
(
aX
,
aY
);
Append
(
v
);
}
/**
...
...
@@ -322,15 +325,15 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Appends a new point at the end of the line chain.
* @param aP the new point
*/
void
Append
(
const
VECTOR2I
&
aP
)
void
Append
(
const
VECTOR2I
&
aP
)
{
if
(
m_points
.
size
()
==
0
)
m_bbox
=
BOX2I
(
aP
,
VECTOR2I
(
0
,
0
)
);
if
(
m_points
.
size
()
==
0
)
m_bbox
=
BOX2I
(
aP
,
VECTOR2I
(
0
,
0
)
);
if
(
m_points
.
size
()
==
0
||
CPoint
(
-
1
)
!=
aP
)
if
(
m_points
.
size
()
==
0
||
CPoint
(
-
1
)
!=
aP
)
{
m_points
.
push_back
(
aP
);
m_bbox
.
Merge
(
aP
);
m_points
.
push_back
(
aP
);
m_bbox
.
Merge
(
aP
);
}
}
...
...
@@ -340,22 +343,23 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Appends another line chain at the end.
* @param aOtherLine the line chain to be appended.
*/
void
Append
(
const
SHAPE_LINE_CHAIN
&
aOtherLine
)
void
Append
(
const
SHAPE_LINE_CHAIN
&
aOtherLine
)
{
if
(
aOtherLine
.
PointCount
()
==
0
)
if
(
aOtherLine
.
PointCount
()
==
0
)
return
;
else
if
(
PointCount
()
==
0
||
aOtherLine
.
CPoint
(
0
)
!=
CPoint
(
-
1
))
else
if
(
PointCount
()
==
0
||
aOtherLine
.
CPoint
(
0
)
!=
CPoint
(
-
1
)
)
{
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
0
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
0
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
}
for
(
int
i
=
1
;
i
<
aOtherLine
.
PointCount
();
i
++
)
for
(
int
i
=
1
;
i
<
aOtherLine
.
PointCount
();
i
++
)
{
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
i
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
const
VECTOR2I
p
=
aOtherLine
.
CPoint
(
i
);
m_points
.
push_back
(
p
);
m_bbox
.
Merge
(
p
);
}
}
...
...
@@ -364,30 +368,31 @@ class SHAPE_LINE_CHAIN : public SHAPE {
*
* Replaces points with indices in range [start_index, end_index] with a single
* point aP.
* @param
start_i
ndex start of the point range to be replaced (inclusive)
* @param
end_i
ndex end of the point range to be replaced (inclusive)
* @param
aStartI
ndex start of the point range to be replaced (inclusive)
* @param
aEndI
ndex end of the point range to be replaced (inclusive)
* @param aP replacement point
*/
void
Replace
(
int
start_index
,
int
end_index
,
const
VECTOR2I
&
aP
);
void
Replace
(
int
aStartIndex
,
int
aEndIndex
,
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)
* Replaces points with indices in range [start_index, end_index] with the points from
* line chain aLine.
* @param aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex 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
);
void
Replace
(
int
aStartIndex
,
int
aEndIndex
,
const
SHAPE_LINE_CHAIN
&
aLine
);
/**
* Function Remove()
*
* Removes the range of points [start_index, end_index] from the line chain.
* @param
start_i
ndex start of the point range to be replaced (inclusive)
* @param
end_i
ndex end of the point range to be replaced (inclusive)
* @param
aStartI
ndex start of the point range to be replaced (inclusive)
* @param
aEndI
ndex end of the point range to be replaced (inclusive)
*/
void
Remove
(
int
start_index
,
int
end_index
);
void
Remove
(
int
aStartIndex
,
int
aEndIndex
);
/**
* Function Split()
...
...
@@ -397,7 +402,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @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
);
int
Split
(
const
VECTOR2I
&
aP
);
/**
* Function Find()
...
...
@@ -412,26 +417,25 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Function Slice()
*
* Returns a subset of this line chain containing the [start_index, end_index] range of points.
* @param
start_i
ndex start of the point range to be returned (inclusive)
* @param
end_i
ndex end of the point range to be returned (inclusive)
* @param
aStartI
ndex start of the point range to be returned (inclusive)
* @param
aEndI
ndex 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
;
const
SHAPE_LINE_CHAIN
Slice
(
int
aStartIndex
,
int
aEndIndex
=
-
1
)
const
;
struct
compareOriginDistance
{
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
Intersection
&
a
,
const
Intersection
&
b
)
bool
operator
()(
const
Intersection
&
aA
,
const
Intersection
&
aB
)
{
return
(
m_origin
-
a
.
p
).
EuclideanNorm
()
<
(
m_origin
-
b
.
p
).
EuclideanNorm
();
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
p
).
EuclideanNorm
();
}
VECTOR2I
m_origin
;
};
/**
* Function Intersect()
*
...
...
@@ -452,7 +456,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* 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
;
int
Intersect
(
const
SHAPE_LINE_CHAIN
&
aChain
,
Intersections
&
aIp
)
const
;
/**
* Function PathLength()
...
...
@@ -461,7 +465,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* 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
;
int
PathLength
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function PointInside()
...
...
@@ -471,7 +475,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @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
;
bool
PointInside
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function PointOnEdge()
...
...
@@ -480,7 +484,7 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* @param aP point to check
* @return true if the point lies on the edge.
*/
bool
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
;
bool
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
;
/**
* Function SelfIntersecting()
...
...
@@ -504,26 +508,32 @@ class SHAPE_LINE_CHAIN : public SHAPE {
* Finds a point on the line chain that is closest to point aP.
* @return the nearest point.
*/
const
VECTOR2I
NearestPoint
(
const
VECTOR2I
&
aP
)
const
;
const
VECTOR2I
NearestPoint
(
const
VECTOR2I
&
aP
)
const
;
/// @copydoc SHAPE::Format()
const
std
::
string
Format
()
const
;
bool
operator
!=
(
const
SHAPE_LINE_CHAIN
&
rhs
)
const
bool
operator
!=
(
const
SHAPE_LINE_CHAIN
&
aRhs
)
const
{
if
(
PointCount
()
!=
rhs
.
PointCount
()
)
if
(
PointCount
()
!=
aRhs
.
PointCount
()
)
return
true
;
for
(
int
i
=
0
;
i
<
PointCount
();
i
++
)
if
(
CPoint
(
i
)
!=
rhs
.
CPoint
(
i
)
)
for
(
int
i
=
0
;
i
<
PointCount
();
i
++
)
{
if
(
CPoint
(
i
)
!=
aRhs
.
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
;
};
...
...
include/tool/action_manager.h
View file @
3f320e4d
...
...
@@ -43,21 +43,21 @@ public:
/**
* Function RegisterAction()
* Adds a tool action to the manager
set
and sets it up. After that is is possible to invoke
* the action using hotkeys or its name.
* Adds a tool action to the manager and sets it up. After that is is possible to invoke
* the action using hotkeys or
sending a command event with
its name.
* @param aAction: action to be added. Ownership is not transferred.
*/
void
RegisterAction
(
TOOL_ACTION
*
aAction
);
/**
* Function UnregisterAction()
* Removes a tool action from the manager
set
and makes it unavailable for further usage.
* Removes a tool action from the manager and makes it unavailable for further usage.
* @param aAction: action to be removed.
*/
void
UnregisterAction
(
TOOL_ACTION
*
aAction
);
/**
* Generates an unique ID from for a
tool
with given name.
* Generates an unique ID from for a
n action
with given name.
*/
static
int
MakeActionId
(
const
std
::
string
&
aActionName
);
...
...
@@ -82,9 +82,16 @@ public:
bool
RunHotKey
(
int
aHotKey
)
const
;
private
:
///> Tool manager needed to run actions
TOOL_MANAGER
*
m_toolMgr
;
///> Map for indexing actions by their IDs
std
::
map
<
int
,
TOOL_ACTION
*>
m_actionIdIndex
;
///> Map for indexing actions by their names
std
::
map
<
std
::
string
,
TOOL_ACTION
*>
m_actionNameIndex
;
///> Map for indexing actions by their hotkeys
std
::
map
<
int
,
TOOL_ACTION
*>
m_actionHotKeys
;
/**
...
...
include/tool/context_menu.h
View file @
3f320e4d
...
...
@@ -29,7 +29,6 @@
#include <tool/tool_action.h>
#include <map>
class
wxMenu
;
class
TOOL_INTERACTIVE
;
/**
...
...
@@ -40,53 +39,102 @@ class TOOL_INTERACTIVE;
*/
class
CONTEXT_MENU
{
public
:
///> Default constructor
CONTEXT_MENU
();
///> Copy constructor
CONTEXT_MENU
(
const
CONTEXT_MENU
&
aMenu
);
/**
* Function SetTitle()
* Sets title for the context menu. The title is shown as a text label shown on the top of
* the menu.
* @param aTitle is the new title.
*/
void
SetTitle
(
const
wxString
&
aTitle
);
/**
* Function Add()
* Adds an entry to the menu. After highlighting/selecting the entry, a TOOL_EVENT command is
* sent that contains ID of the entry.
* @param aLabel is the text label show in the menu.
* @param aId is the ID that is sent in the TOOL_EVENT. It should be unique for every entry.
*/
void
Add
(
const
wxString
&
aLabel
,
int
aId
);
/**
* Function Add()
* Adds an entry to the menu, basing on the TOOL_ACTION object. After selecting the entry,
* a TOOL_EVENT command containing name of the action is sent.
* @param aAction is the action to be added to menu entry.
*/
void
Add
(
const
TOOL_ACTION
&
aAction
);
/**
* Function Clear()
* Removes all the entries from the menu (as well as its title). It leaves the menu in the
* initial state.
*/
void
Clear
();
/**
* Function GetMenu()
* Returns the instance of wxMenu object used to display the menu.
*/
wxMenu
*
GetMenu
()
const
{
return
const_cast
<
wxMenu
*>
(
&
m_menu
);
}
private
:
///> Class CMEventHandler takes care of handling menu events. After reception of particular
///> events, it translates them to TOOL_EVENTs that may control tools.
class
CMEventHandler
:
public
wxEvtHandler
{
public
:
///> Default constructor
///> aMenu is the CONTEXT_MENU instance for which it handles events.
CMEventHandler
(
CONTEXT_MENU
*
aMenu
)
:
m_menu
(
aMenu
)
{};
///> Handler for menu events.
void
onEvent
(
wxEvent
&
aEvent
);
private
:
///> CONTEXT_MENU instance for which it handles events.
CONTEXT_MENU
*
m_menu
;
};
friend
class
TOOL_INTERACTIVE
;
/**
* Function setTool()
* Sets a tool that is the creator of the menu.
* @param aTool is the tool that created the menu.
*/
void
setTool
(
TOOL_INTERACTIVE
*
aTool
)
{
m_tool
=
aTool
;
}
/**
* Function getHotKeyDescription()
* Returns a hot key in the string format accepted by wxMenu.
*
* @param aAction is the action with hot key to be converted.
* @param aAction is the action with hot key to be translated..
* @return Hot key in the string format compatible with wxMenu.
*/
std
::
string
getHotKeyDescription
(
const
TOOL_ACTION
&
aAction
)
const
;
///
Flag indicating that the menu title was set up
///
> Flag indicating that the menu title was set up.
bool
m_titleSet
;
///> Instance of wxMenu used for display of the context menu.
wxMenu
m_menu
;
///> Instance of menu event handler.
CMEventHandler
m_handler
;
///> Creator of the menu
TOOL_INTERACTIVE
*
m_tool
;
/// Menu items with ID higher than that are considered TOOL_ACTIONs
...
...
include/tool/tool_base.h
View file @
3f320e4d
...
...
@@ -42,17 +42,21 @@ class VIEW_CONTROLS;
enum
TOOL_Type
{
TOOL_Interactive
=
0x1
,
TOOL_Batch
=
0x2
///> Tool that interacts with the user
TOOL_Interactive
=
0x01
,
///> Tool that runs in the background without any user intervention
TOOL_Batch
=
0x02
};
/// Unique identifier for tools
typedef
int
TOOL_ID
;
typedef
DELEGATE
<
int
,
TOOL_EVENT
&>
TOOL_STATE_FUNC
;
/**
* Class TOOL_BASE
*
* Base abstract interface for all kinds of tools
* Base abstract interface for all kinds of tools
.
*/
class
TOOL_BASE
...
...
@@ -61,25 +65,49 @@ public:
TOOL_BASE
(
TOOL_Type
aType
,
TOOL_ID
aId
,
const
std
::
string
&
aName
=
std
::
string
(
""
)
)
:
m_type
(
aType
),
m_toolId
(
aId
),
m_toolName
(
aName
)
{};
m_toolName
(
aName
),
m_toolMgr
(
NULL
){};
virtual
~
TOOL_BASE
()
{};
/**
* Function GetType()
* Returns the type of the tool.
* @return The type of the tool.
*/
TOOL_Type
GetType
()
const
{
return
m_type
;
}
/**
* Function GetId()
* Returns the unique identifier of the tool. The identifier is set by an instance of
* TOOL_MANAGER.
* @return Identifier of the tool.
*/
TOOL_ID
GetId
()
const
{
return
m_toolId
;
}
/**
* Function GetName()
* Returns the name of the tool. Tool names are expected to obey the format:
* application.ToolName (eg. pcbnew.InteractiveSelection).
* @return The name of the tool.
*/
const
std
::
string
&
GetName
()
const
{
return
m_toolName
;
}
/**
* Function GetManager()
* Returns the instance of TOOL_MANAGER that takes care of the tool.
* @return Instance of the TOOL_MANAGER. If there is no TOOL_MANAGER associated, it returns
* NULL.
*/
TOOL_MANAGER
*
GetManager
()
const
{
return
m_toolMgr
;
...
...
@@ -96,14 +124,27 @@ protected:
*/
void
attachManager
(
TOOL_MANAGER
*
aManager
);
/**
* Function getView()
*
* Returns the instance of VIEW object used in the application. It allows tools to draw.
* @return The instance of VIEW.
*/
KiGfx
::
VIEW
*
getView
()
const
;
/**
* Function getViewControls()
*
* Returns the instance of VIEW_CONTROLS object used in the application. It allows tools to
* read & modify user input and its settings (eg. show cursor, enable snapping to grid, etc.)
* @return The instance of VIEW_CONTROLS.
*/
KiGfx
::
VIEW_CONTROLS
*
getViewControls
()
const
;
/**
* Function getEditFrame()
*
* Returns the application window object, casted to requested user type, possibly with
* run-time type check
* Returns the application window object, casted to requested user type.
*/
template
<
typename
T
>
T
*
getEditFrame
()
const
...
...
@@ -124,8 +165,14 @@ protected:
return
static_cast
<
T
*>
(
m
);
}
///> Stores the type of the tool.
TOOL_Type
m_type
;
///> Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
TOOL_ID
m_toolId
;
///> Name of the tool. Names are expected to obey the format application.ToolName
///> (eg. pcbnew.InteractiveSelection).
std
::
string
m_toolName
;
TOOL_MANAGER
*
m_toolMgr
;
...
...
include/tool/tool_dispatcher.h
View file @
3f320e4d
...
...
@@ -29,7 +29,6 @@
#include <tool/tool_event.h>
//#include <wx/event.h>
#include <wx/kbdstate.h>
class
TOOL_MANAGER
;
...
...
@@ -61,26 +60,62 @@ public:
TOOL_DISPATCHER
(
TOOL_MANAGER
*
aToolMgr
,
PCB_BASE_FRAME
*
aEditFrame
);
virtual
~
TOOL_DISPATCHER
();
/**
* Function ResetState()
* Brings the dispatcher to its initial state.
*/
virtual
void
ResetState
();
/**
* Function DispatchWxEvent()
* Processes wxEvents (mostly UI events), translates them to TOOL_EVENTs, and makes tools
* handle those.
* @param aEvent is the wxWidgets event to be processed.
*/
virtual
void
DispatchWxEvent
(
wxEvent
&
aEvent
);
virtual
void
DispatchWxCommand
(
wxCommandEvent
&
aEvent
);
/**
* Function DispatchWxCommand()
* Processes wxCommands (mostly menu related events) and runs appropriate actions (eg. run the
* specified tool).
* @param aEvent is the wxCommandEvent to be processed.
*/
virtual
void
DispatchWxCommand
(
const
wxCommandEvent
&
aEvent
);
private
:
///> Number of mouse buttons that is handled in events.
static
const
int
MouseButtonCount
=
3
;
///> The time threshold for a mouse button press that distinguishes between a single mouse
///> click and a beginning of drag event (expressed in milliseconds).
static
const
int
DragTimeThreshold
=
300
;
///> The distance threshold for mouse cursor that disinguishes between a single mouse click
///> and a beginning of drag event (expressed in screen pixels).
static
const
int
DragDistanceThreshold
=
8
;
///> Handles mouse related events (click, motion, dragging)
bool
handleMouseButton
(
wxEvent
&
aEvent
,
int
aIndex
,
bool
aMotion
);
bool
handlePopupMenu
(
wxEvent
&
aEvent
);
///> Saves the state of key modifiers (Alt, Ctrl and so on).
int
decodeModifiers
(
const
wxKeyboardState
*
aState
)
const
;
///> Stores all the informations regarding a mouse button state.
struct
ButtonState
;
///> The last mouse cursor position (in world coordinates).
VECTOR2D
m_lastMousePos
;
///> State of mouse buttons.
std
::
vector
<
ButtonState
*>
m_buttons
;
///> Returns the instance of VIEW, used by the application.
KiGfx
::
VIEW
*
getView
();
///> Instance of tool manager that cooperates with the dispatcher.
TOOL_MANAGER
*
m_toolMgr
;
///> Instance of wxFrame that is the source of UI events.
PCB_BASE_FRAME
*
m_editFrame
;
};
...
...
include/tool/tool_event.h
View file @
3f320e4d
...
...
@@ -29,6 +29,7 @@
#include <deque>
#include <math/vector2d.h>
#include <cassert>
#include <boost/optional.hpp>
...
...
@@ -71,17 +72,19 @@ enum TOOL_Actions
TA_ViewDirty
=
0x0800
,
TA_ChangeLayer
=
0x1000
,
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from the context menu.
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
// the context menu.
TA_CancelTool
=
0x2000
,
// Context menu update. Issued whenever context menu is open and the user hovers the mouse
over one of choices.
//
Used in dynamic highligting in disambiguation menu
// Context menu update. Issued whenever context menu is open and the user hovers the mouse
//
over one of choices. Used in dynamic highligting in disambiguation menu
TA_ContextMenuUpdate
=
0x4000
,
// Context menu choice. Sent if the user picked something from the context menu or closed it without selecting anything.
// Context menu choice. Sent if the user picked something from the context menu or
// closed it without selecting anything.
TA_ContextMenuChoice
=
0x8000
,
// Tool action
// Tool action
(allows to control tools)
TA_Action
=
0x10000
,
TA_Any
=
0xffffffff
...
...
@@ -129,6 +132,12 @@ enum CONTEXT_MENU_TRIGGER
class
TOOL_EVENT
{
public
:
/**
* Function Format()
* Returns information about event in form of a human-readable string.
*
* @return Event information.
*/
const
std
::
string
Format
()
const
;
TOOL_EVENT
(
TOOL_EventCategory
aCategory
=
TC_None
,
TOOL_Actions
aAction
=
TA_None
,
...
...
@@ -175,33 +184,44 @@ public:
m_commandStr
=
aExtraParam
;
}
///> Returns the category (eg. mouse/keyboard/action) of an event..
TOOL_EventCategory
Category
()
const
{
return
m_category
;
}
///> Returns more specific information about the type of an event.
TOOL_Actions
Action
()
const
{
return
m_actions
;
}
///> Returns information about difference between current mouse cursor position and the place
///> where dragging has started.
const
VECTOR2D
Delta
()
const
{
assert
(
m_category
==
TC_Mouse
);
// this should be used only with mouse events
return
m_mouseDelta
;
}
///> Returns mouse cursor position in world coordinates.
const
VECTOR2D
&
Position
()
const
{
assert
(
m_category
==
TC_Mouse
);
// this should be used only with mouse events
return
m_mousePos
;
}
///> Returns the point where dragging has started.
const
VECTOR2D
&
DragOrigin
()
const
{
assert
(
m_category
==
TC_Mouse
);
// this should be used only with mouse events
return
m_mouseDragOrigin
;
}
///> Returns information about mouse buttons state.
int
Buttons
()
const
{
assert
(
m_category
==
TC_Mouse
);
// this should be used only with mouse events
return
m_mouseButtons
;
}
...
...
@@ -231,6 +251,7 @@ public:
return
m_actions
==
TA_CancelTool
;
}
///> Returns information about key modifiers state (Ctrl, Alt, etc.)
int
Modifier
(
int
aMask
=
MD_ModifierMask
)
const
{
return
(
m_modifiers
&
aMask
);
...
...
@@ -251,8 +272,6 @@ public:
return
m_actions
==
TA_KeyDown
;
}
void
Ignore
();
void
SetMouseDragOrigin
(
const
VECTOR2D
&
aP
)
{
m_mouseDragOrigin
=
aP
;
...
...
@@ -268,6 +287,13 @@ public:
m_mouseDelta
=
aP
;
}
/**
* Function Matches()
* Tests whether two events match in terms of category & action or command.
*
* @param aEvent is the event to test against.
* @return True if two events match, false otherwise.
*/
bool
Matches
(
const
TOOL_EVENT
&
aEvent
)
const
{
if
(
!
(
m_category
&
aEvent
.
m_category
)
)
...
...
@@ -299,13 +325,25 @@ private:
TOOL_Actions
m_actions
;
TOOL_ActionScope
m_scope
;
///> Difference between mouse cursor position and
///> the point where dragging event has started
VECTOR2D
m_mouseDelta
;
///> Current mouse cursor position
VECTOR2D
m_mousePos
;
///> Point where dragging has started
VECTOR2D
m_mouseDragOrigin
;
///> State of mouse buttons
int
m_mouseButtons
;
///> Stores code of pressed/released key
int
m_keyCode
;
///> State of key modifierts (Ctrl/Alt/etc.)
int
m_modifiers
;
boost
::
optional
<
int
>
m_commandId
;
boost
::
optional
<
std
::
string
>
m_commandStr
;
};
...
...
@@ -324,7 +362,10 @@ public:
typedef
std
::
deque
<
TOOL_EVENT
>::
iterator
iterator
;
typedef
std
::
deque
<
TOOL_EVENT
>::
const_iterator
const_iterator
;
///> Default constructor. Creates an empty list.
TOOL_EVENT_LIST
()
{};
///> Constructor for a list containing only one TOOL_EVENT.
TOOL_EVENT_LIST
(
const
TOOL_EVENT
&
aSingleEvent
)
{
m_events
.
push_back
(
aSingleEvent
);
...
...
@@ -346,6 +387,11 @@ public:
return
boost
::
optional
<
const
TOOL_EVENT
&>
();
}
/**
* Function Add()
* Adds a tool event to the list.
* @param aEvent is the tool event to be addded.
*/
void
Add
(
const
TOOL_EVENT
&
aEvent
)
{
m_events
.
push_back
(
aEvent
);
...
...
include/tool/tool_interactive.h
View file @
3f320e4d
...
...
@@ -35,6 +35,10 @@ class CONTEXT_MENU;
class
TOOL_INTERACTIVE
:
public
TOOL_BASE
{
public
:
/**
* Constructor
*
* Creates a tool with given id & name. The name must be unique. */
TOOL_INTERACTIVE
(
TOOL_ID
aId
,
const
std
::
string
&
aName
);
/**
...
...
@@ -46,8 +50,8 @@ public:
/**
* Function Reset()
* Brings the tool to a known, initial state. If the tool claimed anything from
the model or the view,
* it must release it when its reset.
* Brings the tool to a known, initial state. If the tool claimed anything from
*
the model or the view,
it must release it when its reset.
*/
virtual
void
Reset
()
=
0
;
...
...
@@ -65,7 +69,9 @@ public:
/**
* Function SetContextMenu()
*
* Assigns a context menu and tells when it should be activated
* Assigns a context menu and tells when it should be activated.
* @param aMenu is the menu to be assigned.
* @param aTrigger determines conditions upon which the context menu is activated.
*/
void
SetContextMenu
(
CONTEXT_MENU
*
aMenu
,
CONTEXT_MENU_TRIGGER
aTrigger
=
CMENU_BUTTON
);
...
...
@@ -87,9 +93,8 @@ public:
*/
OPT_TOOL_EVENT
Wait
(
const
TOOL_EVENT_LIST
&
aEventList
=
TOOL_EVENT
(
TC_Any
,
TA_Any
)
);
/** functions below are not yet implemented - their interface may change */
template
<
class
Parameters
,
class
ReturnValue
>
/*
template<class Parameters, class ReturnValue>
bool InvokeTool( const std::string& aToolName, const Parameters& parameters,
ReturnValue& returnValue );
...
...
@@ -98,11 +103,10 @@ public:
ReturnValue& returnValue );
template<class T>
void
Yield
(
const
T
&
returnValue
);
void Yield( const T& returnValue );
*/
protected
:
/* helper functions for constructing events for Wait() and Go() with
less typing */
/* helper functions for constructing events for Wait() and Go() with less typing */
const
TOOL_EVENT
evActivate
(
std
::
string
aToolName
=
""
);
const
TOOL_EVENT
evCommand
(
int
aCommandId
=
-
1
);
const
TOOL_EVENT
evCommand
(
std
::
string
aCommandStr
=
""
);
...
...
pcbnew/tools/move_tool.cpp
View file @
3f320e4d
...
...
@@ -36,6 +36,8 @@ using boost::optional;
MOVE_TOOL
::
MOVE_TOOL
()
:
TOOL_INTERACTIVE
(
"pcbnew.InteractiveMove"
),
m_selectionTool
(
NULL
),
// Available actions:
m_activate
(
m_toolName
,
AS_GLOBAL
,
'M'
,
"Move"
,
"Moves the selected item(s)"
),
m_rotate
(
m_toolName
+
".rotate"
,
AS_CONTEXT
,
' '
,
"Rotate"
,
"Rotates selected item(s)"
),
m_flip
(
m_toolName
+
".flip"
,
AS_CONTEXT
,
'F'
,
"Flip"
,
"Flips selected item(s)"
)
...
...
@@ -69,7 +71,7 @@ bool MOVE_TOOL::Init()
m_toolMgr
->
RegisterAction
(
&
m_rotate
);
m_toolMgr
->
RegisterAction
(
&
m_flip
);
// Add context menu entries
for the selection tool
// Add context menu entries
that are displayed when selection tool is active
m_selectionTool
->
AddMenuItem
(
m_activate
);
m_selectionTool
->
AddMenuItem
(
m_rotate
);
m_selectionTool
->
AddMenuItem
(
m_flip
);
...
...
@@ -92,7 +94,9 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
VIEW
*
view
=
getView
();
VIEW_CONTROLS
*
controls
=
getViewControls
();
// Add a VIEW_GROUP that will hold all modified items
view
->
Add
(
&
m_items
);
controls
->
ShowCursor
(
true
);
controls
->
SetSnapping
(
true
);
controls
->
SetAutoPan
(
true
);
...
...
@@ -102,7 +106,7 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
{
if
(
evt
->
IsCancel
()
)
{
restore
=
true
;
restore
=
true
;
// Cancelling the tool means that items have to be restored
break
;
// Finish
}
...
...
@@ -111,12 +115,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
{
VECTOR2D
cursorPos
=
getView
()
->
ToWorld
(
getViewControls
()
->
GetCursorPosition
()
);
if
(
evt
->
Matches
(
m_rotate
.
GetEvent
()
)
)
if
(
evt
->
Matches
(
m_rotate
.
GetEvent
()
)
)
// got rotation event?
{
m_state
.
Rotate
(
cursorPos
,
900.0
);
m_items
.
ViewUpdate
(
VIEW_ITEM
::
GEOMETRY
);
}
else
if
(
evt
->
Matches
(
m_flip
.
GetEvent
()
)
)
else
if
(
evt
->
Matches
(
m_flip
.
GetEvent
()
)
)
// got flip event?
{
m_state
.
Flip
(
cursorPos
);
m_items
.
ViewUpdate
(
VIEW_ITEM
::
GEOMETRY
);
...
...
@@ -165,20 +169,22 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
// Restore visibility of the original items
vgSetVisibility
(
&
m_items
,
true
);
// Movement has to be rollbacked, so restore the previous state of items
if
(
restore
)
{
// Modifications has to be rollbacked, so restore the previous state of items
vgUpdate
(
&
m_items
,
VIEW_ITEM
::
APPEARANCE
);
m_state
.
RestoreAll
();
}
else
{
// Changes are applied, so update the items
vgUpdate
(
&
m_items
,
m_state
.
GetUpdateFlag
()
);
m_state
.
Apply
();
}
m_items
.
Clear
();
view
->
Remove
(
&
m_items
);
controls
->
ShowCursor
(
false
);
controls
->
SetSnapping
(
false
);
controls
->
SetAutoPan
(
false
);
...
...
pcbnew/tools/selection_area.h
View file @
3f320e4d
...
...
@@ -50,6 +50,7 @@ public:
virtual
const
BOX2I
ViewBBox
()
const
;
void
ViewDraw
(
int
aLayer
,
KiGfx
::
GAL
*
aGal
)
const
;
void
ViewGetLayers
(
int
aLayers
[],
int
&
aCount
)
const
;
void
SetOrigin
(
VECTOR2I
aOrigin
)
...
...
pcbnew/tools/selection_tool.cpp
View file @
3f320e4d
...
...
@@ -83,7 +83,6 @@ bool SELECTION_TOOL::Init()
int
SELECTION_TOOL
::
Main
(
TOOL_EVENT
&
aEvent
)
{
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
assert
(
board
!=
NULL
);
// Main loop: keep receiving events
...
...
@@ -116,13 +115,16 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
}
else
{
// Check if dragging has started within any of selected items bounding box
if
(
containsSelected
(
evt
->
Position
()
)
)
{
// Yes -> run the move tool and wait till it finishes
m_toolMgr
->
InvokeTool
(
"pcbnew.InteractiveMove"
);
Wait
();
}
else
{
// No -> clear the selection list
clearSelection
();
}
}
...
...
@@ -135,7 +137,7 @@ int SELECTION_TOOL::Main( TOOL_EVENT& aEvent )
void
SELECTION_TOOL
::
AddMenuItem
(
const
TOOL_ACTION
&
aAction
)
{
assert
(
aAction
.
GetId
()
>
0
);
// Check if the action was registered before
assert
(
aAction
.
GetId
()
>
0
);
// Check if the action was registered before
in ACTION_MANAGER
m_menu
.
Add
(
aAction
);
}
...
...
@@ -259,9 +261,9 @@ BOARD_ITEM* SELECTION_TOOL::pickSmallestComponent( GENERAL_COLLECTOR* aCollector
bool
SELECTION_TOOL
::
selectMultiple
()
{
VIEW
*
view
=
getView
();
bool
cancelled
=
false
;
bool
cancelled
=
false
;
// Was the tool cancelled while it was running?
m_multiple
=
true
;
// Multiple selection mode is active
VIEW
*
view
=
getView
();
getViewControls
()
->
SetAutoPan
(
true
);
// Those 2 lines remove the blink-in-the-random-place effect
...
...
@@ -291,7 +293,7 @@ bool SELECTION_TOOL::selectMultiple()
if
(
evt
->
IsMouseUp
(
MB_Left
)
)
{
// End drawing
a
selection box
// End drawing
the
selection box
m_selArea
->
ViewSetVisible
(
false
);
// Mark items within the selection box as selected
...
...
@@ -315,6 +317,7 @@ bool SELECTION_TOOL::selectMultiple()
// Now the context menu should be enabled
if
(
!
m_selectedItems
.
empty
()
)
SetContextMenu
(
&
m_menu
,
CMENU_BUTTON
);
break
;
}
}
...
...
@@ -367,6 +370,7 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
{
optional
<
int
>
id
=
evt
->
GetCommandId
();
// User has selected an item, so this one will be returned
if
(
id
&&
(
*
id
>=
0
)
)
current
=
(
*
aCollector
)[
*
id
];
...
...
@@ -392,11 +396,12 @@ BOARD_ITEM* SELECTION_TOOL::disambiguationMenu( GENERAL_COLLECTOR* aCollector )
bool
SELECTION_TOOL
::
selectable
(
const
BOARD_ITEM
*
aItem
)
const
{
// Is high contrast mode enabled?
bool
highContrast
=
getView
()
->
GetPainter
()
->
GetSettings
()
->
GetHighContrast
();
if
(
highContrast
)
{
bool
onActive
=
false
;
bool
onActive
=
false
;
// Is the item on any of active layers?
int
layers
[
KiGfx
::
VIEW
::
VIEW_MAX_LAYERS
],
layers_count
;
// Filter out items that do not belong to active layers
...
...
@@ -406,14 +411,14 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
for
(
int
i
=
0
;
i
<
layers_count
;
++
i
)
{
if
(
activeLayers
.
count
(
layers
[
i
]
)
>
0
)
// Item is on at least one
active layer
if
(
activeLayers
.
count
(
layers
[
i
]
)
>
0
)
// Item is on at least one
of active layers
{
onActive
=
true
;
break
;
}
}
if
(
!
onActive
)
if
(
!
onActive
)
// We do not want to select items that are in the background
return
false
;
}
...
...
@@ -426,8 +431,7 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
LAYER_NUM
top
,
bottom
;
static_cast
<
const
SEGVIA
*>
(
aItem
)
->
ReturnLayerPair
(
&
top
,
&
bottom
);
return
(
board
->
IsLayerVisible
(
top
)
||
board
->
IsLayerVisible
(
bottom
)
);
return
(
board
->
IsLayerVisible
(
top
)
||
board
->
IsLayerVisible
(
bottom
)
);
}
break
;
...
...
@@ -473,8 +477,7 @@ bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const
{
// Check if the point is located within any of the currently selected items bounding boxes
std
::
set
<
BOARD_ITEM
*>::
iterator
it
,
it_end
;
for
(
it
=
m_selectedItems
.
begin
(),
it_end
=
m_selectedItems
.
end
();
it
!=
it_end
;
++
it
)
for
(
it
=
m_selectedItems
.
begin
(),
it_end
=
m_selectedItems
.
end
();
it
!=
it_end
;
++
it
)
{
BOX2I
itemBox
=
(
*
it
)
->
ViewBBox
();
itemBox
.
Inflate
(
500000
);
// Give some margin for gripping an item
...
...
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