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
22045b61
Commit
22045b61
authored
Oct 14, 2013
by
Maciej Suminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Converted tabs to spaces. Removed trailing whitespaces.
parent
ac489ece
Changes
55
Hide whitespace changes
Inline
Side-by-side
Showing
55 changed files
with
3023 additions
and
3024 deletions
+3023
-3024
drawpanel_gal.cpp
common/drawpanel_gal.cpp
+20
-20
color4d.cpp
common/gal/color4d.cpp
+2
-3
opengl_gal.cpp
common/gal/opengl/opengl_gal.cpp
+1
-1
shader.frag
common/gal/opengl/shader.frag
+1
-1
shader.vert
common/gal/opengl/shader.vert
+8
-8
seg.cpp
common/geometry/seg.cpp
+60
-60
shape_collisions.cpp
common/geometry/shape_collisions.cpp
+155
-155
shape_line_chain.cpp
common/geometry/shape_line_chain.cpp
+362
-362
fcontext.s
common/system/fcontext.s
+3
-3
make_i386_pe_gas.S
common/system/make_i386_pe_gas.S
+33
-33
context_menu.cpp
common/tool/context_menu.cpp
+21
-21
tool_base.cpp
common/tool/tool_base.cpp
+5
-5
tool_dispatcher.cpp
common/tool/tool_dispatcher.cpp
+168
-168
tool_event.cpp
common/tool/tool_event.cpp
+89
-89
tool_interactive.cpp
common/tool/tool_interactive.cpp
+8
-8
tool_manager.cpp
common/tool/tool_manager.cpp
+165
-165
class_drawpanel_gal.h
include/class_drawpanel_gal.h
+1
-1
color4d.h
include/gal/color4d.h
+1
-1
shader.h
include/gal/opengl/shader.h
+5
-5
seg.h
include/geometry/seg.h
+266
-266
shape.h
include/geometry/shape.h
+97
-97
shape_circle.h
include/geometry/shape_circle.h
+34
-34
shape_index.h
include/geometry/shape_index.h
+4
-4
shape_index_list.h
include/geometry/shape_index_list.h
+218
-218
shape_line_chain.h
include/geometry/shape_line_chain.h
+494
-494
shape_rect.h
include/geometry/shape_rect.h
+109
-109
box2.h
include/math/box2.h
+2
-2
vector2d.h
include/math/vector2d.h
+1
-1
context_menu.h
include/tool/context_menu.h
+94
-94
coroutine.h
include/tool/coroutine.h
+152
-152
delegate.h
include/tool/delegate.h
+54
-54
coroutine_example.cpp
include/tool/examples/coroutine_example.cpp
+31
-31
delegate_example.cpp
include/tool/examples/delegate_example.cpp
+18
-18
tool_base.h
include/tool/tool_base.h
+117
-117
tool_dispatcher.h
include/tool/tool_dispatcher.h
+3
-3
tool_event.h
include/tool/tool_event.h
+54
-54
tool_interactive.h
include/tool/tool_interactive.h
+67
-67
view_controls.h
include/view/view_controls.h
+1
-1
edit.cpp
pcbnew/edit.cpp
+0
-0
pcb_painter.cpp
pcbnew/pcb_painter.cpp
+1
-1
pns_itemset.h
pcbnew/router/pns_itemset.h
+1
-1
pns_joint.h
pcbnew/router/pns_joint.h
+11
-11
pns_line.cpp
pcbnew/router/pns_line.cpp
+5
-5
pns_line.h
pcbnew/router/pns_line.h
+10
-10
pns_line_placer.cpp
pcbnew/router/pns_line_placer.cpp
+10
-10
pns_line_placer.h
pcbnew/router/pns_line_placer.h
+24
-24
pns_node.cpp
pcbnew/router/pns_node.cpp
+11
-11
pns_node.h
pcbnew/router/pns_node.h
+12
-12
pns_optimizer.cpp
pcbnew/router/pns_optimizer.cpp
+8
-8
pns_router.cpp
pcbnew/router/pns_router.cpp
+1
-1
pns_shove.cpp
pcbnew/router/pns_shove.cpp
+1
-1
pns_shove.h
pcbnew/router/pns_shove.h
+1
-1
pns_walkaround.cpp
pcbnew/router/pns_walkaround.cpp
+1
-1
pns_walkaround.h
pcbnew/router/pns_walkaround.h
+1
-1
router_tool.cpp
pcbnew/router/router_tool.cpp
+1
-1
No files found.
common/drawpanel_gal.cpp
View file @
22045b61
...
...
@@ -78,21 +78,21 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin
Connect
(
wxEVT_SIZE
,
wxSizeEventHandler
(
EDA_DRAW_PANEL_GAL
::
onSize
),
NULL
,
this
);
/* Generic events for the Tool Dispatcher */
Connect
(
wxEVT_MOTION
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_LEFT_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_LEFT_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_RIGHT_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_RIGHT_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MIDDLE_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MIDDLE_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MOUSEWHEEL
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_CHAR_HOOK
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
skipEvent
)
);
Connect
(
wxEVT_KEY_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_KEY_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MOTION
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_LEFT_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_LEFT_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_RIGHT_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_RIGHT_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MIDDLE_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MIDDLE_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_MOUSEWHEEL
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_CHAR_HOOK
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
skipEvent
)
);
Connect
(
wxEVT_KEY_UP
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_KEY_DOWN
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
Connect
(
wxEVT_ENTER_WINDOW
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEnter
),
NULL
,
this
);
Connect
(
KiGfx
::
WX_VIEW_CONTROLS
::
EVT_REFRESH_MOUSE
,
wxEventHandler
(
EDA_DRAW_PANEL_GAL
::
onEvent
),
NULL
,
this
);
m_refreshTimer
.
SetOwner
(
this
);
Connect
(
wxEVT_TIMER
,
wxTimerEventHandler
(
EDA_DRAW_PANEL_GAL
::
onRefreshTimer
),
NULL
,
this
);
...
...
@@ -171,7 +171,7 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
m_refreshTimer
.
Start
(
(
MinRefreshPeriod
-
delta
).
ToLong
(),
true
);
m_pendingRefresh
=
true
;
}
}
}
void
EDA_DRAW_PANEL_GAL
::
SwitchBackend
(
GalType
aGalType
)
...
...
@@ -223,13 +223,13 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
void
EDA_DRAW_PANEL_GAL
::
onEvent
(
wxEvent
&
aEvent
)
{
if
(
!
m_eventDispatcher
)
{
aEvent
.
Skip
();
return
;
}
else
{
if
(
!
m_eventDispatcher
)
{
aEvent
.
Skip
();
return
;
}
else
{
m_eventDispatcher
->
DispatchWxEvent
(
aEvent
);
}
...
...
common/gal/color4d.cpp
View file @
22045b61
...
...
@@ -159,7 +159,6 @@ void COLOR4D::FromHSV( double aInH, double aInS, double aInV )
b
=
q
;
break
;
}
}
...
...
@@ -168,7 +167,7 @@ COLOR4D& COLOR4D::Saturate( double aFactor )
double
h
,
s
,
v
;
ToHSV
(
h
,
s
,
v
);
FromHSV
(
h
,
aFactor
,
1.0
);
return
*
this
;
}
common/gal/opengl/opengl_gal.cpp
View file @
22045b61
...
...
@@ -127,7 +127,7 @@ void OPENGL_GAL::BeginDrawing()
glViewport
(
0
,
0
,
(
GLsizei
)
screenSize
.
x
,
(
GLsizei
)
screenSize
.
y
);
// Create the screen transformation
glOrtho
(
0
,
(
GLint
)
screenSize
.
x
,
0
,
(
GLsizei
)
screenSize
.
y
,
glOrtho
(
0
,
(
GLint
)
screenSize
.
x
,
0
,
(
GLsizei
)
screenSize
.
y
,
-
depthRange
.
x
,
-
depthRange
.
y
);
// Prepare rendering target buffers
...
...
common/gal/opengl/shader.frag
View file @
22045b61
...
...
@@ -49,7 +49,7 @@ void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
float
innerRadius
=
aRadius
-
(
aWidth
/
2
);
float
relWidth
=
innerRadius
/
outerRadius
;
if
(
(
dot
(
aCoord
,
aCoord
)
<
1
.
0
f
)
&&
if
(
(
dot
(
aCoord
,
aCoord
)
<
1
.
0
f
)
&&
(
dot
(
aCoord
,
aCoord
)
>
relWidth
*
relWidth
)
)
gl_FragColor
=
gl_Color
;
else
...
...
common/gal/opengl/shader.vert
View file @
22045b61
...
...
@@ -42,23 +42,23 @@ void main()
{
// Pass attributes to the fragment shader
shaderParams
=
attrShaderParams
;
if
(
shaderParams
[
0
]
==
SHADER_LINE
)
{
float
lineWidth
=
shaderParams
[
3
];
float
worldScale
=
gl_ModelViewMatrix
[
0
][
0
];
float
scale
;
// Make lines appear to be at least 1 pixel wide
if
(
worldScale
*
lineWidth
<
MIN_WIDTH
)
scale
=
MIN_WIDTH
/
(
worldScale
*
lineWidth
);
else
scale
=
1
.
0
f
;
gl_Position
=
gl_ModelViewProjectionMatrix
*
gl_Position
=
gl_ModelViewProjectionMatrix
*
(
gl_Vertex
+
vec4
(
shaderParams
.
yz
*
scale
,
0
.
0
,
0
.
0
)
);
}
else
if
(
(
shaderParams
[
0
]
==
SHADER_STROKED_CIRCLE
)
||
else
if
(
(
shaderParams
[
0
]
==
SHADER_STROKED_CIRCLE
)
||
(
shaderParams
[
0
]
==
SHADER_FILLED_CIRCLE
)
)
{
// Compute relative circle coordinates basing on indices
...
...
@@ -69,7 +69,7 @@ void main()
circleCoords
=
vec2
(
sqrt
(
3
.
0
f
),
-
1
.
0
f
);
else
if
(
shaderParams
[
1
]
==
3
.
0
f
)
circleCoords
=
vec2
(
0
.
0
f
,
2
.
0
f
);
// Semicircle
else
if
(
shaderParams
[
1
]
==
4
.
0
f
)
circleCoords
=
vec2
(
-
3
.
0
f
/
sqrt
(
3
.
0
f
),
0
.
0
f
);
...
...
@@ -81,7 +81,7 @@ void main()
// Make the line appear to be at least 1 pixel wide
float
lineWidth
=
shaderParams
[
3
];
float
worldScale
=
gl_ModelViewMatrix
[
0
][
0
];
// Make lines appear to be at least 1 pixel width
if
(
worldScale
*
lineWidth
<
MIN_WIDTH
)
shaderParams
[
3
]
=
shaderParams
[
3
]
/
(
worldScale
*
lineWidth
);
...
...
@@ -93,7 +93,7 @@ void main()
// Pass through the coordinates like in the fixed pipeline
gl_Position
=
ftransform
();
}
gl_FrontColor
=
gl_Color
;
}
common/geometry/seg.cpp
View file @
22045b61
...
...
@@ -32,38 +32,38 @@ template<typename T> int sgn( T val ) {
bool
SEG
::
PointCloserThan
(
const
VECTOR2I
&
aP
,
int
dist
)
const
{
VECTOR2I
d
=
b
-
a
;
ecoord
dist_sq
=
(
ecoord
)
dist
*
dist
;
VECTOR2I
d
=
b
-
a
;
ecoord
dist_sq
=
(
ecoord
)
dist
*
dist
;
SEG
::
ecoord
l_squared
=
d
.
Dot
(
d
);
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
;
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
);
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
;
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
;
VECTOR2I
nearest
;
nearest
.
x
=
a
.
x
+
rescale
(
t
,
(
ecoord
)
d
.
x
,
l_squared
);
nearest
.
y
=
a
.
y
+
rescale
(
t
,
(
ecoord
)
d
.
y
,
l_squared
);
...
...
@@ -71,7 +71,7 @@ bool SEG::PointCloserThan( const VECTOR2I& aP, int dist ) const
}
SEG
::
ecoord
SEG
::
SquaredDistance
(
const
SEG
&
aSeg
)
const
SEG
::
ecoord
SEG
::
SquaredDistance
(
const
SEG
&
aSeg
)
const
{
// fixme: rather inefficient....
if
(
Intersect
(
aSeg
)
)
...
...
@@ -91,62 +91,62 @@ SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const
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
;
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
);
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
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
;
// 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
);
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
;
return
false
;
}
bool
SEG
::
Contains
(
const
VECTOR2I
&
aP
)
const
{
return
PointCloserThan
(
aP
,
1
);
return
PointCloserThan
(
aP
,
1
);
}
common/geometry/shape_collisions.cpp
View file @
22045b61
...
...
@@ -34,200 +34,200 @@ typedef VECTOR2I::extended_type ecoord;
static
inline
bool
Collide
(
const
SHAPE_CIRCLE
&
aA
,
const
SHAPE_CIRCLE
&
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
ecoord
min_dist
=
aClearance
+
aA
.
GetRadius
()
+
aB
.
GetRadius
();
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
const
VECTOR2I
delta
=
aB
.
GetCenter
()
-
aA
.
GetCenter
();
ecoord
min_dist
=
aClearance
+
aA
.
GetRadius
()
+
aB
.
GetRadius
();
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
ecoord
dist_sq
=
delta
.
SquaredEuclideanNorm
();
const
VECTOR2I
delta
=
aB
.
GetCenter
()
-
aA
.
GetCenter
();
if
(
dist_sq
>=
min_dist_sq
)
return
false
;
if
(
aNeedMTV
)
aMTV
=
delta
.
Resize
(
sqrt
(
abs
(
min_dist_sq
-
dist_sq
)
)
+
1
);
ecoord
dist_sq
=
delta
.
SquaredEuclideanNorm
();
return
true
;
if
(
dist_sq
>=
min_dist_sq
)
return
false
;
if
(
aNeedMTV
)
aMTV
=
delta
.
Resize
(
sqrt
(
abs
(
min_dist_sq
-
dist_sq
)
)
+
1
);
return
true
;
}
static
inline
bool
Collide
(
const
SHAPE_RECT
&
aA
,
const
SHAPE_CIRCLE
&
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
const
VECTOR2I
c
=
aB
.
GetCenter
();
const
VECTOR2I
p0
=
aA
.
GetPosition
();
const
VECTOR2I
size
=
aA
.
GetSize
();
const
ecoord
r
=
aB
.
GetRadius
();
const
ecoord
min_dist
=
aClearance
+
r
;
const
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
if
(
aA
.
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
(
!
aNeedMTV
)
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
(
!
aNeedMTV
)
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
;
const
VECTOR2I
c
=
aB
.
GetCenter
();
const
VECTOR2I
p0
=
aA
.
GetPosition
();
const
VECTOR2I
size
=
aA
.
GetSize
();
const
ecoord
r
=
aB
.
GetRadius
();
const
ecoord
min_dist
=
aClearance
+
r
;
const
ecoord
min_dist_sq
=
min_dist
*
min_dist
;
if
(
aA
.
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
(
!
aNeedMTV
)
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
(
!
aNeedMTV
)
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
&
aA
,
const
SHAPE_LINE_CHAIN
&
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
s
=
0
;
s
<
aB
.
SegmentCount
();
s
++
)
{
if
(
aA
.
Collide
(
aB
.
CSegment
(
s
),
aClearance
)
)
return
true
;
}
return
false
;
for
(
int
s
=
0
;
s
<
aB
.
SegmentCount
();
s
++
)
{
if
(
aA
.
Collide
(
aB
.
CSegment
(
s
),
aClearance
)
)
return
true
;
}
return
false
;
}
static
inline
bool
Collide
(
const
SHAPE_LINE_CHAIN
&
aA
,
const
SHAPE_LINE_CHAIN
&
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
i
=
0
;
i
<
aB
.
SegmentCount
();
i
++
)
if
(
aA
.
Collide
(
aB
.
CSegment
(
i
),
aClearance
)
)
return
true
;
return
false
;
for
(
int
i
=
0
;
i
<
aB
.
SegmentCount
();
i
++
)
if
(
aA
.
Collide
(
aB
.
CSegment
(
i
),
aClearance
)
)
return
true
;
return
false
;
}
static
inline
bool
Collide
(
const
SHAPE_RECT
&
aA
,
const
SHAPE_LINE_CHAIN
&
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
for
(
int
s
=
0
;
s
<
aB
.
SegmentCount
();
s
++
)
{
SEG
seg
=
aB
.
CSegment
(
s
);
if
(
aA
.
Collide
(
seg
,
aClearance
)
)
return
true
;
}
return
false
;
for
(
int
s
=
0
;
s
<
aB
.
SegmentCount
();
s
++
)
{
SEG
seg
=
aB
.
CSegment
(
s
);
if
(
aA
.
Collide
(
seg
,
aClearance
)
)
return
true
;
}
return
false
;
}
bool
CollideShapes
(
const
SHAPE
*
aA
,
const
SHAPE
*
aB
,
int
aClearance
,
bool
aNeedMTV
,
VECTOR2I
&
aMTV
)
{
switch
(
aA
->
Type
()
)
{
case
SH_RECT
:
switch
(
aB
->
Type
()
)
{
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aA
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
default:
break
;
}
case
SH_CIRCLE
:
switch
(
aB
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aB
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
default:
break
;
}
case
SH_LINE_CHAIN
:
switch
(
aB
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aB
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
default:
break
;
}
default:
break
;
}
bool
unsupported_collision
=
true
;
assert
(
unsupported_collision
==
false
);
return
false
;
switch
(
aA
->
Type
()
)
{
case
SH_RECT
:
switch
(
aB
->
Type
()
)
{
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aA
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
default:
break
;
}
case
SH_CIRCLE
:
switch
(
aB
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aB
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
aMTV
);
default:
break
;
}
case
SH_LINE_CHAIN
:
switch
(
aB
->
Type
()
)
{
case
SH_RECT
:
return
Collide
(
*
static_cast
<
const
SHAPE_RECT
*>
(
aB
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_CIRCLE
:
return
Collide
(
*
static_cast
<
const
SHAPE_CIRCLE
*>
(
aB
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
aClearance
,
aNeedMTV
,
aMTV
);
case
SH_LINE_CHAIN
:
return
Collide
(
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aA
),
*
static_cast
<
const
SHAPE_LINE_CHAIN
*>
(
aB
),
aClearance
,
aNeedMTV
,
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
);
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
);
VECTOR2I
dummy
;
return
CollideShapes
(
this
,
aShape
,
aClerance
,
false
,
dummy
);
}
common/geometry/shape_line_chain.cpp
View file @
22045b61
...
...
@@ -30,491 +30,491 @@ using boost::optional;
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
VECTOR2I
&
aP
,
int
aClearance
)
const
{
assert
(
false
);
return
false
;
assert
(
false
);
return
false
;
}
bool
SHAPE_LINE_CHAIN
::
Collide
(
const
BOX2I
&
aBox
,
int
aClearance
)
const
{
assert
(
false
);
return
false
;
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
;
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
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
;
SHAPE_LINE_CHAIN
a
(
*
this
);
reverse
(
a
.
m_points
.
begin
(),
a
.
m_points
.
end
()
);
a
.
m_closed
=
m_closed
;
return
a
;
return
a
;
}
int
SHAPE_LINE_CHAIN
::
Length
()
const
{
int
l
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
l
+=
CSegment
(
i
).
Length
();
int
l
=
0
;
for
(
int
i
=
0
;
i
<
SegmentCount
();
i
++
)
l
+=
CSegment
(
i
).
Length
();
return
l
;
return
l
;
}
void
SHAPE_LINE_CHAIN
::
Replace
(
int
aStartIndex
,
int
aEndIndex
,
const
VECTOR2I
&
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
;
}
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
aStartIndex
,
int
aEndIndex
,
const
SHAPE_LINE_CHAIN
&
aLine
)
{
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
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
()
);
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
aStartIndex
,
int
aEndIndex
)
{
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
m_points
.
erase
(
m_points
.
begin
()
+
aStartIndex
,
m_points
.
begin
()
+
aEndIndex
+
1
);
m_points
.
erase
(
m_points
.
begin
()
+
aStartIndex
,
m_points
.
begin
()
+
aEndIndex
+
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
)
);
int
d
=
INT_MAX
;
for
(
int
s
=
0
;
s
<
SegmentCount
();
s
++
)
d
=
min
(
d
,
CSegment
(
s
).
Distance
(
aP
)
);
return
d
;
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
;
}
}
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
);
if
(
ii
>=
0
)
{
m_points
.
insert
(
m_points
.
begin
()
+
ii
+
1
,
aP
);
return
ii
+
1
;
}
return
ii
+
1
;
}
return
-
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
;
for
(
int
s
=
0
;
s
<
PointCount
();
s
++
)
if
(
CPoint
(
s
)
==
aP
)
return
s
;
return
-
1
;
return
-
1
;
}
const
SHAPE_LINE_CHAIN
SHAPE_LINE_CHAIN
::
Slice
(
int
aStartIndex
,
int
aEndIndex
)
const
{
SHAPE_LINE_CHAIN
rv
;
if
(
aEndIndex
<
0
)
aEndIndex
+=
PointCount
();
if
(
aStartIndex
<
0
)
aStartIndex
+=
PointCount
();
SHAPE_LINE_CHAIN
rv
;
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
=
aStartIndex
;
i
<=
aEndIndex
;
i
++
)
rv
.
Append
(
m_points
[
i
]
);
return
rv
;
return
rv
;
}
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
SHAPE_LINE_CHAIN
::
Intersection
&
aA
,
const
SHAPE_LINE_CHAIN
::
Intersection
&
aB
)
{
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
p
).
EuclideanNorm
();
}
bool
operator
()(
const
SHAPE_LINE_CHAIN
::
Intersection
&
aA
,
const
SHAPE_LINE_CHAIN
::
Intersection
&
aB
)
{
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
p
).
EuclideanNorm
();
}
VECTOR2I
m_origin
;
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
();
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
();
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
;
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
;
if
(
!
m_closed
||
SegmentCount
()
<
3
)
return
false
;
int
cur
=
CSegment
(
0
).
Side
(
aP
);
int
cur
=
CSegment
(
0
).
Side
(
aP
);
if
(
cur
==
0
)
return
false
;
if
(
cur
==
0
)
return
false
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
s
=
CSegment
(
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!
return
false
;
if
(
aP
==
s
.
a
||
aP
==
s
.
b
)
// edge does not belong to the interior!
return
false
;
if
(
s
.
Side
(
aP
)
!=
cur
)
return
false
;
if
(
s
.
Side
(
aP
)
!=
cur
)
return
false
;
}
return
true
;
return
true
;
}
bool
SHAPE_LINE_CHAIN
::
PointOnEdge
(
const
VECTOR2I
&
aP
)
const
{
if
(
SegmentCount
()
<
1
)
return
m_points
[
0
]
==
aP
;
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
;
for
(
int
i
=
1
;
i
<
SegmentCount
();
i
++
)
{
const
SEG
s
=
CSegment
(
i
);
if
(
s
.
Distance
(
aP
)
<=
1
)
return
true
;
}
if
(
s
.
a
==
aP
||
s
.
b
==
aP
)
return
true
;
return
false
;
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
>
();
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
;
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
=
0
;
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
);
int
min_d
=
INT_MAX
;
int
nearest
=
0
;
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
;
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
();
return
ss
.
str
();
}
common/system/fcontext.s
View file @
22045b61
/*
Boost::Context assembly wrapper - done to avoid compiling the whole boost binary library
which may be unpleasant, in particular under Windows (we don't support VC++, while boost::context
does not support mingw */
Boost::Context assembly wrapper - done to avoid compiling the whole boost binary library
which may be unpleasant, in particular under Windows (we don't support VC++, while boost::context
does not support mingw */
#ifdef __APPLE__
...
...
common/system/make_i386_pe_gas.S
View file @
22045b61
...
...
@@ -9,39 +9,39 @@
.align 2
_make_fcontext:
mov 0x4(%esp),%eax
lea -0x34(%eax),%eax
and $0xfffffff0,%eax
mov 0x4(%esp),%ecx
mov %ecx,0x18(%eax)
mov 0x8(%esp),%edx
mov %edx,0x1c(%eax)
neg %edx
lea (%edx,%ecx,1),%ecx
mov %ecx,0x20(%eax)
mov 0xc(%esp),%ecx
mov %ecx,0x14(%eax)
stmxcsr 0x2c(%eax)
fnstcw 0x30(%eax)
lea -0x1c(%eax),%edx
mov %edx,0x10(%eax)
mov $0x0,%ecx
mov %ecx,(%edx)
mov %fs:0x18,%ecx
mov (%ecx),%edx
inc %edx
je _make_fcontext+0x4c // <_make_fcontext+0x4c>
dec %edx
xchg %edx,%ecx
jmp _make_fcontext+0x42 // <_make_fcontext+0x42>
mov 0x4(%ecx),%ecx
mov 0x10(%eax),%edx
mov %ecx,0x18(%edx)
mov $0xffffffff,%ecx
mov %ecx,0x14(%edx)
lea 0x14(%edx),%ecx
mov %ecx,0x24(%eax)
ret
mov 0x4(%esp),%eax
lea -0x34(%eax),%eax
and $0xfffffff0,%eax
mov 0x4(%esp),%ecx
mov %ecx,0x18(%eax)
mov 0x8(%esp),%edx
mov %edx,0x1c(%eax)
neg %edx
lea (%edx,%ecx,1),%ecx
mov %ecx,0x20(%eax)
mov 0xc(%esp),%ecx
mov %ecx,0x14(%eax)
stmxcsr 0x2c(%eax)
fnstcw 0x30(%eax)
lea -0x1c(%eax),%edx
mov %edx,0x10(%eax)
mov $0x0,%ecx
mov %ecx,(%edx)
mov %fs:0x18,%ecx
mov (%ecx),%edx
inc %edx
je _make_fcontext+0x4c // <_make_fcontext+0x4c>
dec %edx
xchg %edx,%ecx
jmp _make_fcontext+0x42 // <_make_fcontext+0x42>
mov 0x4(%ecx),%ecx
mov 0x10(%eax),%edx
mov %ecx,0x18(%edx)
mov $0xffffffff,%ecx
mov %ecx,0x14(%edx)
lea 0x14(%edx),%ecx
mov %ecx,0x24(%eax)
ret
finish:
xor %eax,%eax
...
...
common/tool/context_menu.cpp
View file @
22045b61
...
...
@@ -31,14 +31,14 @@
CONTEXT_MENU
::
CONTEXT_MENU
()
:
m_titleSet
(
false
),
m_handler
(
this
),
m_tool
(
NULL
)
{
m_menu
.
Connect
(
wxEVT_MENU_HIGHLIGHT
,
wxEventHandler
(
CMEventHandler
::
onEvent
),
NULL
,
&
m_handler
);
m_menu
.
Connect
(
wxEVT_COMMAND_MENU_SELECTED
,
wxEventHandler
(
CMEventHandler
::
onEvent
),
NULL
,
&
m_handler
);
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent
menuEvent
(
wxEVT_MENU_HIGHLIGHT
,
-
1
,
&
m_menu
);
m_menu
.
AddPendingEvent
(
menuEvent
);
m_menu
.
Connect
(
wxEVT_MENU_HIGHLIGHT
,
wxEventHandler
(
CMEventHandler
::
onEvent
),
NULL
,
&
m_handler
);
m_menu
.
Connect
(
wxEVT_COMMAND_MENU_SELECTED
,
wxEventHandler
(
CMEventHandler
::
onEvent
),
NULL
,
&
m_handler
);
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent
menuEvent
(
wxEVT_MENU_HIGHLIGHT
,
-
1
,
&
m_menu
);
m_menu
.
AddPendingEvent
(
menuEvent
);
}
...
...
@@ -72,16 +72,16 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle )
// TODO handle an empty string (remove title and separator)
// Unfortunately wxMenu::SetTitle() does nothing..
if
(
m_titleSet
)
{
if
(
m_titleSet
)
{
m_menu
.
FindItemByPosition
(
0
)
->
SetItemLabel
(
aTitle
);
}
else
{
}
else
{
m_menu
.
InsertSeparator
(
0
);
m_menu
.
Insert
(
0
,
new
wxMenuItem
(
&
m_menu
,
-
1
,
aTitle
,
wxEmptyString
,
wxITEM_NORMAL
)
);
m_titleSet
=
true
;
}
}
}
...
...
@@ -92,7 +92,7 @@ void CONTEXT_MENU::Add( const wxString& aLabel, int aId )
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
)
);
m_menu
.
Append
(
new
wxMenuItem
(
&
m_menu
,
aId
,
aLabel
,
wxEmptyString
,
wxITEM_NORMAL
)
);
}
...
...
@@ -104,7 +104,7 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
if
(
aAction
.
HasHotKey
()
)
menuEntry
=
wxString
(
(
aAction
.
GetMenuItem
()
+
'\t'
+
getHotKeyDescription
(
aAction
)
).
c_str
(),
wxConvUTF8
);
wxConvUTF8
);
else
menuEntry
=
wxString
(
aAction
.
GetMenuItem
().
c_str
(),
wxConvUTF8
);
...
...
@@ -117,13 +117,13 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
void
CONTEXT_MENU
::
Clear
()
{
m_titleSet
=
false
;
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
)
);
// Remove all the entries from context menu
for
(
unsigned
i
=
0
;
i
<
m_menu
.
GetMenuItemCount
();
++
i
)
m_menu
.
Destroy
(
m_menu
.
FindItemByPosition
(
0
)
);
m_toolActions
.
clear
();
m_toolActions
.
clear
();
}
...
...
common/tool/tool_base.cpp
View file @
22045b61
...
...
@@ -27,23 +27,23 @@
KiGfx
::
VIEW
*
TOOL_BASE
::
getView
()
const
{
return
m_toolMgr
->
GetView
();
return
m_toolMgr
->
GetView
();
}
KiGfx
::
VIEW_CONTROLS
*
TOOL_BASE
::
getViewControls
()
const
{
return
m_toolMgr
->
GetViewControls
();
{
return
m_toolMgr
->
GetViewControls
();
}
wxWindow
*
TOOL_BASE
::
getEditFrameInt
()
const
{
return
m_toolMgr
->
GetEditFrame
();
return
m_toolMgr
->
GetEditFrame
();
}
EDA_ITEM
*
TOOL_BASE
::
getModelInt
()
const
{
return
m_toolMgr
->
GetModel
();
return
m_toolMgr
->
GetModel
();
}
common/tool/tool_dispatcher.cpp
View file @
22045b61
...
...
@@ -42,52 +42,52 @@ using boost::optional;
///> Stores information about a mouse button state
struct
TOOL_DISPATCHER
::
ButtonState
{
ButtonState
(
TOOL_MouseButtons
aButton
,
const
wxEventType
&
aDownEvent
,
const
wxEventType
&
aUpEvent
)
:
button
(
aButton
),
downEvent
(
aDownEvent
),
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
;
///> Time stamp for the last mouse button press event.
wxLongLong
downTimestamp
;
///> Restores initial state.
void
Reset
()
{
dragging
=
false
;
pressed
=
false
;
}
ButtonState
(
TOOL_MouseButtons
aButton
,
const
wxEventType
&
aDownEvent
,
const
wxEventType
&
aUpEvent
)
:
button
(
aButton
),
downEvent
(
aDownEvent
),
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
;
///> Time stamp for the last mouse button press event.
wxLongLong
downTimestamp
;
///> Restores initial state.
void
Reset
()
{
dragging
=
false
;
pressed
=
false
;
}
};
TOOL_DISPATCHER
::
TOOL_DISPATCHER
(
TOOL_MANAGER
*
aToolMgr
,
PCB_BASE_FRAME
*
aEditFrame
)
:
m_toolMgr
(
aToolMgr
),
m_editFrame
(
aEditFrame
)
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
)
);
...
...
@@ -99,135 +99,135 @@ TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditF
TOOL_DISPATCHER
::~
TOOL_DISPATCHER
()
{
BOOST_FOREACH
(
ButtonState
*
st
,
m_buttons
)
delete
st
;
BOOST_FOREACH
(
ButtonState
*
st
,
m_buttons
)
delete
st
;
}
void
TOOL_DISPATCHER
::
ResetState
()
{
BOOST_FOREACH
(
ButtonState
*
st
,
m_buttons
)
st
->
Reset
();
BOOST_FOREACH
(
ButtonState
*
st
,
m_buttons
)
st
->
Reset
();
}
KiGfx
::
VIEW
*
TOOL_DISPATCHER
::
getView
()
{
return
m_editFrame
->
GetGalCanvas
()
->
GetView
();
return
m_editFrame
->
GetGalCanvas
()
->
GetView
();
}
bool
TOOL_DISPATCHER
::
handleMouseButton
(
wxEvent
&
aEvent
,
int
aIndex
,
bool
aMotion
)
{
ButtonState
*
st
=
m_buttons
[
aIndex
];
wxEventType
type
=
aEvent
.
GetEventType
();
optional
<
TOOL_EVENT
>
evt
;
bool
isClick
=
false
;
bool
up
=
type
==
st
->
upEvent
;
bool
down
=
type
==
st
->
downEvent
;
int
mods
=
decodeModifiers
<
wxMouseEvent
>
(
static_cast
<
wxMouseEvent
*>
(
&
aEvent
)
);
int
args
=
st
->
button
|
mods
;
if
(
down
)
// Handle mouse button press
{
st
->
downTimestamp
=
wxGetLocalTimeMillis
();
st
->
dragOrigin
=
m_lastMousePos
;
st
->
downPosition
=
m_lastMousePos
;
st
->
dragMaxDelta
=
0
;
st
->
pressed
=
true
;
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseDown
,
args
);
}
else
if
(
up
)
// Handle mouse button release
{
st
->
pressed
=
false
;
if
(
st
->
dragging
)
{
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
;
else
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseUp
,
args
);
}
else
isClick
=
true
;
if
(
isClick
)
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseClick
,
args
);
st
->
dragging
=
false
;
}
if
(
st
->
pressed
&&
aMotion
)
{
st
->
dragging
=
true
;
double
dragPixelDistance
=
getView
()
->
ToScreen
(
m_lastMousePos
-
st
->
dragOrigin
,
false
).
EuclideanNorm
();
st
->
dragMaxDelta
=
std
::
max
(
st
->
dragMaxDelta
,
dragPixelDistance
);
wxLongLong
t
=
wxGetLocalTimeMillis
();
if
(
t
-
st
->
downTimestamp
>
DragTimeThreshold
||
st
->
dragMaxDelta
>
DragDistanceThreshold
)
{
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseDrag
,
args
);
evt
->
SetMouseDragOrigin
(
st
->
dragOrigin
);
evt
->
SetMouseDelta
(
m_lastMousePos
-
st
->
dragOrigin
);
}
}
if
(
evt
)
{
evt
->
SetMousePosition
(
isClick
?
st
->
downPosition
:
m_lastMousePos
);
m_toolMgr
->
ProcessEvent
(
*
evt
);
return
true
;
}
return
false
;
ButtonState
*
st
=
m_buttons
[
aIndex
];
wxEventType
type
=
aEvent
.
GetEventType
();
optional
<
TOOL_EVENT
>
evt
;
bool
isClick
=
false
;
bool
up
=
type
==
st
->
upEvent
;
bool
down
=
type
==
st
->
downEvent
;
int
mods
=
decodeModifiers
<
wxMouseEvent
>
(
static_cast
<
wxMouseEvent
*>
(
&
aEvent
)
);
int
args
=
st
->
button
|
mods
;
if
(
down
)
// Handle mouse button press
{
st
->
downTimestamp
=
wxGetLocalTimeMillis
();
st
->
dragOrigin
=
m_lastMousePos
;
st
->
downPosition
=
m_lastMousePos
;
st
->
dragMaxDelta
=
0
;
st
->
pressed
=
true
;
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseDown
,
args
);
}
else
if
(
up
)
// Handle mouse button release
{
st
->
pressed
=
false
;
if
(
st
->
dragging
)
{
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
;
else
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseUp
,
args
);
}
else
isClick
=
true
;
if
(
isClick
)
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseClick
,
args
);
st
->
dragging
=
false
;
}
if
(
st
->
pressed
&&
aMotion
)
{
st
->
dragging
=
true
;
double
dragPixelDistance
=
getView
()
->
ToScreen
(
m_lastMousePos
-
st
->
dragOrigin
,
false
).
EuclideanNorm
();
st
->
dragMaxDelta
=
std
::
max
(
st
->
dragMaxDelta
,
dragPixelDistance
);
wxLongLong
t
=
wxGetLocalTimeMillis
();
if
(
t
-
st
->
downTimestamp
>
DragTimeThreshold
||
st
->
dragMaxDelta
>
DragDistanceThreshold
)
{
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseDrag
,
args
);
evt
->
SetMouseDragOrigin
(
st
->
dragOrigin
);
evt
->
SetMouseDelta
(
m_lastMousePos
-
st
->
dragOrigin
);
}
}
if
(
evt
)
{
evt
->
SetMousePosition
(
isClick
?
st
->
downPosition
:
m_lastMousePos
);
m_toolMgr
->
ProcessEvent
(
*
evt
);
return
true
;
}
return
false
;
}
void
TOOL_DISPATCHER
::
DispatchWxEvent
(
wxEvent
&
aEvent
)
{
bool
motion
=
false
,
buttonEvents
=
false
;
optional
<
TOOL_EVENT
>
evt
;
int
type
=
aEvent
.
GetEventType
();
// Mouse handling
if
(
type
==
wxEVT_MOTION
||
type
==
wxEVT_MOUSEWHEEL
||
type
==
wxEVT_LEFT_DOWN
||
type
==
wxEVT_LEFT_UP
||
type
==
wxEVT_MIDDLE_DOWN
||
type
==
wxEVT_MIDDLE_UP
||
type
==
wxEVT_RIGHT_DOWN
||
type
==
wxEVT_RIGHT_UP
||
// Event issued whem mouse retains position in screen coordinates,
// but changes in world coordinates (eg. autopanning)
type
==
KiGfx
::
WX_VIEW_CONTROLS
::
EVT_REFRESH_MOUSE
)
{
bool
motion
=
false
,
buttonEvents
=
false
;
optional
<
TOOL_EVENT
>
evt
;
int
type
=
aEvent
.
GetEventType
();
// Mouse handling
if
(
type
==
wxEVT_MOTION
||
type
==
wxEVT_MOUSEWHEEL
||
type
==
wxEVT_LEFT_DOWN
||
type
==
wxEVT_LEFT_UP
||
type
==
wxEVT_MIDDLE_DOWN
||
type
==
wxEVT_MIDDLE_UP
||
type
==
wxEVT_RIGHT_DOWN
||
type
==
wxEVT_RIGHT_UP
||
// Event issued whem mouse retains position in screen coordinates,
// but changes in world coordinates (eg. autopanning)
type
==
KiGfx
::
WX_VIEW_CONTROLS
::
EVT_REFRESH_MOUSE
)
{
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
;
m_lastMousePos
=
pos
;
}
if
(
pos
!=
m_lastMousePos
||
type
==
KiGfx
::
WX_VIEW_CONTROLS
::
EVT_REFRESH_MOUSE
)
{
motion
=
true
;
m_lastMousePos
=
pos
;
}
for
(
unsigned
int
i
=
0
;
i
<
m_buttons
.
size
();
i
++
)
buttonEvents
|=
handleMouseButton
(
aEvent
,
i
,
motion
);
for
(
unsigned
int
i
=
0
;
i
<
m_buttons
.
size
();
i
++
)
buttonEvents
|=
handleMouseButton
(
aEvent
,
i
,
motion
);
if
(
!
buttonEvents
&&
motion
)
{
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseMotion
);
evt
->
SetMousePosition
(
pos
);
}
}
if
(
!
buttonEvents
&&
motion
)
{
evt
=
TOOL_EVENT
(
TC_Mouse
,
TA_MouseMotion
);
evt
->
SetMousePosition
(
pos
);
}
}
// Keyboard handling
else
if
(
type
==
wxEVT_KEY_UP
||
type
==
wxEVT_KEY_DOWN
)
// Keyboard handling
else
if
(
type
==
wxEVT_KEY_UP
||
type
==
wxEVT_KEY_DOWN
)
{
wxKeyEvent
*
ke
=
static_cast
<
wxKeyEvent
*>
(
&
aEvent
);
int
key
=
ke
->
GetKeyCode
();
...
...
@@ -246,33 +246,33 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
}
}
if
(
evt
)
m_toolMgr
->
ProcessEvent
(
*
evt
);
if
(
evt
)
m_toolMgr
->
ProcessEvent
(
*
evt
);
// pass the event to the GUI, it might still be interested in it
aEvent
.
Skip
();
// pass the event to the GUI, it might still be interested in it
aEvent
.
Skip
();
}
void
TOOL_DISPATCHER
::
DispatchWxCommand
(
const
wxCommandEvent
&
aEvent
)
{
bool
activateTool
=
false
;
std
::
string
toolName
;
// fixme: use TOOL_ACTIONs here
switch
(
aEvent
.
GetId
()
)
{
case
ID_PNS_ROUTER_TOOL
:
toolName
=
"pcbnew.InteractiveRouter"
;
activateTool
=
true
;
break
;
case
ID_SELECTION_TOOL
:
toolName
=
"pcbnew.InteractiveSelection"
;
activateTool
=
true
;
break
;
}
// do nothing if the legacy view is active
if
(
activateTool
&&
m_editFrame
->
IsGalCanvasActive
()
)
m_toolMgr
->
InvokeTool
(
toolName
);
bool
activateTool
=
false
;
std
::
string
toolName
;
// fixme: use TOOL_ACTIONs here
switch
(
aEvent
.
GetId
()
)
{
case
ID_PNS_ROUTER_TOOL
:
toolName
=
"pcbnew.InteractiveRouter"
;
activateTool
=
true
;
break
;
case
ID_SELECTION_TOOL
:
toolName
=
"pcbnew.InteractiveSelection"
;
activateTool
=
true
;
break
;
}
// do nothing if the legacy view is active
if
(
activateTool
&&
m_editFrame
->
IsGalCanvasActive
()
)
m_toolMgr
->
InvokeTool
(
toolName
);
}
common/tool/tool_event.cpp
View file @
22045b61
...
...
@@ -35,22 +35,22 @@ using namespace std;
struct
FlagString
{
int
flag
;
std
::
string
str
;
int
flag
;
std
::
string
str
;
};
static
const
std
::
string
flag2string
(
int
flag
,
const
FlagString
*
exps
)
{
std
::
string
rv
;
std
::
string
rv
;
for
(
int
i
=
0
;
exps
[
i
].
str
.
length
();
i
++
)
{
if
(
exps
[
i
].
flag
&
flag
)
rv
+=
exps
[
i
].
str
+
" "
;
}
for
(
int
i
=
0
;
exps
[
i
].
str
.
length
();
i
++
)
{
if
(
exps
[
i
].
flag
&
flag
)
rv
+=
exps
[
i
].
str
+
" "
;
}
return
rv
;
return
rv
;
}
...
...
@@ -62,97 +62,97 @@ bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const
const
std
::
string
TOOL_EVENT
::
Format
()
const
{
std
::
string
ev
;
const
FlagString
categories
[]
=
{
{
TC_Mouse
,
"mouse"
},
{
TC_Keyboard
,
"keyboard"
},
{
TC_Command
,
"command"
},
{
TC_Message
,
"message"
},
{
TC_View
,
"view"
},
{
0
,
""
}
};
const
FlagString
actions
[]
=
{
{
TA_MouseClick
,
"click"
},
{
TA_MouseUp
,
"button-up"
},
{
TA_MouseDown
,
"button-down"
},
{
TA_MouseDrag
,
"drag"
},
{
TA_MouseMotion
,
"motion"
},
{
TA_MouseWheel
,
"wheel"
},
{
TA_KeyUp
,
"key-up"
},
{
TA_KeyDown
,
"key-down"
},
{
TA_ViewRefresh
,
"view-refresh"
},
{
TA_ViewZoom
,
"view-zoom"
},
{
TA_ViewPan
,
"view-pan"
},
{
TA_ViewDirty
,
"view-dirty"
},
{
TA_ChangeLayer
,
"change-layer"
},
{
TA_CancelTool
,
"cancel-tool"
},
{
TA_ContextMenuUpdate
,
"context-menu-update"
},
{
TA_ContextMenuChoice
,
"context-menu-choice"
},
{
TA_Action
,
"action"
},
{
0
,
""
}
};
const
FlagString
buttons
[]
=
{
{
MB_None
,
"none"
},
{
MB_Left
,
"left"
},
{
MB_Right
,
"right"
},
{
MB_Middle
,
"middle"
},
{
0
,
""
}
};
const
FlagString
modifiers
[]
=
{
std
::
string
ev
;
const
FlagString
categories
[]
=
{
{
TC_Mouse
,
"mouse"
},
{
TC_Keyboard
,
"keyboard"
},
{
TC_Command
,
"command"
},
{
TC_Message
,
"message"
},
{
TC_View
,
"view"
},
{
0
,
""
}
};
const
FlagString
actions
[]
=
{
{
TA_MouseClick
,
"click"
},
{
TA_MouseUp
,
"button-up"
},
{
TA_MouseDown
,
"button-down"
},
{
TA_MouseDrag
,
"drag"
},
{
TA_MouseMotion
,
"motion"
},
{
TA_MouseWheel
,
"wheel"
},
{
TA_KeyUp
,
"key-up"
},
{
TA_KeyDown
,
"key-down"
},
{
TA_ViewRefresh
,
"view-refresh"
},
{
TA_ViewZoom
,
"view-zoom"
},
{
TA_ViewPan
,
"view-pan"
},
{
TA_ViewDirty
,
"view-dirty"
},
{
TA_ChangeLayer
,
"change-layer"
},
{
TA_CancelTool
,
"cancel-tool"
},
{
TA_ContextMenuUpdate
,
"context-menu-update"
},
{
TA_ContextMenuChoice
,
"context-menu-choice"
},
{
TA_Action
,
"action"
},
{
0
,
""
}
};
const
FlagString
buttons
[]
=
{
{
MB_None
,
"none"
},
{
MB_Left
,
"left"
},
{
MB_Right
,
"right"
},
{
MB_Middle
,
"middle"
},
{
0
,
""
}
};
const
FlagString
modifiers
[]
=
{
{
MD_ModShift
,
"shift"
},
{
MD_ModCtrl
,
"ctrl"
},
{
MD_ModAlt
,
"alt"
},
{
0
,
""
}
};
ev
=
"category: "
;
ev
+=
flag2string
(
m_category
,
categories
);
ev
+=
" action: "
;
ev
+=
flag2string
(
m_actions
,
actions
);
if
(
m_actions
&
TA_Mouse
)
{
ev
+=
" btns: "
;
ev
+=
flag2string
(
m_mouseButtons
,
buttons
);
}
if
(
m_actions
&
TA_Keyboard
)
{
};
ev
=
"category: "
;
ev
+=
flag2string
(
m_category
,
categories
);
ev
+=
" action: "
;
ev
+=
flag2string
(
m_actions
,
actions
);
if
(
m_actions
&
TA_Mouse
)
{
ev
+=
" btns: "
;
ev
+=
flag2string
(
m_mouseButtons
,
buttons
);
}
if
(
m_actions
&
TA_Keyboard
)
{
char
tmp
[
128
];
sprintf
(
tmp
,
"key: %d"
,
m_keyCode
);
ev
+=
tmp
;
}
if
(
m_actions
&
(
TA_Mouse
|
TA_Keyboard
)
)
{
ev
+=
" mods: "
;
ev
+=
flag2string
(
m_modifiers
,
modifiers
);
}
if
(
m_commandId
)
{
char
tmp
[
128
];
sprintf
(
tmp
,
"cmd-id: %d"
,
*
m_commandId
);
ev
+=
tmp
;
}
if
(
m_commandStr
)
ev
+=
"cmd-str: "
+
(
*
m_commandStr
);
return
ev
;
}
if
(
m_actions
&
(
TA_Mouse
|
TA_Keyboard
)
)
{
ev
+=
" mods: "
;
ev
+=
flag2string
(
m_modifiers
,
modifiers
);
}
if
(
m_commandId
)
{
char
tmp
[
128
];
sprintf
(
tmp
,
"cmd-id: %d"
,
*
m_commandId
);
ev
+=
tmp
;
}
if
(
m_commandStr
)
ev
+=
"cmd-str: "
+
(
*
m_commandStr
);
return
ev
;
}
const
std
::
string
TOOL_EVENT_LIST
::
Format
()
const
{
string
s
;
string
s
;
BOOST_FOREACH
(
TOOL_EVENT
e
,
m_events
)
s
+=
e
.
Format
()
+
" "
;
BOOST_FOREACH
(
TOOL_EVENT
e
,
m_events
)
s
+=
e
.
Format
()
+
" "
;
return
s
;
return
s
;
}
common/tool/tool_interactive.cpp
View file @
22045b61
...
...
@@ -30,13 +30,13 @@
#include <tool/context_menu.h>
TOOL_INTERACTIVE
::
TOOL_INTERACTIVE
(
TOOL_ID
aId
,
const
std
::
string
&
aName
)
:
TOOL_BASE
(
TOOL_Interactive
,
aId
,
aName
)
{};
TOOL_BASE
(
TOOL_Interactive
,
aId
,
aName
)
{};
TOOL_INTERACTIVE
::
TOOL_INTERACTIVE
(
const
std
::
string
&
aName
)
:
TOOL_BASE
(
TOOL_Interactive
,
TOOL_MANAGER
::
MakeToolId
(
aName
),
aName
)
{};
TOOL_BASE
(
TOOL_Interactive
,
TOOL_MANAGER
::
MakeToolId
(
aName
),
aName
)
{};
TOOL_INTERACTIVE
::~
TOOL_INTERACTIVE
()
...
...
@@ -46,18 +46,18 @@ TOOL_INTERACTIVE::~TOOL_INTERACTIVE()
OPT_TOOL_EVENT
TOOL_INTERACTIVE
::
Wait
(
const
TOOL_EVENT_LIST
&
aEventList
)
{
return
m_toolMgr
->
ScheduleWait
(
this
,
aEventList
);
return
m_toolMgr
->
ScheduleWait
(
this
,
aEventList
);
}
void
TOOL_INTERACTIVE
::
goInternal
(
TOOL_STATE_FUNC
&
aState
,
const
TOOL_EVENT_LIST
&
aConditions
)
{
m_toolMgr
->
ScheduleNextState
(
this
,
aState
,
aConditions
);
m_toolMgr
->
ScheduleNextState
(
this
,
aState
,
aConditions
);
}
void
TOOL_INTERACTIVE
::
SetContextMenu
(
CONTEXT_MENU
*
aMenu
,
CONTEXT_MENU_TRIGGER
aTrigger
)
{
aMenu
->
setTool
(
this
);
m_toolMgr
->
ScheduleContextMenu
(
this
,
aMenu
,
aTrigger
);
aMenu
->
setTool
(
this
);
m_toolMgr
->
ScheduleContextMenu
(
this
,
aMenu
,
aTrigger
);
}
common/tool/tool_manager.cpp
View file @
22045b61
...
...
@@ -52,50 +52,50 @@ using namespace std;
struct
TOOL_MANAGER
::
TOOL_STATE
{
/// The tool itself
TOOL_BASE
*
theTool
;
/// Is the tool active (pending execution) or disabled at the moment
bool
idle
;
TOOL_BASE
*
theTool
;
/// Flag defining if the tool is waiting for any event (i.e. if it
/// issued a Wait() call).
bool
pendingWait
;
/// Is the tool active (pending execution) or disabled at the moment
bool
idle
;
/// Is there a context menu being displayed
bool
pendingContextMenu
;
/// Flag defining if the tool is waiting for any event (i.e. if it
/// issued a Wait() call).
bool
pendingWait
;
/// Context menu currently used by the tool
CONTEXT_MENU
*
c
ontextMenu
;
/// Is there a context menu being displayed
bool
pendingC
ontextMenu
;
/// Defines when the context menu is opened
CONTEXT_MENU_TRIGGER
contextMenuTrigger
;
/// Context menu currently used by the tool
CONTEXT_MENU
*
contextMenu
;
/// Tool execution context
COROUTINE
<
int
,
TOOL_EVENT
&>*
cofunc
;
/// The event that triggered the execution/wakeup of the tool after Wait() call
TOOL_EVENT
wakeupEvent
;
/// Defines when the context menu is opened
CONTEXT_MENU_TRIGGER
contextMenuTrigger
;
/// List of events the tool is currently waiting for
TOOL_EVENT_LIST
waitEvents
;
/// Tool execution context
COROUTINE
<
int
,
TOOL_EVENT
&>*
cofunc
;
/// List of possible transitions (ie. association of events and state handlers that are executed
/// upon the event reception
std
::
vector
<
TRANSITION
>
transitions
;
/// The event that triggered the execution/wakeup of the tool after Wait() call
TOOL_EVENT
wakeupEvent
;
bool
operator
==
(
const
TOOL_MANAGER
::
TOOL_STATE
&
aRhs
)
const
/// List of events the tool is currently waiting for
TOOL_EVENT_LIST
waitEvents
;
/// List of possible transitions (ie. association of events and state handlers that are executed
/// upon the event reception
std
::
vector
<
TRANSITION
>
transitions
;
bool
operator
==
(
const
TOOL_MANAGER
::
TOOL_STATE
&
aRhs
)
const
{
return
(
aRhs
.
theTool
==
this
->
theTool
);
return
(
aRhs
.
theTool
==
this
->
theTool
);
}
bool
operator
!=
(
const
TOOL_MANAGER
::
TOOL_STATE
&
aRhs
)
const
bool
operator
!=
(
const
TOOL_MANAGER
::
TOOL_STATE
&
aRhs
)
const
{
return
(
aRhs
.
theTool
!=
this
->
theTool
);
return
(
aRhs
.
theTool
!=
this
->
theTool
);
}
};
TOOL_MANAGER
::
TOOL_MANAGER
()
:
TOOL_MANAGER
::
TOOL_MANAGER
()
:
m_model
(
NULL
),
m_view
(
NULL
)
{
m_actionMgr
=
new
ACTION_MANAGER
(
this
);
...
...
@@ -119,37 +119,37 @@ TOOL_MANAGER::~TOOL_MANAGER()
void
TOOL_MANAGER
::
RegisterTool
(
TOOL_BASE
*
aTool
)
{
TOOL_STATE
*
st
=
new
TOOL_STATE
;
st
->
theTool
=
aTool
;
st
->
idle
=
true
;
st
->
pendingWait
=
false
;
st
->
pendingContextMenu
=
false
;
st
->
cofunc
=
NULL
;
st
->
contextMenuTrigger
=
CMENU_OFF
;
m_toolState
[
aTool
]
=
st
;
m_toolNameIndex
[
aTool
->
GetName
()]
=
st
;
m_toolIdIndex
[
aTool
->
GetId
()]
=
st
;
aTool
->
m_toolMgr
=
this
;
if
(
aTool
->
GetType
()
==
TOOL_Interactive
)
{
bool
initState
=
static_cast
<
TOOL_INTERACTIVE
*>
(
aTool
)
->
Init
();
if
(
!
initState
)
{
wxLogError
(
wxT
(
"Initialization of the %s tool failed"
),
aTool
->
GetName
().
c_str
()
);
// Unregister the tool
m_toolState
.
erase
(
aTool
);
m_toolNameIndex
.
erase
(
aTool
->
GetName
()
);
m_toolIdIndex
.
erase
(
aTool
->
GetId
()
);
delete
st
;
delete
aTool
;
}
}
TOOL_STATE
*
st
=
new
TOOL_STATE
;
st
->
theTool
=
aTool
;
st
->
idle
=
true
;
st
->
pendingWait
=
false
;
st
->
pendingContextMenu
=
false
;
st
->
cofunc
=
NULL
;
st
->
contextMenuTrigger
=
CMENU_OFF
;
m_toolState
[
aTool
]
=
st
;
m_toolNameIndex
[
aTool
->
GetName
()]
=
st
;
m_toolIdIndex
[
aTool
->
GetId
()]
=
st
;
aTool
->
m_toolMgr
=
this
;
if
(
aTool
->
GetType
()
==
TOOL_Interactive
)
{
bool
initState
=
static_cast
<
TOOL_INTERACTIVE
*>
(
aTool
)
->
Init
();
if
(
!
initState
)
{
wxLogError
(
wxT
(
"Initialization of the %s tool failed"
),
aTool
->
GetName
().
c_str
()
);
// Unregister the tool
m_toolState
.
erase
(
aTool
);
m_toolNameIndex
.
erase
(
aTool
->
GetName
()
);
m_toolIdIndex
.
erase
(
aTool
->
GetId
()
);
delete
st
;
delete
aTool
;
}
}
}
...
...
@@ -268,89 +268,89 @@ TOOL_BASE* TOOL_MANAGER::FindTool( const std::string& aName ) const
void
TOOL_MANAGER
::
ScheduleNextState
(
TOOL_BASE
*
aTool
,
TOOL_STATE_FUNC
&
aHandler
,
const
TOOL_EVENT_LIST
&
aConditions
)
{
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
st
->
transitions
.
push_back
(
TRANSITION
(
aConditions
,
aHandler
)
);
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
st
->
transitions
.
push_back
(
TRANSITION
(
aConditions
,
aHandler
)
);
}
optional
<
TOOL_EVENT
>
TOOL_MANAGER
::
ScheduleWait
(
TOOL_BASE
*
aTool
,
const
TOOL_EVENT_LIST
&
aConditions
)
{
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
// indicate to the manager that we are going to sleep and we shall be
// woken up when an event matching aConditions arrive
st
->
pendingWait
=
true
;
st
->
waitEvents
=
aConditions
;
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
// switch context back to event dispatcher loop
st
->
cofunc
->
Yield
();
// indicate to the manager that we are going to sleep and we shall be
// woken up when an event matching aConditions arrive
st
->
pendingWait
=
true
;
st
->
waitEvents
=
aConditions
;
return
st
->
wakeupEvent
;
// switch context back to event dispatcher loop
st
->
cofunc
->
Yield
();
return
st
->
wakeupEvent
;
}
void
TOOL_MANAGER
::
dispatchInternal
(
TOOL_EVENT
&
aEvent
)
{
// iterate over all registered tools
// iterate over all registered tools
BOOST_FOREACH
(
TOOL_ID
toolId
,
m_activeTools
)
{
TOOL_STATE
*
st
=
m_toolIdIndex
[
toolId
];
// the tool state handler is waiting for events (i.e. called Wait() method)
if
(
st
->
pendingWait
)
{
if
(
st
->
waitEvents
.
Matches
(
aEvent
)
)
{
// By default, already processed events are not passed further
m_passEvent
=
false
;
// got matching event? clear wait list and wake up the coroutine
st
->
wakeupEvent
=
aEvent
;
st
->
pendingWait
=
false
;
st
->
waitEvents
.
clear
();
if
(
st
->
cofunc
&&
!
st
->
cofunc
->
Resume
()
)
finishTool
(
st
);
// The couroutine has finished
// If the tool did not request to propagate
// the event to other tools, we should stop it now
if
(
!
m_passEvent
)
break
;
}
}
// the tool state handler is waiting for events (i.e. called Wait() method)
if
(
st
->
pendingWait
)
{
if
(
st
->
waitEvents
.
Matches
(
aEvent
)
)
{
// By default, already processed events are not passed further
m_passEvent
=
false
;
// got matching event? clear wait list and wake up the coroutine
st
->
wakeupEvent
=
aEvent
;
st
->
pendingWait
=
false
;
st
->
waitEvents
.
clear
();
if
(
st
->
cofunc
&&
!
st
->
cofunc
->
Resume
()
)
finishTool
(
st
);
// The couroutine has finished
// If the tool did not request to propagate
// the event to other tools, we should stop it now
if
(
!
m_passEvent
)
break
;
}
}
}
BOOST_FOREACH
(
TOOL_STATE
*
st
,
m_toolState
|
boost
::
adaptors
::
map_values
)
{
// the tool scheduled next state(s) by calling Go()
if
(
!
st
->
pendingWait
)
{
// no state handler in progress - check if there are any transitions (defined by
// Go() method that match the event.
if
(
st
->
transitions
.
size
()
)
{
BOOST_FOREACH
(
TRANSITION
tr
,
st
->
transitions
)
{
if
(
tr
.
first
.
Matches
(
aEvent
)
)
{
st
->
transitions
.
clear
();
// no tool context allocated yet? Create one.
if
(
!
st
->
cofunc
)
st
->
cofunc
=
new
COROUTINE
<
int
,
TOOL_EVENT
&>
(
tr
.
second
);
else
st
->
cofunc
->
SetEntry
(
tr
.
second
);
// got match? Run the handler.
st
->
cofunc
->
Call
(
aEvent
);
if
(
!
st
->
cofunc
->
Running
()
)
finishTool
(
st
);
// The couroutine has finished immediately?
}
}
}
}
}
if
(
!
st
->
pendingWait
)
{
// no state handler in progress - check if there are any transitions (defined by
// Go() method that match the event.
if
(
st
->
transitions
.
size
()
)
{
BOOST_FOREACH
(
TRANSITION
tr
,
st
->
transitions
)
{
if
(
tr
.
first
.
Matches
(
aEvent
)
)
{
st
->
transitions
.
clear
();
// no tool context allocated yet? Create one.
if
(
!
st
->
cofunc
)
st
->
cofunc
=
new
COROUTINE
<
int
,
TOOL_EVENT
&>
(
tr
.
second
);
else
st
->
cofunc
->
SetEntry
(
tr
.
second
);
// got match? Run the handler.
st
->
cofunc
->
Call
(
aEvent
);
if
(
!
st
->
cofunc
->
Running
()
)
finishTool
(
st
);
// The couroutine has finished immediately?
}
}
}
}
}
}
...
...
@@ -411,90 +411,90 @@ void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
bool
TOOL_MANAGER
::
ProcessEvent
(
TOOL_EVENT
&
aEvent
)
{
//
wxLogDebug( "event: %s", aEvent.Format().c_str() );
//
wxLogDebug( "event: %s", aEvent.Format().c_str() );
// Early dispatch of events destined for the TOOL_MANAGER
if
(
!
dispatchStandardEvents
(
aEvent
)
)
return
false
;
dispatchInternal
(
aEvent
);
dispatchInternal
(
aEvent
);
// popup menu handling
// popup menu handling
BOOST_FOREACH
(
TOOL_ID
toolId
,
m_activeTools
)
{
TOOL_STATE
*
st
=
m_toolIdIndex
[
toolId
];
// the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
// or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
if
(
st
->
contextMenuTrigger
!=
CMENU_OFF
)
{
if
(
st
->
contextMenuTrigger
==
CMENU_BUTTON
&&
!
aEvent
.
IsClick
(
MB_Right
)
)
break
;
if
(
st
->
contextMenuTrigger
!=
CMENU_OFF
)
{
if
(
st
->
contextMenuTrigger
==
CMENU_BUTTON
&&
!
aEvent
.
IsClick
(
MB_Right
)
)
break
;
st
->
pendingWait
=
true
;
st
->
waitEvents
=
TOOL_EVENT
(
TC_Any
,
TA_Any
);
st
->
pendingWait
=
true
;
st
->
waitEvents
=
TOOL_EVENT
(
TC_Any
,
TA_Any
);
if
(
st
->
contextMenuTrigger
==
CMENU_NOW
)
st
->
contextMenuTrigger
=
CMENU_OFF
;
if
(
st
->
contextMenuTrigger
==
CMENU_NOW
)
st
->
contextMenuTrigger
=
CMENU_OFF
;
boost
::
scoped_ptr
<
CONTEXT_MENU
>
menu
(
new
CONTEXT_MENU
(
*
st
->
contextMenu
)
);
GetEditFrame
()
->
PopupMenu
(
menu
->
GetMenu
()
);
//
TOOL_EVENT
evt
(
TC_Command
,
TA_ContextMenuChoice
);
dispatchInternal
(
evt
);
TOOL_EVENT
evt
(
TC_Command
,
TA_ContextMenuChoice
);
dispatchInternal
(
evt
);
break
;
}
}
break
;
}
}
if
(
m_view
->
IsDirty
()
)
{
PCB_EDIT_FRAME
*
f
=
static_cast
<
PCB_EDIT_FRAME
*>
(
GetEditFrame
()
);
f
->
GetGalCanvas
()
->
Refresh
();
// fixme: ugly hack, provide a method in TOOL_DISPATCHER.
}
if
(
m_view
->
IsDirty
()
)
{
PCB_EDIT_FRAME
*
f
=
static_cast
<
PCB_EDIT_FRAME
*>
(
GetEditFrame
()
);
f
->
GetGalCanvas
()
->
Refresh
();
// fixme: ugly hack, provide a method in TOOL_DISPATCHER.
}
return
false
;
return
false
;
}
void
TOOL_MANAGER
::
ScheduleContextMenu
(
TOOL_BASE
*
aTool
,
CONTEXT_MENU
*
aMenu
,
CONTEXT_MENU_TRIGGER
aTrigger
)
{
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
st
->
contextMenu
=
aMenu
;
st
->
contextMenuTrigger
=
aTrigger
;
// the tool wants the menu immediately? Preempt it and do so :)
if
(
aTrigger
==
CMENU_NOW
)
st
->
cofunc
->
Yield
();
TOOL_STATE
*
st
=
m_toolState
[
aTool
];
st
->
contextMenu
=
aMenu
;
st
->
contextMenuTrigger
=
aTrigger
;
// the tool wants the menu immediately? Preempt it and do so :)
if
(
aTrigger
==
CMENU_NOW
)
st
->
cofunc
->
Yield
();
}
TOOL_ID
TOOL_MANAGER
::
MakeToolId
(
const
std
::
string
&
aToolName
)
{
static
int
currentId
;
return
currentId
++
;
static
int
currentId
;
return
currentId
++
;
}
void
TOOL_MANAGER
::
SetEnvironment
(
EDA_ITEM
*
aModel
,
KiGfx
::
VIEW
*
aView
,
KiGfx
::
VIEW_CONTROLS
*
aViewControls
,
wxWindow
*
aFrame
)
{
m_model
=
aModel
;
m_view
=
aView
;
m_viewControls
=
aViewControls
;
m_editFrame
=
aFrame
;
// Reset state of the registered tools
BOOST_FOREACH
(
TOOL_ID
toolId
,
m_activeTools
)
{
TOOL_BASE
*
tool
=
m_toolIdIndex
[
toolId
]
->
theTool
;
if
(
tool
->
GetType
()
==
TOOL_Interactive
)
static_cast
<
TOOL_INTERACTIVE
*>
(
tool
)
->
Reset
();
}
m_model
=
aModel
;
m_view
=
aView
;
m_viewControls
=
aViewControls
;
m_editFrame
=
aFrame
;
// Reset state of the registered tools
BOOST_FOREACH
(
TOOL_ID
toolId
,
m_activeTools
)
{
TOOL_BASE
*
tool
=
m_toolIdIndex
[
toolId
]
->
theTool
;
if
(
tool
->
GetType
()
==
TOOL_Interactive
)
static_cast
<
TOOL_INTERACTIVE
*>
(
tool
)
->
Reset
();
}
}
...
...
include/class_drawpanel_gal.h
View file @
22045b61
...
...
@@ -87,7 +87,7 @@ public:
{
return
m_view
;
}
/**
* Function GetViewControls()
* Returns a pointer to the VIEW_CONTROLS instance used in the panel.
...
...
include/gal/color4d.h
View file @
22045b61
...
...
@@ -131,7 +131,7 @@ public:
* Saturates the color to a given factor (in HSV model)
*/
COLOR4D
&
Saturate
(
double
aFactor
);
/**
* Function Brightened
* Returns a color that is brighter by a given factor, without modifying object.
...
...
include/gal/opengl/shader.h
View file @
22045b61
...
...
@@ -172,11 +172,11 @@ private:
void
programInfo
(
GLuint
aProgram
);
/**
* @brief Get the shader information.
*
* @param aShader is the shader number.
*/
void
shaderInfo
(
GLuint
aShader
);
* @brief Get the shader information.
*
* @param aShader is the shader number.
*/
void
shaderInfo
(
GLuint
aShader
);
/**
* @brief Read the shader source file
...
...
include/geometry/seg.h
View file @
22045b61
...
...
@@ -36,278 +36,278 @@ 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 (aX1, aY1) and (aX2, aY2), locally referenced
*/
SEG
(
int
aX1
,
int
aY1
,
int
aX2
,
int
aY2
)
:
a
(
m_a
),
b
(
m_b
)
{
m_a
=
VECTOR2I
(
aX1
,
aY1
);
m_b
=
VECTOR2I
(
aX2
,
aY2
);
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
&
aSeg
)
:
a
(
m_a
),
b
(
m_b
)
{
if
(
aSeg
.
m_is_local
)
{
m_a
=
aSeg
.
m_a
;
m_b
=
aSeg
.
m_b
;
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
else
{
a
=
aSeg
.
a
;
b
=
aSeg
.
b
;
m_index
=
aSeg
.
m_index
;
m_is_local
=
false
;
}
}
SEG
&
operator
=
(
const
SEG
&
aSeg
)
{
a
=
aSeg
.
a
;
b
=
aSeg
.
b
;
m_a
=
aSeg
.
m_a
;
m_b
=
aSeg
.
m_b
;
m_index
=
aSeg
.
m_index
;
m_is_local
=
aSeg
.
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
();
}
ecoord
SquaredLength
()
const
{
return
(
a
-
b
).
SquaredEuclideanNorm
();
}
/**
* 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
aDist
)
const
;
//
friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
private
:
bool
ccw
(
const
VECTOR2I
&
aA
,
const
VECTOR2I
&
aB
,
const
VECTOR2I
&
aC
)
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
;
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 (aX1, aY1) and (aX2, aY2), locally referenced
*/
SEG
(
int
aX1
,
int
aY1
,
int
aX2
,
int
aY2
)
:
a
(
m_a
),
b
(
m_b
)
{
m_a
=
VECTOR2I
(
aX1
,
aY1
);
m_b
=
VECTOR2I
(
aX2
,
aY2
);
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
&
aSeg
)
:
a
(
m_a
),
b
(
m_b
)
{
if
(
aSeg
.
m_is_local
)
{
m_a
=
aSeg
.
m_a
;
m_b
=
aSeg
.
m_b
;
a
=
m_a
;
b
=
m_b
;
m_is_local
=
true
;
m_index
=
-
1
;
}
else
{
a
=
aSeg
.
a
;
b
=
aSeg
.
b
;
m_index
=
aSeg
.
m_index
;
m_is_local
=
false
;
}
}
SEG
&
operator
=
(
const
SEG
&
aSeg
)
{
a
=
aSeg
.
a
;
b
=
aSeg
.
b
;
m_a
=
aSeg
.
m_a
;
m_b
=
aSeg
.
m_b
;
m_index
=
aSeg
.
m_index
;
m_is_local
=
aSeg
.
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
();
}
ecoord
SquaredLength
()
const
{
return
(
a
-
b
).
SquaredEuclideanNorm
();
}
/**
* 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
aDist
)
const
;
//
friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
private
:
bool
ccw
(
const
VECTOR2I
&
aA
,
const
VECTOR2I
&
aB
,
const
VECTOR2I
&
aC
)
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
);
return
VECTOR2I
(
0
,
0
);
// fixme: numerical errors for large integers
assert
(
false
);
return
VECTOR2I
(
0
,
0
);
}
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
r
=
-
p
*
a
.
x
-
q
*
a
.
y
;
ecoord
dist
=
(
p
*
aP
.
x
+
q
*
aP
.
y
+
r
)
/
sqrt
(
p
*
p
+
q
*
q
);
...
...
@@ -321,14 +321,14 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
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
);
...
...
@@ -338,7 +338,7 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
aStream
,
const
SEG
&
aSeg
)
{
if
(
aSeg
.
m_is_local
)
aStream
<<
"[ local "
<<
aSeg
.
a
<<
" - "
<<
aSeg
.
b
<<
" ]"
;
aStream
<<
"[ local "
<<
aSeg
.
a
<<
" - "
<<
aSeg
.
b
<<
" ]"
;
return
aStream
;
}
...
...
include/geometry/shape.h
View file @
22045b61
...
...
@@ -36,109 +36,109 @@
*/
enum
ShapeType
{
SH_RECT
=
0
,
///> axis-aligned rectangle
SH_SEGMENT
,
///> line segment
SH_LINE_CHAIN
,
///> line chain (polyline)
SH_CIRCLE
///> circle
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.
*/
*/
class
SHAPE
{
protected
:
typedef
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
);
return
NULL
;
};
/**
* 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.
* @param aShape shape to check collision against
* @param aClearance minimum clearance
* @param aMTV minimum translation vector
* @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
;
protected
:
typedef
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
);
return
NULL
;
};
/**
* 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.
* @param aShape shape to check collision against
* @param aClearance minimum clearance
* @param aMTV minimum translation vector
* @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
;
};
...
...
include/geometry/shape_circle.h
View file @
22045b61
...
...
@@ -30,48 +30,48 @@
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
()
:
SHAPE
(
SH_CIRCLE
),
m_radius
(
0
)
{};
~
SHAPE_CIRCLE
()
{};
SHAPE_CIRCLE
(
const
VECTOR2I
&
aCenter
,
int
aRadius
)
:
SHAPE
(
SH_CIRCLE
),
m_radius
(
aRadius
),
m_center
(
aCenter
)
{};
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
const
VECTOR2I
rc
(
m_radius
+
aClearance
,
m_radius
+
aClearance
);
return
BOX2I
(
m_center
-
rc
,
rc
*
2
);
}
~
SHAPE_CIRCLE
()
{};
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
{
int
rc
=
aClearance
+
m_radius
;
return
aSeg
.
Distance
(
m_center
)
<=
rc
;
}
const
BOX2I
BBox
(
int
aClearance
=
0
)
const
{
const
VECTOR2I
rc
(
m_radius
+
aClearance
,
m_radius
+
aClearance
)
;
return
BOX2I
(
m_center
-
rc
,
rc
*
2
)
;
}
void
SetRadius
(
int
aRadius
)
{
m_radius
=
aRadius
;
}
bool
Collide
(
const
SEG
&
aSeg
,
int
aClearance
=
0
)
const
{
int
rc
=
aClearance
+
m_radius
;
return
aSeg
.
Distance
(
m_center
)
<=
rc
;
}
void
SetCenter
(
const
VECTOR2I
&
aCenter
)
{
m_center
=
aCenter
;
}
void
SetRadius
(
int
aRadius
)
{
m_radius
=
aRadius
;
}
int
GetRadius
()
const
{
return
m_radius
;
}
void
SetCenter
(
const
VECTOR2I
&
aCenter
)
{
m_center
=
aCenter
;
}
const
VECTOR2I
GetCenter
()
const
{
return
m_center
;
}
int
GetRadius
()
const
{
return
m_radius
;
}
const
VECTOR2I
GetCenter
()
const
{
return
m_center
;
}
private
:
int
m_radius
;
VECTOR2I
m_center
;
int
m_radius
;
VECTOR2I
m_center
;
};
#endif
include/geometry/shape_index.h
View file @
22045b61
...
...
@@ -276,11 +276,11 @@ class SHAPE_INDEX
{
BOX2I
box
=
aShape
->
BBox
();
box
.
Inflate
(
aMinDistance
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
return
this
->
m_tree
->
Search
(
min
,
max
,
aVisitor
);
int
min
[
2
]
=
{
box
.
GetX
(),
box
.
GetY
()
};
int
max
[
2
]
=
{
box
.
GetRight
(),
box
.
GetBottom
()
};
return
this
->
m_tree
->
Search
(
min
,
max
,
aVisitor
);
}
/**
...
...
include/geometry/shape_index_list.h
View file @
22045b61
...
...
@@ -29,205 +29,205 @@
template
<
class
T
>
const
SHAPE
*
defaultShapeFunctor
(
const
T
aItem
)
{
return
aItem
->
GetShape
();
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
;
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
&
aB
)
:
m_current
(
aB
.
m_current
)
{};
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
void
operator
++
()
{
++
m_current
;
}
iterator
&
operator
++
(
int
aDummy
)
{
++
m_current
;
return
*
this
;
}
bool
operator
==
(
const
iterator
&
aRhs
)
const
{
return
m_current
==
aRhs
.
m_current
;
}
bool
operator
!=
(
const
iterator
&
aRhs
)
const
{
return
m_current
!=
aRhs
.
m_current
;
}
const
iterator
&
operator
=
(
const
iterator
&
aRhs
)
{
m_current
=
aRhs
.
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
&
aB
)
:
m_end
(
aB
.
m_end
),
m_current
(
aB
.
m_current
),
m_shape
(
aB
.
m_shape
),
m_minDistance
(
aB
.
m_minDistance
),
m_exact
(
aB
.
m_exact
),
m_refBBox
(
aB
.
m_refBBox
)
{
}
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
query_iterator
&
operator
++
()
{
++
m_current
;
next
();
return
*
this
;
}
query_iterator
&
operator
++
(
int
aDummy
)
{
++
m_current
;
next
();
return
*
this
;
}
bool
operator
==
(
const
query_iterator
&
aRhs
)
const
{
return
m_current
==
aRhs
.
m_current
;
}
bool
operator
!=
(
const
query_iterator
&
aRhs
)
const
{
return
m_current
!=
aRhs
.
m_current
;
}
const
query_iterator
&
operator
=
(
const
query_iterator
&
aRhs
)
{
m_end
=
aRhs
.
m_end
;
m_current
=
aRhs
.
m_current
;
m_shape
=
aRhs
.
m_shape
;
m_minDistance
=
aRhs
.
m_minDistance
;
m_exact
=
aRhs
.
m_exact
;
m_refBBox
=
aRhs
.
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
>
// "Normal" iterator interface, for STL algorithms.
class
iterator
{
public
:
iterator
()
{};
iterator
(
ShapeVecIter
aCurrent
)
:
m_current
(
aCurrent
)
{};
iterator
(
const
iterator
&
aB
)
:
m_current
(
aB
.
m_current
)
{};
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
void
operator
++
()
{
++
m_current
;
}
iterator
&
operator
++
(
int
aDummy
)
{
++
m_current
;
return
*
this
;
}
bool
operator
==
(
const
iterator
&
aRhs
)
const
{
return
m_current
==
aRhs
.
m_current
;
}
bool
operator
!=
(
const
iterator
&
aRhs
)
const
{
return
m_current
!=
aRhs
.
m_current
;
}
const
iterator
&
operator
=
(
const
iterator
&
aRhs
)
{
m_current
=
aRhs
.
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
&
aB
)
:
m_end
(
aB
.
m_end
),
m_current
(
aB
.
m_current
),
m_shape
(
aB
.
m_shape
),
m_minDistance
(
aB
.
m_minDistance
),
m_exact
(
aB
.
m_exact
),
m_refBBox
(
aB
.
m_refBBox
)
{
}
T
operator
*
()
const
{
return
(
*
m_current
).
parent
;
}
query_iterator
&
operator
++
()
{
++
m_current
;
next
();
return
*
this
;
}
query_iterator
&
operator
++
(
int
aDummy
)
{
++
m_current
;
next
();
return
*
this
;
}
bool
operator
==
(
const
query_iterator
&
aRhs
)
const
{
return
m_current
==
aRhs
.
m_current
;
}
bool
operator
!=
(
const
query_iterator
&
aRhs
)
const
{
return
m_current
!=
aRhs
.
m_current
;
}
const
query_iterator
&
operator
=
(
const
query_iterator
&
aRhs
)
{
m_end
=
aRhs
.
m_end
;
m_current
=
aRhs
.
m_current
;
m_shape
=
aRhs
.
m_shape
;
m_minDistance
=
aRhs
.
m_minDistance
;
m_exact
=
aRhs
.
m_exact
;
m_refBBox
=
aRhs
.
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
&
aV
,
bool
aExact
=
true
)
//const
{
ShapeVecIter
i
;
...
...
@@ -251,33 +251,33 @@ public:
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
()
);
}
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
;
ShapeVec
m_shapes
;
};
#endif
include/geometry/shape_line_chain.h
View file @
22045b61
...
...
@@ -38,504 +38,504 @@
* 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.
* 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
&
aA
,
const
VECTOR2I
&
aB
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
2
);
m_points
[
0
]
=
aA
;
m_points
[
1
]
=
aB
;
}
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
]
=
aA
;
m_points
[
1
]
=
aB
;
m_points
[
2
]
=
aC
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
*
aV
,
int
aCount
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
aCount
);
for
(
int
i
=
0
;
i
<
aCount
;
i
++
)
m_points
[
i
]
=
*
aV
++
;
}
~
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 aIndex: 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
aIndex
)
{
if
(
aIndex
<
0
)
aIndex
+=
SegmentCount
();
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
m_points
[
aIndex
],
m_points
[
0
],
aIndex
);
else
return
SEG
(
m_points
[
aIndex
],
m_points
[
aIndex
+
1
],
aIndex
);
}
/**
* Function CSegment()
*
* Returns a read-only segment referencing to the segment (index) in the line chain.
* @param aIndex: 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
aIndex
)
const
{
if
(
aIndex
<
0
)
aIndex
+=
SegmentCount
();
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
0
]
),
aIndex
);
else
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
+
1
]
),
aIndex
);
}
/**
* Function Point()
*
* Returns a reference to a given point in the line chain.
* @param aIndex index of the point
* @return reference to the point
*/
VECTOR2I
&
Point
(
int
aIndex
)
{
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/**
* Function CPoint()
*
* Returns a const reference to a given point in the line chain.
* @param aIndex index of the point
* @return const reference to the point
*/
const
VECTOR2I
&
CPoint
(
int
aIndex
)
const
{
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/// @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 aX is X coordinate of the new point
* @param aY is Y coordinate of the new point
*/
void
Append
(
int
aX
,
int
aY
)
{
VECTOR2I
v
(
aX
,
aY
);
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 aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive)
* @param aP replacement point
*/
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 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
aStartIndex
,
int
aEndIndex
,
const
SHAPE_LINE_CHAIN
&
aLine
);
/**
* Function Remove()
*
* Removes the range of points [start_index, end_index] from the line chain.
* @param aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive)
*/
void
Remove
(
int
aStartIndex
,
int
aEndIndex
);
/**
* 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 aStartIndex start of the point range to be returned (inclusive)
* @param aEndIndex end of the point range to be returned (inclusive)
* @return cut line chain.
*/
const
SHAPE_LINE_CHAIN
Slice
(
int
aStartIndex
,
int
aEndIndex
=
-
1
)
const
;
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
Intersection
&
aA
,
const
Intersection
&
aB
)
{
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
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
&
aRhs
)
const
{
if
(
PointCount
()
!=
aRhs
.
PointCount
()
)
return
true
;
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
;
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
&
aA
,
const
VECTOR2I
&
aB
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
2
);
m_points
[
0
]
=
aA
;
m_points
[
1
]
=
aB
;
}
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
]
=
aA
;
m_points
[
1
]
=
aB
;
m_points
[
2
]
=
aC
;
}
SHAPE_LINE_CHAIN
(
const
VECTOR2I
*
aV
,
int
aCount
)
:
SHAPE
(
SH_LINE_CHAIN
),
m_closed
(
false
)
{
m_points
.
resize
(
aCount
);
for
(
int
i
=
0
;
i
<
aCount
;
i
++
)
m_points
[
i
]
=
*
aV
++
;
}
~
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 aIndex: 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
aIndex
)
{
if
(
aIndex
<
0
)
aIndex
+=
SegmentCount
();
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
m_points
[
aIndex
],
m_points
[
0
],
aIndex
);
else
return
SEG
(
m_points
[
aIndex
],
m_points
[
aIndex
+
1
],
aIndex
);
}
/**
* Function CSegment()
*
* Returns a read-only segment referencing to the segment (index) in the line chain.
* @param aIndex: 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
aIndex
)
const
{
if
(
aIndex
<
0
)
aIndex
+=
SegmentCount
();
if
(
aIndex
==
(
m_points
.
size
()
-
1
)
&&
m_closed
)
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
0
]
),
aIndex
);
else
return
SEG
(
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
]
),
const_cast
<
VECTOR2I
&>
(
m_points
[
aIndex
+
1
]
),
aIndex
);
}
/**
* Function Point()
*
* Returns a reference to a given point in the line chain.
* @param aIndex index of the point
* @return reference to the point
*/
VECTOR2I
&
Point
(
int
aIndex
)
{
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/**
* Function CPoint()
*
* Returns a const reference to a given point in the line chain.
* @param aIndex index of the point
* @return const reference to the point
*/
const
VECTOR2I
&
CPoint
(
int
aIndex
)
const
{
if
(
aIndex
<
0
)
aIndex
+=
PointCount
();
return
m_points
[
aIndex
];
}
/// @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 aX is X coordinate of the new point
* @param aY is Y coordinate of the new point
*/
void
Append
(
int
aX
,
int
aY
)
{
VECTOR2I
v
(
aX
,
aY
);
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 aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive)
* @param aP replacement point
*/
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 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
aStartIndex
,
int
aEndIndex
,
const
SHAPE_LINE_CHAIN
&
aLine
);
/**
* Function Remove()
*
* Removes the range of points [start_index, end_index] from the line chain.
* @param aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive)
*/
void
Remove
(
int
aStartIndex
,
int
aEndIndex
);
/**
* 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 aStartIndex start of the point range to be returned (inclusive)
* @param aEndIndex end of the point range to be returned (inclusive)
* @return cut line chain.
*/
const
SHAPE_LINE_CHAIN
Slice
(
int
aStartIndex
,
int
aEndIndex
=
-
1
)
const
;
struct
compareOriginDistance
{
compareOriginDistance
(
VECTOR2I
&
aOrigin
)
:
m_origin
(
aOrigin
)
{};
bool
operator
()(
const
Intersection
&
aA
,
const
Intersection
&
aB
)
{
return
(
m_origin
-
aA
.
p
).
EuclideanNorm
()
<
(
m_origin
-
aB
.
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
&
aRhs
)
const
{
if
(
PointCount
()
!=
aRhs
.
PointCount
()
)
return
true
;
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
;
};
#endif // __SHAPE_LINE_CHAIN
include/geometry/shape_rect.h
View file @
22045b61
...
...
@@ -31,114 +31,114 @@
#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 (aX0, aY0), width aW and height aH.
*/
SHAPE_RECT
(
int
aX0
,
int
aY0
,
int
aW
,
int
aH
)
:
SHAPE
(
SH_RECT
),
m_p0
(
aX0
,
aY0
),
m_w
(
aW
),
m_h
(
aH
)
{};
/**
* Constructor
* Creates a rectangle defined by top-left corner aP0, width aW and height aH.
*/
SHAPE_RECT
(
const
VECTOR2I
&
aP0
,
int
aW
,
int
aH
)
:
SHAPE
(
SH_RECT
),
m_p0
(
aP0
),
m_w
(
aW
),
m_h
(
aH
)
{};
/// @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
;
};
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 (aX0, aY0), width aW and height aH.
*/
SHAPE_RECT
(
int
aX0
,
int
aY0
,
int
aW
,
int
aH
)
:
SHAPE
(
SH_RECT
),
m_p0
(
aX0
,
aY0
),
m_w
(
aW
),
m_h
(
aH
)
{};
/**
* Constructor
* Creates a rectangle defined by top-left corner aP0, width aW and height aH.
*/
SHAPE_RECT
(
const
VECTOR2I
&
aP0
,
int
aW
,
int
aH
)
:
SHAPE
(
SH_RECT
),
m_p0
(
aP0
),
m_w
(
aW
),
m_h
(
aH
)
{};
/// @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
include/math/box2.h
View file @
22045b61
...
...
@@ -66,7 +66,7 @@ public:
BOX2
(
const
Vec
&
aPos
,
const
Vec
&
aSize
)
:
m_Pos
(
aPos
),
m_Size
(
aSize
)
{
{
Normalize
();
}
...
...
@@ -420,7 +420,7 @@ public:
ecoord_type
y2
=
m_Pos
.
y
+
m_Size
.
y
;
ecoord_type
xdiff
=
std
::
max
(
aP
.
x
<
m_Pos
.
x
?
m_Pos
.
x
-
aP
.
x
:
m_Pos
.
x
-
x2
,
(
ecoord_type
)
0
);
ecoord_type
ydiff
=
std
::
max
(
aP
.
y
<
m_Pos
.
y
?
m_Pos
.
y
-
aP
.
y
:
m_Pos
.
y
-
y2
,
(
ecoord_type
)
0
);
return
xdiff
*
xdiff
+
ydiff
*
ydiff
;
return
xdiff
*
xdiff
+
ydiff
*
ydiff
;
}
ecoord_type
Distance
(
const
Vec
&
aP
)
const
...
...
include/math/vector2d.h
View file @
22045b61
...
...
@@ -224,7 +224,7 @@ public:
/// Division with a factor
VECTOR2
<
T
>
operator
/
(
const
T
&
aFactor
)
const
;
/// Equality operator
const
bool
operator
==
(
const
VECTOR2
<
T
>&
aVector
)
const
;
...
...
include/tool/context_menu.h
View file @
22045b61
...
...
@@ -37,105 +37,105 @@ class TOOL_INTERACTIVE;
* Defines the structure of a context (usually right-click) popup menu
* for a given tool.
*/
class
CONTEXT_MENU
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
);
}
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 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.
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
;
///> 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 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.
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
static
const
int
m_actionId
=
10000
;
...
...
include/tool/coroutine.h
View file @
22045b61
...
...
@@ -34,13 +34,13 @@
/**
Class COROUNTINE.
Implements a coroutine. Wikipedia has a good explanation:
"Coroutines are computer program components that generalize subroutines to
allow multiple entry points for suspending and resuming execution at certain locations.
Coroutines are well-suited for implementing more familiar program components such as cooperative
"Coroutines are computer program components that generalize subroutines to
allow multiple entry points for suspending and resuming execution at certain locations.
Coroutines are well-suited for implementing more familiar program components such as cooperative
tasks, exceptions, event loop, iterators, infinite lists and pipes."
In other words, a coroutine can be considered a lightweight thread - which can be
In other words, a coroutine can be considered a lightweight thread - which can be
preempted only when it deliberately yields the control to the caller. This way,
we avoid concurrency problems such as locking / race conditions.
...
...
@@ -56,82 +56,82 @@ template<class ReturnType, class ArgType>
class
COROUTINE
{
public
:
COROUTINE
()
{
m_stackSize
=
c_defaultStackSize
;
m_stack
=
NULL
;
m_saved
=
NULL
;
}
/**
* Constructor
* Creates a coroutine from a member method of an object
*/
template
<
class
T
>
COROUTINE
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
ArgType
)
)
:
m_func
(
object
,
ptr
),
m_saved
(
NULL
),
m_stack
(
NULL
),
m_stackSize
(
c_defaultStackSize
)
{
}
/**
* Constructor
* Creates a coroutine from a delegate object
*/
COROUTINE
(
DELEGATE
<
ReturnType
,
ArgType
>
aEntry
)
:
COROUTINE
()
{
m_stackSize
=
c_defaultStackSize
;
m_stack
=
NULL
;
m_saved
=
NULL
;
}
/**
* Constructor
* Creates a coroutine from a member method of an object
*/
template
<
class
T
>
COROUTINE
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
ArgType
)
)
:
m_func
(
object
,
ptr
),
m_saved
(
NULL
),
m_stack
(
NULL
),
m_stackSize
(
c_defaultStackSize
)
{
}
/**
* Constructor
* Creates a coroutine from a delegate object
*/
COROUTINE
(
DELEGATE
<
ReturnType
,
ArgType
>
aEntry
)
:
m_func
(
aEntry
),
m_saved
(
NULL
),
m_stack
(
NULL
),
m_stackSize
(
c_defaultStackSize
)
{};
{};
~
COROUTINE
()
{
~
COROUTINE
()
{
if
(
m_saved
)
delete
m_saved
;
if
(
m_stack
)
free
(
m_stack
);
}
/**
* Function Yield()
*
* Stops execution of the coroutine and returns control to the caller.
* After a yield, Call() or Resume() methods invoked by the caller will
* immediately return true, indicating that we are not done yet, just asleep.
*/
void
Yield
()
{
boost
::
context
::
jump_fcontext
(
m_self
,
m_saved
,
0
);
}
/**
* Function Yield()
*
* Yield with a value - passes a value of given type to the caller.
* Useful for implementing generator objects.
*/
void
Yield
(
ReturnType
&
retVal
)
{
m_retVal
=
retVal
;
boost
::
context
::
jump_fcontext
(
m_self
,
m_saved
,
0
);
}
/**
<F11>* Function SetEntry()
*
* Defines the entry point for the coroutine, if not set in the constructor.
*/
void
SetEntry
(
DELEGATE
<
ReturnType
,
ArgType
>
aEntry
)
{
m_func
=
aEntry
;
}
/* Function Call()
*
* Starts execution of a coroutine, passing args as its arguments.
* @return true, if the coroutine has yielded and false if it has finished its
* execution (returned).
*/
bool
Call
(
ArgType
args
)
{
// fixme: Clean up stack stuff. Add a guard
}
/**
* Function Yield()
*
* Stops execution of the coroutine and returns control to the caller.
* After a yield, Call() or Resume() methods invoked by the caller will
* immediately return true, indicating that we are not done yet, just asleep.
*/
void
Yield
()
{
boost
::
context
::
jump_fcontext
(
m_self
,
m_saved
,
0
);
}
/**
* Function Yield()
*
* Yield with a value - passes a value of given type to the caller.
* Useful for implementing generator objects.
*/
void
Yield
(
ReturnType
&
retVal
)
{
m_retVal
=
retVal
;
boost
::
context
::
jump_fcontext
(
m_self
,
m_saved
,
0
);
}
/**
<F11>* Function SetEntry()
*
* Defines the entry point for the coroutine, if not set in the constructor.
*/
void
SetEntry
(
DELEGATE
<
ReturnType
,
ArgType
>
aEntry
)
{
m_func
=
aEntry
;
}
/* Function Call()
*
* Starts execution of a coroutine, passing args as its arguments.
* @return true, if the coroutine has yielded and false if it has finished its
* execution (returned).
*/
bool
Call
(
ArgType
args
)
{
// fixme: Clean up stack stuff. Add a guard
m_stack
=
malloc
(
c_defaultStackSize
);
// align to 16 bytes
...
...
@@ -145,87 +145,87 @@ public:
// off we go!
boost
::
context
::
jump_fcontext
(
m_saved
,
m_self
,
reinterpret_cast
<
intptr_t
>
(
this
)
);
return
m_running
;
}
/**
* Function Resume()
*
* Resumes execution of a previously yielded coroutine.
* @return true, if the coroutine has yielded again and false if it has finished its
* execution (returned).
*/
bool
Resume
()
{
}
/**
* Function Resume()
*
* Resumes execution of a previously yielded coroutine.
* @return true, if the coroutine has yielded again and false if it has finished its
* execution (returned).
*/
bool
Resume
()
{
boost
::
context
::
jump_fcontext
(
m_saved
,
m_self
,
0
);
return
m_running
;
}
/**
* Function ReturnValue()
*
* Returns the yielded value (the argument Yield() was called with)
*/
const
ReturnType
&
ReturnValue
()
const
{
return
m_retVal
;
}
/**
* Function Running()
*
* @return true, if the coroutine is active
*/
bool
Running
()
const
{
return
m_running
;
}
}
/**
* Function ReturnValue()
*
* Returns the yielded value (the argument Yield() was called with)
*/
const
ReturnType
&
ReturnValue
()
const
{
return
m_retVal
;
}
/**
* Function Running()
*
* @return true, if the coroutine is active
*/
bool
Running
()
const
{
return
m_running
;
}
private
:
static
const
int
c_defaultStackSize
=
2000000
;
// fixme: make configurable
/* real entry point of the coroutine */
static
void
callerStub
(
intptr_t
data
)
{
// get pointer to self
COROUTINE
<
ReturnType
,
ArgType
>*
cor
=
reinterpret_cast
<
COROUTINE
<
ReturnType
,
ArgType
>*>
(
data
);
// call the coroutine method
cor
->
m_retVal
=
cor
->
m_func
(
*
cor
->
m_args
);
cor
->
m_running
=
false
;
// go back to wherever we came from.
boost
::
context
::
jump_fcontext
(
cor
->
m_self
,
cor
->
m_saved
,
0
);
//reinterpret_cast<intptr_t>( this ));
}
template
<
typename
T
>
struct
strip_ref
{
typedef
T
result
;
};
template
<
typename
T
>
struct
strip_ref
<
T
&>
{
typedef
T
result
;
};
DELEGATE
<
ReturnType
,
ArgType
>
m_func
;
///< pointer to coroutine entry arguments. Stripped of references
///< to avoid compiler errors.
typename
strip_ref
<
ArgType
>::
result
*
m_args
;
ReturnType
m_retVal
;
///< saved caller context
boost
::
context
::
fcontext_t
*
m_saved
;
///< saved coroutine context
boost
::
context
::
fcontext_t
*
m_self
;
///< coroutine stack
void
*
m_stack
;
size_t
m_stackSize
;
bool
m_running
;
static
const
int
c_defaultStackSize
=
2000000
;
// fixme: make configurable
/* real entry point of the coroutine */
static
void
callerStub
(
intptr_t
data
)
{
// get pointer to self
COROUTINE
<
ReturnType
,
ArgType
>*
cor
=
reinterpret_cast
<
COROUTINE
<
ReturnType
,
ArgType
>*>
(
data
);
// call the coroutine method
cor
->
m_retVal
=
cor
->
m_func
(
*
cor
->
m_args
);
cor
->
m_running
=
false
;
// go back to wherever we came from.
boost
::
context
::
jump_fcontext
(
cor
->
m_self
,
cor
->
m_saved
,
0
);
//reinterpret_cast<intptr_t>( this ));
}
template
<
typename
T
>
struct
strip_ref
{
typedef
T
result
;
};
template
<
typename
T
>
struct
strip_ref
<
T
&>
{
typedef
T
result
;
};
DELEGATE
<
ReturnType
,
ArgType
>
m_func
;
///< pointer to coroutine entry arguments. Stripped of references
///< to avoid compiler errors.
typename
strip_ref
<
ArgType
>::
result
*
m_args
;
ReturnType
m_retVal
;
///< saved caller context
boost
::
context
::
fcontext_t
*
m_saved
;
///< saved coroutine context
boost
::
context
::
fcontext_t
*
m_self
;
///< coroutine stack
void
*
m_stack
;
size_t
m_stackSize
;
bool
m_running
;
};
#endif
include/tool/delegate.h
View file @
22045b61
...
...
@@ -28,38 +28,38 @@
/**
* class DELEGATE
* A trivial delegate (pointer to member method of an object) pattern implementation.
* A trivial delegate (pointer to member method of an object) pattern implementation.
* Check delegate_example.cpp for a coding sample.
*/
template
<
class
ReturnType
,
class
Arg
>
class
DELEGATE
{
public
:
typedef
ReturnType
(
DELEGATE
<
ReturnType
,
Arg
>::*
MemberPointer
)(
Arg
);
typedef
ReturnType
_ReturnType
;
typedef
Arg
_ArgType
;
DELEGATE
()
{
}
template
<
class
T
>
DELEGATE
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
Arg
)
)
{
m_ptr
=
reinterpret_cast
<
MemberPointer
>
(
ptr
);
m_object
=
reinterpret_cast
<
void
*>
(
object
);
};
ReturnType
operator
()(
Arg
a
)
const
{
DELEGATE
<
ReturnType
,
Arg
>
*
casted
=
reinterpret_cast
<
DELEGATE
<
ReturnType
,
Arg
>*>
(
m_object
);
return
(
casted
->*
m_ptr
)(
a
);
}
private
:
MemberPointer
m_ptr
;
void
*
m_object
;
class
DELEGATE
{
public
:
typedef
ReturnType
(
DELEGATE
<
ReturnType
,
Arg
>::*
MemberPointer
)(
Arg
);
typedef
ReturnType
_ReturnType
;
typedef
Arg
_ArgType
;
DELEGATE
()
{
}
template
<
class
T
>
DELEGATE
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
Arg
)
)
{
m_ptr
=
reinterpret_cast
<
MemberPointer
>
(
ptr
);
m_object
=
reinterpret_cast
<
void
*>
(
object
);
};
ReturnType
operator
()(
Arg
a
)
const
{
DELEGATE
<
ReturnType
,
Arg
>
*
casted
=
reinterpret_cast
<
DELEGATE
<
ReturnType
,
Arg
>*>
(
m_object
);
return
(
casted
->*
m_ptr
)(
a
);
}
private
:
MemberPointer
m_ptr
;
void
*
m_object
;
};
/**
...
...
@@ -67,32 +67,32 @@ private:
* Same as DELEGATE, but with no arguments.
*/
template
<
class
ReturnType
>
class
DELEGATE0
{
public
:
typedef
ReturnType
(
DELEGATE0
<
ReturnType
>::*
MemberPointer
)();
typedef
ReturnType
_ReturnType
;
DELEGATE0
()
{
}
template
<
class
T
>
DELEGATE0
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
)
)
{
m_ptr
=
reinterpret_cast
<
MemberPointer
>
(
ptr
);
m_object
=
reinterpret_cast
<
void
*>
(
object
);
};
ReturnType
operator
()(
)
const
{
DELEGATE0
<
ReturnType
>*
casted
=
reinterpret_cast
<
DELEGATE0
<
ReturnType
>*>
(
m_object
);
return
(
casted
->*
m_ptr
)();
}
private
:
MemberPointer
m_ptr
;
void
*
m_object
;
class
DELEGATE0
{
public
:
typedef
ReturnType
(
DELEGATE0
<
ReturnType
>::*
MemberPointer
)();
typedef
ReturnType
_ReturnType
;
DELEGATE0
()
{
}
template
<
class
T
>
DELEGATE0
(
T
*
object
,
ReturnType
(
T
::*
ptr
)(
)
)
{
m_ptr
=
reinterpret_cast
<
MemberPointer
>
(
ptr
);
m_object
=
reinterpret_cast
<
void
*>
(
object
);
};
ReturnType
operator
()(
)
const
{
DELEGATE0
<
ReturnType
>*
casted
=
reinterpret_cast
<
DELEGATE0
<
ReturnType
>*>
(
m_object
);
return
(
casted
->*
m_ptr
)();
}
private
:
MemberPointer
m_ptr
;
void
*
m_object
;
};
#endif
include/tool/examples/coroutine_example.cpp
View file @
22045b61
...
...
@@ -9,40 +9,40 @@ typedef COROUTINE<int, int> MyCoroutine;
class
MyClass
{
public
:
int
CountTo
(
int
n
)
{
printf
(
"%s: Coroutine says hi. I will count from 1 to %d and yield each value.
\n
"
,
__FUNCTION__
,
n
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
printf
(
"%s: Yielding %d
\n
"
,
__FUNCTION__
,
i
);
cofunc
.
Yield
(
i
);
}
}
void
Run
()
{
cofunc
=
MyCoroutine
(
this
,
&
MyClass
::
CountTo
);
printf
(
"%s: Calling coroutine that will count from 1 to 5.
\n
"
,
__FUNCTION__
);
cofunc
.
Call
(
5
);
while
(
cofunc
.
Running
())
{
printf
(
"%s: Got value: %d
\n
"
,
__FUNCTION__
,
cofunc
.
ReturnValue
());
cofunc
.
Resume
();
}
printf
(
"%s: Done!
\n
"
,
__FUNCTION__
);
}
MyCoroutine
cofunc
;
public
:
int
CountTo
(
int
n
)
{
printf
(
"%s: Coroutine says hi. I will count from 1 to %d and yield each value.
\n
"
,
__FUNCTION__
,
n
);
for
(
int
i
=
1
;
i
<=
n
;
i
++
)
{
printf
(
"%s: Yielding %d
\n
"
,
__FUNCTION__
,
i
);
cofunc
.
Yield
(
i
);
}
}
void
Run
()
{
cofunc
=
MyCoroutine
(
this
,
&
MyClass
::
CountTo
);
printf
(
"%s: Calling coroutine that will count from 1 to 5.
\n
"
,
__FUNCTION__
);
cofunc
.
Call
(
5
);
while
(
cofunc
.
Running
())
{
printf
(
"%s: Got value: %d
\n
"
,
__FUNCTION__
,
cofunc
.
ReturnValue
());
cofunc
.
Resume
();
}
printf
(
"%s: Done!
\n
"
,
__FUNCTION__
);
}
MyCoroutine
cofunc
;
};
main
()
{
MyClass
obj
;
MyClass
obj
;
obj
.
Run
();
return
0
;
}
obj
.
Run
();
return
0
;
}
include/tool/examples/delegate_example.cpp
View file @
22045b61
...
...
@@ -7,29 +7,29 @@ using namespace std;
class
MyClass
{
public
:
int
MyMethod
(
const
string
&
arg
)
{
printf
(
"MyClass(this = %p)::MyMethod() called with string '%s', length %d
\n
"
,
this
,
arg
.
c_str
(),
arg
.
length
());
return
arg
.
length
();
}
public
:
int
MyMethod
(
const
string
&
arg
)
{
printf
(
"MyClass(this = %p)::MyMethod() called with string '%s', length %d
\n
"
,
this
,
arg
.
c_str
(),
arg
.
length
());
return
arg
.
length
();
}
};
typedef
DELEGATE
<
int
,
const
string
&>
MyDelegate
;
main
()
{
MyClass
t1
;
MyClass
t2
;
MyDelegate
ptr1
(
&
t1
,
&
MyClass
::
MyMethod
);
MyDelegate
ptr2
(
&
t2
,
&
MyClass
::
MyMethod
);
int
retval1
,
retval2
;
MyClass
t1
;
MyClass
t2
;
MyDelegate
ptr1
(
&
t1
,
&
MyClass
::
MyMethod
);
MyDelegate
ptr2
(
&
t2
,
&
MyClass
::
MyMethod
);
int
retval1
,
retval2
;
retval1
=
ptr1
(
"apples"
);
retval2
=
ptr2
(
"cherries"
);
printf
(
"Object 1 returned %d, object 2 returned %d
\n
"
,
retval1
,
retval2
);
return
0
;
}
printf
(
"Object 1 returned %d, object 2 returned %d
\n
"
,
retval1
,
retval2
);
return
0
;
}
include/tool/tool_base.h
View file @
22045b61
...
...
@@ -59,128 +59,128 @@ typedef DELEGATE<int, TOOL_EVENT&> TOOL_STATE_FUNC;
* Base abstract interface for all kinds of tools.
*/
class
TOOL_BASE
class
TOOL_BASE
{
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_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
;
}
TOOL_BASE
(
TOOL_Type
aType
,
TOOL_ID
aId
,
const
std
::
string
&
aName
=
std
::
string
(
""
)
)
:
m_type
(
aType
),
m_toolId
(
aId
),
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
;
}
protected
:
friend
class
TOOL_MANAGER
;
/**
* Function attachManager()
*
* Sets the TOOL_MANAGER the tool will belong to.
* Called by TOOL_MANAGER::RegisterTool()
*/
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.
*/
template
<
typename
T
>
T
*
getEditFrame
()
const
{
return
static_cast
<
T
*>
(
getEditFrameInt
()
);
}
/**
* Function getModel()
*
* Returns the model object if it matches the requested type.
*/
template
<
typename
T
>
T
*
getModel
(
KICAD_T
modelType
)
const
{
EDA_ITEM
*
m
=
getModelInt
();
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
;
friend
class
TOOL_MANAGER
;
/**
* Function attachManager()
*
* Sets the TOOL_MANAGER the tool will belong to.
* Called by TOOL_MANAGER::RegisterTool()
*/
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.
*/
template
<
typename
T
>
T
*
getEditFrame
()
const
{
return
static_cast
<
T
*>
(
getEditFrameInt
()
);
}
/**
* Function getModel()
*
* Returns the model object if it matches the requested type.
*/
template
<
typename
T
>
T
*
getModel
(
KICAD_T
modelType
)
const
{
EDA_ITEM
*
m
=
getModelInt
();
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
;
private
:
// hide the implementation to avoid spreading half of
// kicad and wxWidgets headers to the tools that may not need them at all!
EDA_ITEM
*
getModelInt
()
const
;
wxWindow
*
getEditFrameInt
()
const
;
// hide the implementation to avoid spreading half of
// kicad and wxWidgets headers to the tools that may not need them at all!
EDA_ITEM
*
getModelInt
()
const
;
wxWindow
*
getEditFrameInt
()
const
;
};
#endif
include/tool/tool_dispatcher.h
View file @
22045b61
...
...
@@ -33,12 +33,12 @@ class TOOL_MANAGER;
class
PCB_BASE_FRAME
;
namespace
KiGfx
{
class
VIEW
;
class
VIEW
;
};
/**
/**
* Class TOOL_DISPATCHER
*
*
* - takes wx events,
* - fixes all wx quirks (mouse warping, panning, ordering problems, etc)
* - translates coordinates to world space
...
...
include/tool/tool_event.h
View file @
22045b61
...
...
@@ -42,63 +42,63 @@ class TOOL_MANAGER;
*/
enum
TOOL_EventCategory
{
TC_None
=
0x00
,
TC_Mouse
=
0x01
,
TC_Keyboard
=
0x02
,
TC_Command
=
0x04
,
TC_Message
=
0x08
,
TC_View
=
0x10
,
TC_Any
=
0xffffffff
TC_None
=
0x00
,
TC_Mouse
=
0x01
,
TC_Keyboard
=
0x02
,
TC_Command
=
0x04
,
TC_Message
=
0x08
,
TC_View
=
0x10
,
TC_Any
=
0xffffffff
};
enum
TOOL_Actions
{
// UI input events
TA_None
=
0x0000
,
TA_MouseClick
=
0x0001
,
TA_MouseUp
=
0x0002
,
TA_MouseDown
=
0x0004
,
TA_MouseDrag
=
0x0008
,
TA_MouseMotion
=
0x0010
,
TA_MouseWheel
=
0x0020
,
TA_Mouse
=
0x003f
,
TA_KeyUp
=
0x0040
,
TA_None
=
0x0000
,
TA_MouseClick
=
0x0001
,
TA_MouseUp
=
0x0002
,
TA_MouseDown
=
0x0004
,
TA_MouseDrag
=
0x0008
,
TA_MouseMotion
=
0x0010
,
TA_MouseWheel
=
0x0020
,
TA_Mouse
=
0x003f
,
TA_KeyUp
=
0x0040
,
TA_KeyDown
=
0x0080
,
TA_Keyboard
=
TA_KeyUp
|
TA_KeyDown
,
// View related events
TA_ViewRefresh
=
0x0100
,
TA_ViewZoom
=
0x0200
,
TA_ViewPan
=
0x0400
,
TA_ViewDirty
=
0x0800
,
TA_ChangeLayer
=
0x1000
,
TA_ViewRefresh
=
0x0100
,
TA_ViewZoom
=
0x0200
,
TA_ViewPan
=
0x0400
,
TA_ViewDirty
=
0x0800
,
TA_ChangeLayer
=
0x1000
,
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
// the context menu.
TA_CancelTool
=
0x2000
,
// 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
TA_ContextMenuUpdate
=
0x4000
,
// 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.
TA_ContextMenuChoice
=
0x8000
,
// Context menu choice. Sent if the user picked something from the context menu or
// closed it without selecting anything.
TA_ContextMenuChoice
=
0x8000
,
// Tool action (allows to control tools)
TA_Action
=
0x10000
,
// Tool action (allows to control tools)
TA_Action
=
0x10000
,
TA_Any
=
0xffffffff
TA_Any
=
0xffffffff
};
enum
TOOL_MouseButtons
{
MB_None
=
0x0
,
MB_Left
=
0x1
,
MB_Right
=
0x2
,
MB_Middle
=
0x4
,
MB_ButtonMask
=
MB_Left
|
MB_Right
|
MB_Middle
,
MB_Any
=
0xffffffff
MB_None
=
0x0
,
MB_Left
=
0x1
,
MB_Right
=
0x2
,
MB_Middle
=
0x4
,
MB_ButtonMask
=
MB_Left
|
MB_Right
|
MB_Middle
,
MB_Any
=
0xffffffff
};
enum
TOOL_Modifiers
...
...
@@ -120,14 +120,14 @@ enum TOOL_ActionScope
/// Defines when a context menu is opened.
enum
CONTEXT_MENU_TRIGGER
{
CMENU_BUTTON
=
0
,
// On the right button
CMENU_NOW
,
// Right now (after TOOL_INTERACTIVE::SetContextMenu)
CMENU_OFF
// Never
CMENU_BUTTON
=
0
,
// On the right button
CMENU_NOW
,
// Right now (after TOOL_INTERACTIVE::SetContextMenu)
CMENU_OFF
// Never
};
/**
/**
* Class TOOL_EVENT
*
*
* Generic, UI-independent tool event.
*/
class
TOOL_EVENT
...
...
@@ -359,9 +359,9 @@ private:
typedef
boost
::
optional
<
TOOL_EVENT
>
OPT_TOOL_EVENT
;
/**
/**
* Class TOOL_EVENT_LIST
*
*
* A list of TOOL_EVENTs, with overloaded || operators allowing for
* concatenating TOOL_EVENTs with little code.
*/
...
...
@@ -473,20 +473,20 @@ private:
inline
const
TOOL_EVENT_LIST
operator
||
(
const
TOOL_EVENT
&
a
,
const
TOOL_EVENT
&
b
)
{
TOOL_EVENT_LIST
l
;
TOOL_EVENT_LIST
l
;
l
.
Add
(
a
);
l
.
Add
(
b
);
l
.
Add
(
a
);
l
.
Add
(
b
);
return
l
;
return
l
;
}
inline
const
TOOL_EVENT_LIST
operator
||
(
const
TOOL_EVENT
&
a
,
const
TOOL_EVENT_LIST
&
b
)
{
TOOL_EVENT_LIST
l
(
b
);
l
.
Add
(
a
);
return
l
;
TOOL_EVENT_LIST
l
(
b
);
l
.
Add
(
a
);
return
l
;
}
#endif
include/tool/tool_interactive.h
View file @
22045b61
...
...
@@ -39,23 +39,23 @@ public:
* Constructor
*
* Creates a tool with given id & name. The name must be unique. */
TOOL_INTERACTIVE
(
TOOL_ID
aId
,
const
std
::
string
&
aName
);
/**
* Constructor
*
* Creates a tool with given name. The name must be unique. */
TOOL_INTERACTIVE
(
const
std
::
string
&
aName
);
virtual
~
TOOL_INTERACTIVE
();
/**
* 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.
*/
virtual
void
Reset
()
=
0
;
/**
TOOL_INTERACTIVE
(
TOOL_ID
aId
,
const
std
::
string
&
aName
);
/**
* Constructor
*
* Creates a tool with given name. The name must be unique. */
TOOL_INTERACTIVE
(
const
std
::
string
&
aName
);
virtual
~
TOOL_INTERACTIVE
();
/**
* 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.
*/
virtual
void
Reset
()
=
0
;
/**
* Function Init()
* Init() is called once upon a registration of the tool.
*
...
...
@@ -66,58 +66,58 @@ public:
return
true
;
}
/**
* Function SetContextMenu()
*
* 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
);
/**
* Function Go()
*
* Defines which state (aStateFunc) to go when a certain event arrives (aConditions).
* No conditions means any event.
*/
template
<
class
T
>
void
Go
(
int
(
T
::*
aStateFunc
)(
TOOL_EVENT
&
),
const
TOOL_EVENT_LIST
&
aConditions
=
TOOL_EVENT
(
TC_Any
,
TA_Any
)
);
/**
* Function Wait()
*
* Suspends execution of the tool until an event specified in aEventList arrives.
* No parameters means waiting for any event.
*/
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>
bool InvokeTool( const std::string& aToolName, const Parameters& parameters,
ReturnValue& returnValue );
template<class Parameters, class ReturnValue>
bool InvokeWindow( const std::string& aWindowName, const Parameters& parameters,
ReturnValue& returnValue );
template<class T>
void Yield( const T& returnValue );*/
/**
* Function SetContextMenu()
*
* 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
);
/**
* Function Go()
*
* Defines which state (aStateFunc) to go when a certain event arrives (aConditions).
* No conditions means any event.
*/
template
<
class
T
>
void
Go
(
int
(
T
::*
aStateFunc
)(
TOOL_EVENT
&
),
const
TOOL_EVENT_LIST
&
aConditions
=
TOOL_EVENT
(
TC_Any
,
TA_Any
)
);
/**
* Function Wait()
*
* Suspends execution of the tool until an event specified in aEventList arrives.
* No parameters means waiting for any event.
*/
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>
bool InvokeTool( const std::string& aToolName, const Parameters& parameters,
ReturnValue& returnValue );
template<class Parameters, class ReturnValue>
bool InvokeWindow( const std::string& aWindowName, const Parameters& parameters,
ReturnValue& returnValue );
template<class T>
void Yield( const T& returnValue );*/
protected
:
/* 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
=
""
);
const
TOOL_EVENT
evMotion
();
const
TOOL_EVENT
evClick
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evDrag
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evButtonUp
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evButtonDown
(
int
aButton
=
MB_Any
);
/* 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
=
""
);
const
TOOL_EVENT
evMotion
();
const
TOOL_EVENT
evClick
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evDrag
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evButtonUp
(
int
aButton
=
MB_Any
);
const
TOOL_EVENT
evButtonDown
(
int
aButton
=
MB_Any
);
private
:
void
goInternal
(
TOOL_STATE_FUNC
&
aState
,
const
TOOL_EVENT_LIST
&
aConditions
);
void
goInternal
(
TOOL_STATE_FUNC
&
aState
,
const
TOOL_EVENT_LIST
&
aConditions
);
};
// hide TOOL_MANAGER implementation
...
...
@@ -125,8 +125,8 @@ template<class T>
void
TOOL_INTERACTIVE
::
Go
(
int
(
T
::*
aStateFunc
)(
TOOL_EVENT
&
),
const
TOOL_EVENT_LIST
&
aConditions
)
{
TOOL_STATE_FUNC
sptr
(
static_cast
<
T
*>
(
this
),
aStateFunc
);
goInternal
(
sptr
,
aConditions
);
TOOL_STATE_FUNC
sptr
(
static_cast
<
T
*>
(
this
),
aStateFunc
);
goInternal
(
sptr
,
aConditions
);
}
#endif
include/view/view_controls.h
View file @
22045b61
...
...
@@ -122,7 +122,7 @@ public:
virtual
const
VECTOR2D
GetCursorPosition
()
const
=
0
;
/**
/**
* Function ForceCursorPosition()
* Places the cursor immediately at a given point. Mouse movement is ignored.
* @param aEnabled enable forced cursor position
...
...
pcbnew/edit.cpp
100755 → 100644
View file @
22045b61
File mode changed from 100755 to 100644
pcbnew/pcb_painter.cpp
View file @
22045b61
...
...
@@ -279,7 +279,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
NETINFO_ITEM
*
net
=
(
(
BOARD
*
)
aTrack
->
GetParent
()
)
->
FindNet
(
netNumber
);
if
(
!
net
)
return
;
std
::
string
netName
=
std
::
string
(
net
->
GetShortNetname
().
mb_str
()
);
VECTOR2D
textPosition
=
start
+
line
/
2.0
;
// center of the track
double
textOrientation
=
-
atan
(
line
.
y
/
line
.
x
);
...
...
pcbnew/router/pns_itemset.h
View file @
22045b61
...
...
@@ -28,7 +28,7 @@
/**
* Class PNS_ITEMSET
*
* Holds a list of board items, that can be filtered against net, kinds,
* Holds a list of board items, that can be filtered against net, kinds,
* layers, etc.
**/
...
...
pcbnew/router/pns_joint.h
View file @
22045b61
...
...
@@ -32,9 +32,9 @@
/**
* Class PNS_JOINT
*
* Represents a 2D point on a given set of layers and belonging to a certain
* Represents a 2D point on a given set of layers and belonging to a certain
* net, that links together a number of board items.
* A hash table of joints is used by the router to follow connectivity between
* A hash table of joints is used by the router to follow connectivity between
* the items.
**/
class
PNS_JOINT
:
public
PNS_ITEM
...
...
@@ -53,8 +53,8 @@ public:
PNS_JOINT
()
:
PNS_ITEM
(
JOINT
)
{}
PNS_JOINT
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
=
-
1
)
:
PNS_JOINT
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
=
-
1
)
:
PNS_ITEM
(
JOINT
)
{
m_tag
.
pos
=
aPos
;
...
...
@@ -78,14 +78,14 @@ public:
return
NULL
;
}
///> Returns true if the joint is a trivial line corner, connecting two
///> Returns true if the joint is a trivial line corner, connecting two
/// segments of the same net, on the same layer.
bool
IsLineCorner
()
const
{
if
(
m_linkedItems
.
size
()
!=
2
)
return
false
;
if
(
m_linkedItems
[
0
]
->
GetKind
()
!=
SEGMENT
||
if
(
m_linkedItems
[
0
]
->
GetKind
()
!=
SEGMENT
||
m_linkedItems
[
1
]
->
GetKind
()
!=
SEGMENT
)
return
false
;
...
...
@@ -99,7 +99,7 @@ public:
///> Links the joint to a given board item (when it's added to the PNS_NODE)
void
Link
(
PNS_ITEM
*
aItem
)
{
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
()
)
...
...
@@ -112,7 +112,7 @@ public:
///> Returns true if the joint became dangling after unlinking.
bool
Unlink
(
PNS_ITEM
*
aItem
)
{
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
LinkedItems
::
iterator
f
=
std
::
find
(
m_linkedItems
.
begin
(),
m_linkedItems
.
end
(),
aItem
);
if
(
f
!=
m_linkedItems
.
end
()
)
...
...
@@ -142,7 +142,7 @@ public:
{
int
n
=
0
;
for
(
LinkedItems
::
const_iterator
i
=
m_linkedItems
.
begin
();
for
(
LinkedItems
::
const_iterator
i
=
m_linkedItems
.
begin
();
i
!=
m_linkedItems
.
end
();
++
i
)
if
(
(
*
i
)
->
GetKind
()
&
aMask
)
n
++
;
...
...
@@ -172,7 +172,7 @@ public:
bool
Overlaps
(
const
PNS_JOINT
&
rhs
)
const
{
return
m_tag
.
pos
==
rhs
.
m_tag
.
pos
&&
return
m_tag
.
pos
==
rhs
.
m_tag
.
pos
&&
m_tag
.
net
==
rhs
.
m_tag
.
net
&&
m_layers
.
Overlaps
(
rhs
.
m_layers
);
}
...
...
@@ -186,7 +186,7 @@ private:
// hash function & comparison operator for boost::unordered_map<>
inline
bool
operator
==
(
PNS_JOINT
::
HashTag
const
&
p1
,
inline
bool
operator
==
(
PNS_JOINT
::
HashTag
const
&
p1
,
PNS_JOINT
::
HashTag
const
&
p2
)
{
return
p1
.
pos
==
p2
.
pos
&&
p1
.
net
==
p2
.
net
;
...
...
pcbnew/router/pns_line.cpp
View file @
22045b61
...
...
@@ -434,7 +434,7 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
path
.
Append
(
l_hull
.
CPoint
(
j
)
);
li
=
l_orig
.
Find
(
l_hull
.
CPoint
(
j
)
);
if
(
li
>=
0
&&
(
li
==
(
l_orig
.
PointCount
()
-
1
)
||
if
(
li
>=
0
&&
(
li
==
(
l_orig
.
PointCount
()
-
1
)
||
outside
[
li
+
1
])
)
break
;
}
...
...
@@ -514,7 +514,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line,
{
index_l
=
(
reverse
?
sc
-
1
-
i
:
i
);
ip
=
s
.
a
;
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
return
true
;
}
...
...
@@ -523,7 +523,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line,
{
index_l
=
(
reverse
?
sc
-
1
-
i
-
1
:
i
+
1
);
ip
=
s
.
b
;
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
printf
(
"vertex %d on-%s %d
\n
"
,
index_l
,
is_vertex
?
"vertex"
:
"edge"
,
index_o
);
return
true
;
}
...
...
@@ -562,7 +562,7 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN obstacle,
if
(
line
.
SegmentCount
()
<
1
)
return
false
;
if
(
obstacle
.
PointInside
(
line
.
CPoint
(
0
)
)
||
if
(
obstacle
.
PointInside
(
line
.
CPoint
(
0
)
)
||
obstacle
.
PointInside
(
line
.
CPoint
(
-
1
)
)
)
return
false
;
...
...
@@ -714,7 +714,7 @@ bool PNS_LINE::Is45Degree()
const
SEG
&
s
=
m_line
.
CSegment
(
i
);
double
angle
=
180.0
/
M_PI
*
atan2
(
(
double
)
s
.
b
.
y
-
(
double
)
s
.
a
.
y
,
atan2
(
(
double
)
s
.
b
.
y
-
(
double
)
s
.
a
.
y
,
(
double
)
s
.
b
.
x
-
(
double
)
s
.
a
.
x
);
if
(
angle
<
0
)
...
...
pcbnew/router/pns_line.h
View file @
22045b61
...
...
@@ -38,17 +38,17 @@ class PNS_VIA;
/**
* Class PNS_LINE
*
* Represents a track on a PCB, connecting two non-trivial joints (that is,
* vias, pads, junctions between multiple traces or two traces different widths
* and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* Instead, they are assembled on-the-fly, based on a via/pad/segment that
* Represents a track on a PCB, connecting two non-trivial joints (that is,
* vias, pads, junctions between multiple traces or two traces different widths
* and combinations of these). PNS_LINEs are NOT stored in the model (PNS_NODE).
* Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them.
*
* PNS_LINEs can be either loose (consisting of segments that do not belong to
* any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* PNS_LINEs can be either loose (consisting of segments that do not belong to
* any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends.
*
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* A PNS_LINE may have a PNS_VIA attached at its and - this is used by via
* dragging/force propagation stuff.
*/
...
...
@@ -141,7 +141,7 @@ public:
m_segmentRefs
->
push_back
(
aSeg
);
}
///> Returns a list of segments from the owning node that constitute this
///> Returns a list of segments from the owning node that constitute this
///> line (or NULL if the line is loose)
LinkedSegments
*
GetLinkedSegments
()
{
...
...
@@ -157,7 +157,7 @@ public:
aSeg
)
!=
m_segmentRefs
->
end
();
}
///> Returns this line, but clipped to the nearest obstacle
///> Returns this line, but clipped to the nearest obstacle
///> along, to avoid collision.
const
PNS_LINE
ClipToNearestObstacle
(
PNS_NODE
*
aNode
)
const
;
...
...
@@ -168,7 +168,7 @@ public:
///> Returns the number of corners of angles specified by mask aAngles.
int
CountCorners
(
int
aAngles
);
///> Calculates a line thightly wrapping a convex hull
///> Calculates a line thightly wrapping a convex hull
///> of an obstacle object (aObstacle).
///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle
...
...
pcbnew/router/pns_line_placer.cpp
View file @
22045b61
...
...
@@ -63,7 +63,7 @@ void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings )
}
void
PNS_LINE_PLACER
::
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
void
PNS_LINE_PLACER
::
StartPlacement
(
const
VECTOR2I
&
aStart
,
int
aNet
,
int
aWidth
,
int
aLayer
)
{
m_direction
=
m_initial_direction
;
...
...
@@ -177,14 +177,14 @@ bool PNS_LINE_PLACER::handlePullback()
DIRECTION_45
last_tail
(
tail
.
Segment
(
-
1
)
);
DIRECTION_45
::
AngleType
angle
=
first_head
.
Angle
(
last_tail
);
// case 1: we have a defined routing direction, and the currently computed
// case 1: we have a defined routing direction, and the currently computed
// head goes in different one.
bool
pullback_1
=
false
;
// (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
// case 2: regardless of the current routing direction, if the tail/head
// case 2: regardless of the current routing direction, if the tail/head
// extremities form an acute or right angle, reduce the tail by one segment
// (and hope that further iterations) will result with a cleaner trace
bool
pullback_2
=
(
angle
==
DIRECTION_45
::
ANG_RIGHT
||
bool
pullback_2
=
(
angle
==
DIRECTION_45
::
ANG_RIGHT
||
angle
==
DIRECTION_45
::
ANG_ACUTE
);
if
(
pullback_1
||
pullback_2
)
...
...
@@ -197,7 +197,7 @@ bool PNS_LINE_PLACER::handlePullback()
n
%
last_tail
.
Format
().
c_str
()
%
first_head
.
Format
().
c_str
()
);
// erase the last point in the tail, hoping that the next iteration will
// result with a head trace that starts with a segment following our
// result with a head trace that starts with a segment following our
// current direction.
if
(
n
<
2
)
tail
.
Clear
();
// don't leave a single-point tail
...
...
@@ -239,7 +239,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
const
SEG
s
=
tail
.
CSegment
(
i
);
DIRECTION_45
dir
(
s
);
// calculate a replacement route and check if it matches
// calculate a replacement route and check if it matches
// the direction of the segment to be replaced
SHAPE_LINE_CHAIN
replacement
=
dir
.
BuildInitialTrace
(
s
.
a
,
aEnd
);
...
...
@@ -289,7 +289,7 @@ bool PNS_LINE_PLACER::mergeHead()
SHAPE_LINE_CHAIN
&
head
=
m_head
.
GetLine
();
SHAPE_LINE_CHAIN
&
tail
=
m_tail
.
GetLine
();
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
const
int
ForbiddenAngles
=
DIRECTION_45
::
ANG_ACUTE
|
DIRECTION_45
::
ANG_HALF_FULL
|
DIRECTION_45
::
ANG_UNDEFINED
;
...
...
@@ -366,7 +366,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
if
(
v
.
PushoutForce
(
m_shove
->
GetCurrentNode
(),
lead
,
force
,
true
,
20
)
)
{
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
SHAPE_LINE_CHAIN
line
=
m_direction
.
BuildInitialTrace
(
aHead
.
GetCLine
().
CPoint
(
0
),
aHead
.
GetCLine
().
CPoint
(
-
1
)
+
force
);
aHead
=
PNS_LINE
(
aHead
,
line
);
...
...
@@ -379,7 +379,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
}
bool
PNS_LINE_PLACER
::
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
PNS_LINE_PLACER
::
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
)
{
// STAGE 1: route a simple two-segment trace between m_p_start and aP...
...
...
@@ -543,7 +543,7 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
PNS_LINE
new_head
(
m_tail
,
opt_line
);
// and see if it could be made simpler by merging obtuse/collnear segments.
// If so, replace the (threshold) last tail points and the head with
// If so, replace the (threshold) last tail points and the head with
// the optimized line
// if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS))
...
...
pcbnew/router/pns_line_placer.h
View file @
22045b61
...
...
@@ -39,7 +39,7 @@ class PNS_ROUTER_BASE;
/**
* Class PNS_LINE_PLACER
*
* Interactively routes a single track. Runs shove and walkaround
* Interactively routes a single track. Runs shove and walkaround
* algorithms when needed.
*/
...
...
@@ -63,9 +63,9 @@ public:
/**
* Function Route()
*
* Re-routes the current track to point aP. Returns true, when routing has
* completed successfully (i.e. the trace end has reached point aP), and false
* if the trace was stuck somewhere on the way. May call routeStep()
* Re-routes the current track to point aP. Returns true, when routing has
* completed successfully (i.e. the trace end has reached point aP), and false
* if the trace was stuck somewhere on the way. May call routeStep()
* repetitively due to mouse smoothing.
* @param aP ending point of current route.
* @return true, if the routing is complete.
...
...
@@ -80,7 +80,7 @@ public:
///> Returns the "head" of the line being placed, that is the volatile part
///> that has not been settled yet
const
PNS_LINE
&
GetHead
()
const
{
return
m_head
;
}
///> Returns the "tail" of the line being placed the part that has been
///> Returns the "tail" of the line being placed the part that has been
///> fixed already (follow mouse mode only)
const
PNS_LINE
&
GetTail
()
const
{
return
m_tail
;
}
...
...
@@ -99,9 +99,9 @@ public:
return
m_p_start
;
}
///> Returns all items in the world that have been affected by the routing
///> Returns all items in the world that have been affected by the routing
///> operation. Used to update data structures of the host application
void
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
void
GetUpdatedItems
(
PNS_NODE
::
ItemVector
&
aRemoved
,
PNS_NODE
::
ItemVector
&
aAdded
);
///> Toggles the current posture (straight/diagonal) of the trace head.
...
...
@@ -114,30 +114,30 @@ private:
static
const
double
m_shoveLengthThreshold
=
1
.
7
;
bool
handleViaPlacement
(
PNS_LINE
&
aHead
);
/**
* Function checkObtusity()
*
* Helper that checks if segments a and b form an obtuse angle
* Helper that checks if segments a and b form an obtuse angle
* (in 45-degree regime).
* @return true, if angle (a, b) is obtuse
*/
bool
checkObtusity
(
const
SEG
&
a
,
const
SEG
&
b
)
const
;
/**
* Function handleSelfIntersections()
*
* Checks if the head of the track intersects its tail. If so, cuts the
* Checks if the head of the track intersects its tail. If so, cuts the
* tail up to the intersecting segment and fixes the head direction to match
* the last segment before the cut.
* @return true if the line has been changed.
*/
bool
handleSelfIntersections
();
/**
* Function handlePullback()
*
* Deals with pull-back: reduces the tail if head trace is moved backwards
* Deals with pull-back: reduces the tail if head trace is moved backwards
* wrs to the current tail direction.
* @return true if the line has been changed.
*/
...
...
@@ -146,7 +146,7 @@ private:
/**
* Function mergeHead()
*
* Moves "estabished" segments from the head to the tail if certain
* Moves "estabished" segments from the head to the tail if certain
* conditions are met.
* @return true, if the line has been changed.
*/
...
...
@@ -155,20 +155,20 @@ private:
/**
* Function reduceTail()
*
* Attempts to reduce the numer of segments in the tail by trying to replace a
* certain number of latest tail segments with a direct trace leading to aEnd
* Attempts to reduce the numer of segments in the tail by trying to replace a
* certain number of latest tail segments with a direct trace leading to aEnd
* that does not collide with anything.
* @param aEnd: current routing destination point.
* @return true if the line has been changed.
*/
bool
reduceTail
(
const
VECTOR2I
&
aEnd
);
void
fixHeadPosture
();
/**
* Function optimizeTailHeadTransition()
*
* Tries to reduce the corner count of the most recent part of tail/head by
* Tries to reduce the corner count of the most recent part of tail/head by
* merging obtuse/collinear segments.
* @return true, if the line has been changed.
*/
...
...
@@ -177,12 +177,12 @@ private:
/**
* Function routeHead()
*
* Computes the head trace between the current start point (m_p_start) and
* point aP, starting with direction defined in m_direction. The trace walks
* around all colliding solid or non-movable items. Movable segments are
* Computes the head trace between the current start point (m_p_start) and
* point aP, starting with direction defined in m_direction. The trace walks
* around all colliding solid or non-movable items. Movable segments are
* ignored, as they'll be handled later by the shove algorithm.
*/
bool
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
routeHead
(
const
VECTOR2I
&
aP
,
PNS_LINE
&
aNewHead
,
bool
aCwWalkaround
=
true
);
/**
...
...
@@ -197,7 +197,7 @@ private:
///> routing mode (walkaround, shove, etc.)
PNS_MODE
m_mode
;
///> follow mouse trail by attaching new segments to the head
///> follow mouse trail by attaching new segments to the head
///> as the cursor moves
bool
m_follow_mouse
;
...
...
pcbnew/router/pns_node.cpp
View file @
22045b61
...
...
@@ -71,7 +71,7 @@ PNS_NODE::~PNS_NODE()
allocNodes
.
erase
(
this
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
if
(
(
*
i
)
->
BelongsTo
(
this
)
)
delete
*
i
;
...
...
@@ -111,14 +111,14 @@ PNS_NODE* PNS_NODE::Branch()
child
->
m_clearanceFunctor
=
m_clearanceFunctor
;
child
->
m_root
=
isRoot
()
?
this
:
m_root
;
// immmediate offspring of the root branch needs not copy anything.
// For the rest, deep-copy joints, overridden item map and pointers
// immmediate offspring of the root branch needs not copy anything.
// For the rest, deep-copy joints, overridden item map and pointers
// to stored items.
if
(
!
isRoot
()
)
{
JointMap
::
iterator
j
;
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
m_index
->
begin
();
i
!=
m_index
->
end
();
++
i
)
child
->
m_index
->
Add
(
*
i
);
...
...
@@ -150,7 +150,7 @@ void PNS_NODE::unlinkParent()
}
// function object that visits potential obstacles and performs
// function object that visits potential obstacles and performs
// the actual collision refining
struct
PNS_NODE
::
obstacleVisitor
{
...
...
@@ -200,7 +200,7 @@ struct PNS_NODE::obstacleVisitor
if
(
!
aItem
->
OfKind
(
m_kindMask
)
)
return
true
;
// check if there is a more recent branch with a newer
// check if there is a more recent branch with a newer
// (possibily modified) version of this item.
if
(
m_override
&&
m_override
->
overrides
(
aItem
)
)
return
true
;
...
...
@@ -428,8 +428,8 @@ struct hitVisitor
const
PNS_ITEMSET
PNS_NODE
::
HitTest
(
const
VECTOR2I
&
aPoint
)
{
PNS_ITEMSET
items
;
// fixme: we treat a point as an infinitely small circle - this is inefficient.
SHAPE_CIRCLE
s
(
aPoint
,
0
);
// fixme: we treat a point as an infinitely small circle - this is inefficient.
SHAPE_CIRCLE
s
(
aPoint
,
0
);
hitVisitor
visitor
(
items
,
aPoint
,
this
);
m_index
->
Query
(
&
s
,
m_maxClearance
,
visitor
);
...
...
@@ -537,12 +537,12 @@ void PNS_NODE::Add( PNS_ITEM* aItem )
void
PNS_NODE
::
doRemove
(
PNS_ITEM
*
aItem
)
{
// case 1: removing an item that is stored in the root node from any branch:
// case 1: removing an item that is stored in the root node from any branch:
// mark it as overridden, but do not remove
if
(
aItem
->
BelongsTo
(
m_root
)
&&
!
isRoot
()
)
m_override
.
insert
(
aItem
);
// case 2: the item belongs to this branch or a parent, non-root branch,
// case 2: the item belongs to this branch or a parent, non-root branch,
// or the root itself and we are the root: remove from the index
else
if
(
!
aItem
->
BelongsTo
(
m_root
)
||
isRoot
()
)
m_index
->
Remove
(
aItem
);
...
...
@@ -948,7 +948,7 @@ void PNS_NODE::Commit( PNS_NODE* aNode )
BOOST_FOREACH
(
PNS_ITEM
*
item
,
aNode
->
m_override
)
Remove
(
item
);
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
aNode
->
m_index
->
begin
();
for
(
PNS_INDEX
::
ItemSet
::
iterator
i
=
aNode
->
m_index
->
begin
();
i
!=
aNode
->
m_index
->
end
();
++
i
)
Add
(
*
i
);
...
...
pcbnew/router/pns_node.h
View file @
22045b61
...
...
@@ -79,13 +79,13 @@ struct PNS_OBSTACLE
/**
* Class PNS_NODE
*
* Keeps the router "world" - i.e. all the tracks, vias, solids in a
* Keeps the router "world" - i.e. all the tracks, vias, solids in a
* hierarchical and indexed way.
* Features:
* - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths
* - lightweight cloning/branching (for recursive optimization and shove
* - lightweight cloning/branching (for recursive optimization and shove
* springback)
**/
...
...
@@ -145,11 +145,11 @@ public:
void
Remove
(
PNS_ITEM
*
aItem
);
void
Replace
(
PNS_ITEM
*
aOldItem
,
PNS_ITEM
*
aNewItem
);
///> Creates a lightweight copy ("branch") of self. Note that if there are
///> Creates a lightweight copy ("branch") of self. Note that if there are
///> any branches in use, their parents must NOT be deleted.
PNS_NODE
*
Branch
();
///> Assembles a line connecting two non-trivial joints the
///> Assembles a line connecting two non-trivial joints the
///> segment aSeg belongs to.
PNS_LINE
*
AssembleLine
(
PNS_SEGMENT
*
aSeg
,
const
OptJoint
&
a
=
OptJoint
(),
const
OptJoint
&
b
=
OptJoint
()
);
...
...
@@ -175,15 +175,15 @@ public:
const
OptJoint
FindJoint
(
const
VECTOR2I
&
aPos
,
int
aLayer
,
int
aNet
);
///> finds all linest between a pair of joints. Used by the loop removal engine.
int
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
int
FindLinesBetweenJoints
(
PNS_JOINT
&
a
,
PNS_JOINT
&
b
,
std
::
vector
<
PNS_LINE
*>&
aLines
);
///> finds the joints corresponding to the ends of line aLine
void
FindLineEnds
(
PNS_LINE
*
aLine
,
PNS_JOINT
&
a
,
PNS_JOINT
&
b
);
///> finds all joints that have an (in)direct connection(s)
///> finds all joints that have an (in)direct connection(s)
///> (i.e. segments/vias) with the joint aJoint.
void
FindConnectedJoints
(
const
PNS_JOINT
&
aJoint
,
void
FindConnectedJoints
(
const
PNS_JOINT
&
aJoint
,
std
::
vector
<
PNS_JOINT
*>&
aConnectedJoints
);
///> Destroys all child nodes. Applicable only to the root node.
...
...
@@ -201,15 +201,15 @@ private:
PNS_NODE
&
operator
=
(
const
PNS_NODE
&
b
);
///> tries to find matching joint and creates a new one if not found
PNS_JOINT
&
touchJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
PNS_JOINT
&
touchJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
);
///> touches a joint and links it to an item
void
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
void
linkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
///> unlinks an item from a joint
void
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
void
unlinkJoint
(
const
VECTOR2I
&
aPos
,
const
PNS_LAYERSET
&
aLayers
,
int
aNet
,
PNS_ITEM
*
aWhere
);
///> helpers for adding/removing items
...
...
@@ -231,7 +231,7 @@ private:
return
m_parent
==
NULL
;
}
///> checks if this branch contains an updated version of the item
///> checks if this branch contains an updated version of the item
///> from the root branch.
bool
overrides
(
PNS_ITEM
*
aItem
)
const
{
...
...
@@ -249,7 +249,7 @@ private:
///> spatial index of all items
// SHAPE_INDEX_LIST<PNS_ITEM *> m_items;
///> hash table with the joints, linking the items. Joints are hashed by
///> hash table with the joints, linking the items. Joints are hashed by
///> their position, layer set and net.
JointMap
m_joints
;
...
...
pcbnew/router/pns_optimizer.cpp
View file @
22045b61
...
...
@@ -109,7 +109,7 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther,
{
if
(
aOther
.
m_cornerCost
<
m_cornerCost
&&
aOther
.
m_lengthCost
<
m_lengthCost
)
return
true
;
else
if
(
aOther
.
m_cornerCost
<
m_cornerCost
*
aCornerTollerance
&&
aOther
.
m_lengthCost
<
m_lengthCost
*
aLengthTollerance
)
return
true
;
...
...
@@ -531,19 +531,19 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
if
(
s
.
x
>=
s
.
y
)
{
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
-
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
+
VECTOR2I
(
-
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
l
,
l
)
)
);
}
else
{
// fixme: this could be done more efficiently
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
+
d_offset
,
c
+
d_offset
+
VECTOR2I
(
l
,
l
)
)
);
breakouts
.
push_back
(
SHAPE_LINE_CHAIN
(
c
,
c
-
d_offset
,
c
-
d_offset
-
VECTOR2I
(
-
l
,
l
)
)
);
...
...
@@ -640,7 +640,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
for
(
int
diag
=
0
;
diag
<
2
;
diag
++
)
{
SHAPE_LINE_CHAIN
v
;
SHAPE_LINE_CHAIN
connect
=
dir
.
BuildInitialTrace
(
l
.
CPoint
(
-
1
),
SHAPE_LINE_CHAIN
connect
=
dir
.
BuildInitialTrace
(
l
.
CPoint
(
-
1
),
line
.
CPoint
(
p
),
diag
==
0
);
DIRECTION_45
dir_bkout
(
l
.
CSegment
(
-
1
)
);
...
...
@@ -691,7 +691,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
if
(
!
checkColliding
(
&
tmp
)
)
{
/*
if(aEnd)
/*
if(aEnd)
* PNSDisplayDebugLine (l_best, 6);
* else
* PNSDisplayDebugLine (l_best, 5);*/
...
...
pcbnew/router/pns_router.cpp
View file @
22045b61
...
...
@@ -53,7 +53,7 @@
using
namespace
std
;
// an ugly singleton for drawing debug items within the router context.
// an ugly singleton for drawing debug items within the router context.
// To be fixed sometime in the future.
static
PNS_ROUTER
*
theRouter
;
...
...
pcbnew/router/pns_shove.cpp
View file @
22045b61
...
...
@@ -429,7 +429,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead )
break
;
}
/*
if(lastWalkSolid == nearest->item)
/*
if(lastWalkSolid == nearest->item)
* {
* fail = true;
* break;
...
...
pcbnew/router/pns_shove.h
View file @
22045b61
...
...
@@ -58,7 +58,7 @@ public:
private
:
static
const
int
ShoveTimeLimit
=
3000
;
bool
tryShove
(
PNS_NODE
*
aWorld
,
PNS_LINE
*
aTrack
,
PNS_LINE
*
aObstacle
,
bool
tryShove
(
PNS_NODE
*
aWorld
,
PNS_LINE
*
aTrack
,
PNS_LINE
*
aObstacle
,
PNS_SEGMENT
&
aObstacleSeg
,
PNS_LINE
*
aResult
,
bool
aInvertWinding
);
ShoveStatus
shoveSingleLine
(
PNS_NODE
*
aNode
,
PNS_LINE
*
aCurrent
,
PNS_LINE
*
aObstacle
,
...
...
pcbnew/router/pns_walkaround.cpp
View file @
22045b61
...
...
@@ -74,7 +74,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
}
}
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
0
],
path_walk
[
0
],
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
0
],
path_walk
[
0
],
path_post
[
0
],
aWindingDirection
);
aPath
.
NewWalkaround
(
current_obs
->
hull
,
path_pre
[
1
],
path_walk
[
1
],
path_post
[
1
],
!
aWindingDirection
);
...
...
pcbnew/router/pns_walkaround.h
View file @
22045b61
...
...
@@ -72,7 +72,7 @@ public:
m_cursorApproachMode
=
aEnabled
;
}
WalkaroundStatus
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
WalkaroundStatus
Route
(
const
PNS_LINE
&
aInitialPath
,
PNS_LINE
&
aWalkPath
,
bool
aOptimize
=
true
);
private
:
...
...
pcbnew/router/router_tool.cpp
View file @
22045b61
...
...
@@ -100,7 +100,7 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode )
}
void
ROUTER_TOOL
::
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
void
ROUTER_TOOL
::
getNetclassDimensions
(
int
aNetCode
,
int
&
aWidth
,
int
&
aViaDiameter
,
int
&
aViaDrill
)
{
BOARD
*
board
=
getModel
<
BOARD
>
(
PCB_T
);
...
...
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