Commit 22045b61 authored by Maciej Suminski's avatar Maciej Suminski

Converted tabs to spaces. Removed trailing whitespaces.

parent ac489ece
...@@ -78,21 +78,21 @@ EDA_DRAW_PANEL_GAL::EDA_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWin ...@@ -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 ); Connect( wxEVT_SIZE, wxSizeEventHandler( EDA_DRAW_PANEL_GAL::onSize ), NULL, this );
/* Generic events for the Tool Dispatcher */ /* Generic events for the Tool Dispatcher */
Connect( wxEVT_MOTION, 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_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_LEFT_DOWN, 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_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_RIGHT_DOWN, 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_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_MIDDLE_DOWN, 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_MOUSEWHEEL, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_CHAR_HOOK, wxEventHandler( EDA_DRAW_PANEL_GAL::skipEvent ) ); 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_UP, wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
Connect( wxEVT_KEY_DOWN, 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( wxEVT_ENTER_WINDOW, wxEventHandler( EDA_DRAW_PANEL_GAL::onEnter ), NULL, this );
Connect( KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE, Connect( KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE,
wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this ); wxEventHandler( EDA_DRAW_PANEL_GAL::onEvent ), NULL, this );
m_refreshTimer.SetOwner( this ); m_refreshTimer.SetOwner( this );
Connect( wxEVT_TIMER, wxTimerEventHandler( EDA_DRAW_PANEL_GAL::onRefreshTimer ), NULL, 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 ) ...@@ -171,7 +171,7 @@ void EDA_DRAW_PANEL_GAL::Refresh( bool eraseBackground, const wxRect* rect )
m_refreshTimer.Start( ( MinRefreshPeriod - delta ).ToLong(), true ); m_refreshTimer.Start( ( MinRefreshPeriod - delta ).ToLong(), true );
m_pendingRefresh = true; m_pendingRefresh = true;
} }
} }
void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType ) void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
...@@ -223,13 +223,13 @@ 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 ) void EDA_DRAW_PANEL_GAL::onEvent( wxEvent& aEvent )
{ {
if( !m_eventDispatcher ) if( !m_eventDispatcher )
{ {
aEvent.Skip(); aEvent.Skip();
return; return;
} }
else else
{ {
m_eventDispatcher->DispatchWxEvent( aEvent ); m_eventDispatcher->DispatchWxEvent( aEvent );
} }
......
...@@ -159,7 +159,6 @@ void COLOR4D::FromHSV( double aInH, double aInS, double aInV ) ...@@ -159,7 +159,6 @@ void COLOR4D::FromHSV( double aInH, double aInS, double aInV )
b = q; b = q;
break; break;
} }
} }
...@@ -168,7 +167,7 @@ COLOR4D& COLOR4D::Saturate( double aFactor ) ...@@ -168,7 +167,7 @@ COLOR4D& COLOR4D::Saturate( double aFactor )
double h, s, v; double h, s, v;
ToHSV( h, s, v ); ToHSV( h, s, v );
FromHSV( h, aFactor, 1.0 ); FromHSV( h, aFactor, 1.0 );
return *this; return *this;
} }
...@@ -127,7 +127,7 @@ void OPENGL_GAL::BeginDrawing() ...@@ -127,7 +127,7 @@ void OPENGL_GAL::BeginDrawing()
glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y );
// Create the screen transformation // 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 ); -depthRange.x, -depthRange.y );
// Prepare rendering target buffers // Prepare rendering target buffers
......
...@@ -49,7 +49,7 @@ void strokedCircle( vec2 aCoord, float aRadius, float aWidth ) ...@@ -49,7 +49,7 @@ void strokedCircle( vec2 aCoord, float aRadius, float aWidth )
float innerRadius = aRadius - ( aWidth / 2 ); float innerRadius = aRadius - ( aWidth / 2 );
float relWidth = innerRadius / outerRadius; float relWidth = innerRadius / outerRadius;
if( ( dot( aCoord, aCoord ) < 1.0f ) && if( ( dot( aCoord, aCoord ) < 1.0f ) &&
( dot( aCoord, aCoord ) > relWidth * relWidth ) ) ( dot( aCoord, aCoord ) > relWidth * relWidth ) )
gl_FragColor = gl_Color; gl_FragColor = gl_Color;
else else
......
...@@ -42,23 +42,23 @@ void main() ...@@ -42,23 +42,23 @@ void main()
{ {
// Pass attributes to the fragment shader // Pass attributes to the fragment shader
shaderParams = attrShaderParams; shaderParams = attrShaderParams;
if( shaderParams[0] == SHADER_LINE ) if( shaderParams[0] == SHADER_LINE )
{ {
float lineWidth = shaderParams[3]; float lineWidth = shaderParams[3];
float worldScale = gl_ModelViewMatrix[0][0]; float worldScale = gl_ModelViewMatrix[0][0];
float scale; float scale;
// Make lines appear to be at least 1 pixel wide // Make lines appear to be at least 1 pixel wide
if( worldScale * lineWidth < MIN_WIDTH ) if( worldScale * lineWidth < MIN_WIDTH )
scale = MIN_WIDTH / ( worldScale * lineWidth ); scale = MIN_WIDTH / ( worldScale * lineWidth );
else else
scale = 1.0f; scale = 1.0f;
gl_Position = gl_ModelViewProjectionMatrix * gl_Position = gl_ModelViewProjectionMatrix *
( gl_Vertex + vec4( shaderParams.yz * scale, 0.0, 0.0 ) ); ( 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 ) ) ( shaderParams[0] == SHADER_FILLED_CIRCLE ) )
{ {
// Compute relative circle coordinates basing on indices // Compute relative circle coordinates basing on indices
...@@ -69,7 +69,7 @@ void main() ...@@ -69,7 +69,7 @@ void main()
circleCoords = vec2( sqrt( 3.0f ), -1.0f ); circleCoords = vec2( sqrt( 3.0f ), -1.0f );
else if( shaderParams[1] == 3.0f ) else if( shaderParams[1] == 3.0f )
circleCoords = vec2( 0.0f, 2.0f ); circleCoords = vec2( 0.0f, 2.0f );
// Semicircle // Semicircle
else if( shaderParams[1] == 4.0f ) else if( shaderParams[1] == 4.0f )
circleCoords = vec2( -3.0f / sqrt( 3.0f ), 0.0f ); circleCoords = vec2( -3.0f / sqrt( 3.0f ), 0.0f );
...@@ -81,7 +81,7 @@ void main() ...@@ -81,7 +81,7 @@ void main()
// Make the line appear to be at least 1 pixel wide // Make the line appear to be at least 1 pixel wide
float lineWidth = shaderParams[3]; float lineWidth = shaderParams[3];
float worldScale = gl_ModelViewMatrix[0][0]; float worldScale = gl_ModelViewMatrix[0][0];
// Make lines appear to be at least 1 pixel width // Make lines appear to be at least 1 pixel width
if( worldScale * lineWidth < MIN_WIDTH ) if( worldScale * lineWidth < MIN_WIDTH )
shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth ); shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
...@@ -93,7 +93,7 @@ void main() ...@@ -93,7 +93,7 @@ void main()
// Pass through the coordinates like in the fixed pipeline // Pass through the coordinates like in the fixed pipeline
gl_Position = ftransform(); gl_Position = ftransform();
} }
gl_FrontColor = gl_Color; gl_FrontColor = gl_Color;
} }
...@@ -32,38 +32,38 @@ template<typename T> int sgn( T val ) { ...@@ -32,38 +32,38 @@ template<typename T> int sgn( T val ) {
bool SEG::PointCloserThan( const VECTOR2I& aP, int dist ) const bool SEG::PointCloserThan( const VECTOR2I& aP, int dist ) const
{ {
VECTOR2I d = b - a; VECTOR2I d = b - a;
ecoord dist_sq = (ecoord) dist * dist; 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 ); SEG::ecoord t = d.Dot( aP - a );
if( t <= 0 || !l_squared ) if( t <= 0 || !l_squared )
return ( aP - a ).SquaredEuclideanNorm() < dist_sq; return ( aP - a ).SquaredEuclideanNorm() < dist_sq;
else if( t >= l_squared ) else if( t >= l_squared )
return ( aP - b ).SquaredEuclideanNorm() < dist_sq; return ( aP - b ).SquaredEuclideanNorm() < dist_sq;
int dxdy = abs( d.x ) - abs( d.y ); int dxdy = abs( d.x ) - abs( d.y );
if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 ) if( ( dxdy >= -1 && dxdy <= 1 ) || abs( d.x ) <= 1 || abs( d.y ) <= 1 )
{ {
int ca = -sgn( d.y ); int ca = -sgn( d.y );
int cb = sgn( d.x ); int cb = sgn( d.x );
int cc = -ca * a.x - cb * a.y; int cc = -ca * a.x - cb * a.y;
ecoord num = ca * aP.x + cb * aP.y + cc; ecoord num = ca * aP.x + cb * aP.y + cc;
num *= num; num *= num;
if( ca && cb ) if( ca && cb )
num >>= 1; num >>= 1;
if( num > ( dist_sq + 100 ) ) if( num > ( dist_sq + 100 ) )
return false; return false;
else if( num < ( dist_sq - 100 ) ) else if( num < ( dist_sq - 100 ) )
return true; return true;
} }
VECTOR2I nearest; VECTOR2I nearest;
nearest.x = a.x + rescale( t, (ecoord)d.x, l_squared ); nearest.x = a.x + rescale( t, (ecoord)d.x, l_squared );
nearest.y = a.y + rescale( t, (ecoord)d.y, 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 ...@@ -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.... // fixme: rather inefficient....
if( Intersect( aSeg ) ) if( Intersect( aSeg ) )
...@@ -91,62 +91,62 @@ SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const ...@@ -91,62 +91,62 @@ SEG::ecoord SEG::SquaredDistance( const SEG& aSeg ) const
return m; return m;
} }
OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const OPT_VECTOR2I SEG::Intersect( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines ) const
{ {
const VECTOR2I e ( b - a ); const VECTOR2I e ( b - a );
const VECTOR2I f ( aSeg.b - aSeg.a ); const VECTOR2I f ( aSeg.b - aSeg.a );
const VECTOR2I ac ( aSeg.a - a ); const VECTOR2I ac ( aSeg.a - a );
ecoord d = f.Cross( e ); ecoord d = f.Cross( e );
ecoord p = f.Cross( ac ); ecoord p = f.Cross( ac );
ecoord q = e.Cross( ac ); ecoord q = e.Cross( ac );
if( d == 0 ) if( d == 0 )
return OPT_VECTOR2I(); return OPT_VECTOR2I();
if ( !aLines && d > 0 && ( q < 0 || q > d || p < 0 || p > d ) ) if ( !aLines && d > 0 && ( q < 0 || q > d || p < 0 || p > d ) )
return OPT_VECTOR2I(); return OPT_VECTOR2I();
if ( !aLines && d < 0 && ( q < d || p < d || p > 0 || q > 0 ) ) if ( !aLines && d < 0 && ( q < d || p < d || p > 0 || q > 0 ) )
return OPT_VECTOR2I(); return OPT_VECTOR2I();
if ( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) ) if ( !aLines && aIgnoreEndpoints && ( q == 0 || q == d ) && ( p == 0 || p == d ) )
return OPT_VECTOR2I(); return OPT_VECTOR2I();
VECTOR2I ip( aSeg.a.x + rescale( q, (ecoord)f.x, d ), VECTOR2I ip( aSeg.a.x + rescale( q, (ecoord)f.x, d ),
aSeg.a.y + rescale( q, (ecoord)f.y, d ) ); aSeg.a.y + rescale( q, (ecoord)f.y, d ) );
return ip; return ip;
} }
bool SEG::ccw( const VECTOR2I& a, const VECTOR2I& b, const VECTOR2I& c ) const bool SEG::ccw( const VECTOR2I& a, const VECTOR2I& b, const VECTOR2I& c ) const
{ {
return (ecoord)( c.y - a.y ) * ( b.x - a.x ) > (ecoord)( b.y - a.y ) * ( c.x - a.x ); return (ecoord)( c.y - a.y ) * ( b.x - a.x ) > (ecoord)( b.y - a.y ) * ( c.x - a.x );
} }
bool SEG::Collide( const SEG& aSeg, int aClearance ) const bool SEG::Collide( const SEG& aSeg, int aClearance ) const
{ {
// check for intersection // check for intersection
// fixme: move to a method // fixme: move to a method
if( ccw( a, aSeg.a, aSeg.b ) != ccw( b, aSeg.a, aSeg.b ) && if( ccw( a, aSeg.a, aSeg.b ) != ccw( b, aSeg.a, aSeg.b ) &&
ccw( a, b, aSeg.a ) != ccw( a, b, aSeg.b ) ) ccw( a, b, aSeg.a ) != ccw( a, b, aSeg.b ) )
return true; return true;
#define CHK(_seg, _pt) \ #define CHK(_seg, _pt) \
if( (_seg).PointCloserThan (_pt, aClearance ) ) return true; if( (_seg).PointCloserThan (_pt, aClearance ) ) return true;
CHK( *this, aSeg.a ); CHK( *this, aSeg.a );
CHK( *this, aSeg.b ); CHK( *this, aSeg.b );
CHK( aSeg, a ); CHK( aSeg, a );
CHK( aSeg, b ); CHK( aSeg, b );
#undef CHK #undef CHK
return false; return false;
} }
bool SEG::Contains( const VECTOR2I& aP ) const bool SEG::Contains( const VECTOR2I& aP ) const
{ {
return PointCloserThan( aP, 1 ); return PointCloserThan( aP, 1 );
} }
...@@ -34,200 +34,200 @@ typedef VECTOR2I::extended_type ecoord; ...@@ -34,200 +34,200 @@ typedef VECTOR2I::extended_type ecoord;
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int aClearance, static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV ) bool aNeedMTV, VECTOR2I& aMTV )
{ {
ecoord min_dist = aClearance + aA.GetRadius() + aB.GetRadius(); ecoord min_dist = aClearance + aA.GetRadius() + aB.GetRadius();
ecoord min_dist_sq = min_dist * min_dist; ecoord min_dist_sq = min_dist * min_dist;
const VECTOR2I delta = aB.GetCenter() - aA.GetCenter();
ecoord dist_sq = delta.SquaredEuclideanNorm(); const VECTOR2I delta = aB.GetCenter() - aA.GetCenter();
if ( dist_sq >= min_dist_sq ) ecoord dist_sq = delta.SquaredEuclideanNorm();
return false;
if ( aNeedMTV )
aMTV = delta.Resize( sqrt ( abs( min_dist_sq - dist_sq ) ) + 1 );
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, static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV ) bool aNeedMTV, VECTOR2I& aMTV )
{ {
const VECTOR2I c = aB.GetCenter(); const VECTOR2I c = aB.GetCenter();
const VECTOR2I p0 = aA.GetPosition(); const VECTOR2I p0 = aA.GetPosition();
const VECTOR2I size = aA.GetSize(); const VECTOR2I size = aA.GetSize();
const ecoord r = aB.GetRadius(); const ecoord r = aB.GetRadius();
const ecoord min_dist = aClearance + r; const ecoord min_dist = aClearance + r;
const ecoord min_dist_sq = min_dist * min_dist; const ecoord min_dist_sq = min_dist * min_dist;
if ( aA.BBox( 0 ).Contains( c ) ) if ( aA.BBox( 0 ).Contains( c ) )
return true; return true;
const VECTOR2I vts[] = { const VECTOR2I vts[] = {
VECTOR2I(p0.x, p0.y), VECTOR2I(p0.x, p0.y),
VECTOR2I(p0.x, p0.y + size.y), VECTOR2I(p0.x, p0.y + size.y),
VECTOR2I(p0.x + size.x, p0.y + size.y), VECTOR2I(p0.x + size.x, p0.y + size.y),
VECTOR2I(p0.x + size.x, p0.y), VECTOR2I(p0.x + size.x, p0.y),
VECTOR2I(p0.x, p0.y) }; VECTOR2I(p0.x, p0.y) };
ecoord nearest_seg_dist_sq = VECTOR2I::ECOORD_MAX; ecoord nearest_seg_dist_sq = VECTOR2I::ECOORD_MAX;
VECTOR2I nearest; VECTOR2I nearest;
bool inside = c.x >= p0.x && c.x <= ( p0.x + size.x ) bool inside = c.x >= p0.x && c.x <= ( p0.x + size.x )
&& c.y >= p0.y && c.y <= ( p0.y + size.y ); && c.y >= p0.y && c.y <= ( p0.y + size.y );
if( !inside ) if( !inside )
{ {
for( int i = 0; i < 4; i++ ) for( int i = 0; i < 4; i++ )
{ {
const SEG seg( vts[i], vts[i+1] ); const SEG seg( vts[i], vts[i+1] );
ecoord dist_sq = seg.SquaredDistance( c ); ecoord dist_sq = seg.SquaredDistance( c );
if( dist_sq < min_dist_sq ) if( dist_sq < min_dist_sq )
{ {
if( !aNeedMTV ) if( !aNeedMTV )
return true; return true;
else else
{ {
nearest = seg.NearestPoint( c ); nearest = seg.NearestPoint( c );
nearest_seg_dist_sq = dist_sq; nearest_seg_dist_sq = dist_sq;
} }
} }
} }
} }
if( nearest_seg_dist_sq >= min_dist_sq && !inside ) if( nearest_seg_dist_sq >= min_dist_sq && !inside )
return false; return false;
VECTOR2I delta = c - nearest; VECTOR2I delta = c - nearest;
if( !aNeedMTV ) if( !aNeedMTV )
return true; return true;
if( inside ) if( inside )
aMTV = -delta.Resize( sqrt( abs( r * r + nearest_seg_dist_sq ) + 1 ) ); aMTV = -delta.Resize( sqrt( abs( r * r + nearest_seg_dist_sq ) + 1 ) );
else else
aMTV = delta.Resize( sqrt( abs( r * r - nearest_seg_dist_sq ) + 1 ) ); aMTV = delta.Resize( sqrt( abs( r * r - nearest_seg_dist_sq ) + 1 ) );
return true; return true;
} }
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance, static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV ) bool aNeedMTV, VECTOR2I& aMTV )
{ {
for( int s = 0; s < aB.SegmentCount(); s++ ) for( int s = 0; s < aB.SegmentCount(); s++ )
{ {
if ( aA.Collide( aB.CSegment( s ), aClearance ) ) if ( aA.Collide( aB.CSegment( s ), aClearance ) )
return true; return true;
} }
return false; return false;
} }
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN& aB, int aClearance, static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV ) bool aNeedMTV, VECTOR2I& aMTV )
{ {
for( int i = 0; i < aB.SegmentCount(); i++ ) for( int i = 0; i < aB.SegmentCount(); i++ )
if( aA.Collide( aB.CSegment(i), aClearance ) ) if( aA.Collide( aB.CSegment(i), aClearance ) )
return true; return true;
return false; return false;
} }
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance, static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV ) bool aNeedMTV, VECTOR2I& aMTV )
{ {
for( int s = 0; s < aB.SegmentCount(); s++ ) for( int s = 0; s < aB.SegmentCount(); s++ )
{ {
SEG seg = aB.CSegment( s ); SEG seg = aB.CSegment( s );
if( aA.Collide( seg, aClearance ) ) if( aA.Collide( seg, aClearance ) )
return true; return true;
} }
return false; return false;
} }
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV ) bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{ {
switch( aA->Type() ) switch( aA->Type() )
{ {
case SH_RECT: case SH_RECT:
switch( aB->Type() ) switch( aB->Type() )
{ {
case SH_CIRCLE: case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_RECT*>( aA ), return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN: case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_RECT*>( aA ), return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
default: default:
break; break;
} }
case SH_CIRCLE: case SH_CIRCLE:
switch( aB->Type() ) switch( aB->Type() )
{ {
case SH_RECT: case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( aB ), return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_CIRCLE*>( aA ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_CIRCLE*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_CIRCLE: case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ), return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN: case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ), return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN *>( aB ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_LINE_CHAIN *>( aB ), aClearance, aNeedMTV, aMTV );
default: default:
break; break;
} }
case SH_LINE_CHAIN: case SH_LINE_CHAIN:
switch( aB->Type() ) switch( aB->Type() )
{ {
case SH_RECT: case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( aB ), return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_CIRCLE: case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( aB ), return Collide( *static_cast<const SHAPE_CIRCLE*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN: case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( aA ), return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV ); *static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
default: default:
break; break;
} }
default: default:
break; break;
} }
bool unsupported_collision = true; bool unsupported_collision = true;
assert( unsupported_collision == false ); assert( unsupported_collision == false );
return false; return false;
} }
bool SHAPE::Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const bool SHAPE::Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const
{ {
return CollideShapes( this, aShape, aClerance, true, aMTV); return CollideShapes( this, aShape, aClerance, true, aMTV);
} }
bool SHAPE::Collide ( const SHAPE* aShape, int aClerance ) const bool SHAPE::Collide ( const SHAPE* aShape, int aClerance ) const
{ {
VECTOR2I dummy; VECTOR2I dummy;
return CollideShapes( this, aShape, aClerance, false, dummy ); return CollideShapes( this, aShape, aClerance, false, dummy );
} }
...@@ -30,491 +30,491 @@ using boost::optional; ...@@ -30,491 +30,491 @@ using boost::optional;
bool SHAPE_LINE_CHAIN::Collide( const VECTOR2I& aP, int aClearance ) const bool SHAPE_LINE_CHAIN::Collide( const VECTOR2I& aP, int aClearance ) const
{ {
assert( false ); assert( false );
return false; return false;
} }
bool SHAPE_LINE_CHAIN::Collide( const BOX2I& aBox, int aClearance ) const bool SHAPE_LINE_CHAIN::Collide( const BOX2I& aBox, int aClearance ) const
{ {
assert( false ); assert( false );
return false; return false;
} }
bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance ) const bool SHAPE_LINE_CHAIN::Collide( const SEG& aSeg, int aClearance ) const
{ {
BOX2I box_a( aSeg.a, aSeg.b - aSeg.a ); BOX2I box_a( aSeg.a, aSeg.b - aSeg.a );
BOX2I::ecoord_type dist_sq = (BOX2I::ecoord_type) aClearance * aClearance; BOX2I::ecoord_type dist_sq = (BOX2I::ecoord_type) aClearance * aClearance;
for( int i = 0; i < SegmentCount() ;i++ ) for( int i = 0; i < SegmentCount() ;i++ )
{ {
const SEG& s = CSegment( i ); const SEG& s = CSegment( i );
BOX2I box_b( s.a, s.b - s.a ); BOX2I box_b( s.a, s.b - s.a );
BOX2I::ecoord_type d = box_a.SquaredDistance ( box_b ); BOX2I::ecoord_type d = box_a.SquaredDistance ( box_b );
if( d < dist_sq ) if( d < dist_sq )
{ {
if( s.Collide( aSeg, aClearance ) ) if( s.Collide( aSeg, aClearance ) )
return true; return true;
} }
} }
return false; 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 ); SHAPE_LINE_CHAIN a( *this );
reverse( a.m_points.begin(), a.m_points.end() ); reverse( a.m_points.begin(), a.m_points.end() );
a.m_closed = m_closed; a.m_closed = m_closed;
return a; return a;
} }
int SHAPE_LINE_CHAIN::Length() const int SHAPE_LINE_CHAIN::Length() const
{ {
int l = 0; int l = 0;
for( int i = 0; i < SegmentCount(); i++ ) for( int i = 0; i < SegmentCount(); i++ )
l += CSegment( i ).Length(); l += CSegment( i ).Length();
return l; return l;
} }
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP ) void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP )
{ {
if( aEndIndex < 0 ) if( aEndIndex < 0 )
aEndIndex += PointCount(); aEndIndex += PointCount();
if( aStartIndex < 0 ) if( aStartIndex < 0 )
aStartIndex += PointCount(); aStartIndex += PointCount();
if( aStartIndex == aEndIndex ) if( aStartIndex == aEndIndex )
m_points [aStartIndex] = aP; m_points [aStartIndex] = aP;
else else
{ {
m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 ); m_points.erase( m_points.begin() + aStartIndex + 1, m_points.begin() + aEndIndex + 1 );
m_points[aStartIndex] = aP; m_points[aStartIndex] = aP;
} }
} }
void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine ) void SHAPE_LINE_CHAIN::Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine )
{ {
if( aEndIndex < 0 ) if( aEndIndex < 0 )
aEndIndex += PointCount(); aEndIndex += PointCount();
if( aStartIndex < 0 ) if( aStartIndex < 0 )
aStartIndex += PointCount(); 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 );
m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() ); m_points.insert( m_points.begin() + aStartIndex, aLine.m_points.begin(), aLine.m_points.end() );
} }
void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex ) void SHAPE_LINE_CHAIN::Remove( int aStartIndex, int aEndIndex )
{ {
if(aEndIndex < 0) if(aEndIndex < 0)
aEndIndex += PointCount(); aEndIndex += PointCount();
if(aStartIndex < 0) if(aStartIndex < 0)
aStartIndex += PointCount(); 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 SHAPE_LINE_CHAIN::Distance( const VECTOR2I& aP ) const
{ {
int d = INT_MAX; int d = INT_MAX;
for( int s = 0; s < SegmentCount(); s++ ) for( int s = 0; s < SegmentCount(); s++ )
d = min( d, CSegment( s ).Distance( aP ) ); d = min( d, CSegment( s ).Distance( aP ) );
return d; return d;
} }
int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP ) int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
{ {
int ii = -1; int ii = -1;
int min_dist = 2; int min_dist = 2;
ii = Find( aP ); ii = Find( aP );
if( ii >= 0 ) if( ii >= 0 )
return ii; return ii;
for( int s = 0; s < SegmentCount(); s++ ) for( int s = 0; s < SegmentCount(); s++ )
{ {
const SEG seg = CSegment( s ); const SEG seg = CSegment( s );
int dist = seg.Distance( aP ); int dist = seg.Distance( aP );
// make sure we are not producing a 'slightly concave' primitive. This might happen // 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 aP lies very close to one of already existing points.
if( dist < min_dist && seg.a != aP && seg.b != aP ) if( dist < min_dist && seg.a != aP && seg.b != aP )
{ {
min_dist = dist; min_dist = dist;
ii = s; ii = s;
} }
} }
if( ii >= 0 ) if( ii >= 0 )
{ {
m_points.insert( m_points.begin() + ii + 1, aP ); m_points.insert( m_points.begin() + ii + 1, aP );
return ii + 1; return ii + 1;
} }
return -1; return -1;
} }
int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const int SHAPE_LINE_CHAIN::Find( const VECTOR2I& aP ) const
{ {
for( int s = 0; s< PointCount(); s++ ) for( int s = 0; s< PointCount(); s++ )
if( CPoint( s ) == aP ) if( CPoint( s ) == aP )
return s; return s;
return -1; return -1;
} }
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
{ {
SHAPE_LINE_CHAIN rv; SHAPE_LINE_CHAIN rv;
if( aEndIndex < 0 ) if( aEndIndex < 0 )
aEndIndex += PointCount(); aEndIndex += PointCount();
if( aStartIndex < 0 ) if( aStartIndex < 0 )
aStartIndex += PointCount(); aStartIndex += PointCount();
for( int i = aStartIndex; i <= aEndIndex; i++ ) for( int i = aStartIndex; i <= aEndIndex; i++ )
rv.Append( m_points[i] ); rv.Append( m_points[i] );
return rv; return rv;
} }
struct compareOriginDistance struct compareOriginDistance
{ {
compareOriginDistance( VECTOR2I& aOrigin ): compareOriginDistance( VECTOR2I& aOrigin ):
m_origin( aOrigin ) {}; m_origin( aOrigin ) {};
bool operator()( const SHAPE_LINE_CHAIN::Intersection& aA, bool operator()( const SHAPE_LINE_CHAIN::Intersection& aA,
const SHAPE_LINE_CHAIN::Intersection& aB ) const SHAPE_LINE_CHAIN::Intersection& aB )
{ {
return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm(); 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 int SHAPE_LINE_CHAIN::Intersect( const SEG& aSeg, Intersections& aIp ) const
{ {
for( int s = 0; s < SegmentCount(); s++ ) for( int s = 0; s < SegmentCount(); s++ )
{ {
OPT_VECTOR2I p = CSegment( s ).Intersect( aSeg ); OPT_VECTOR2I p = CSegment( s ).Intersect( aSeg );
if( p ) if( p )
{ {
Intersection is; Intersection is;
is.our = CSegment( s ); is.our = CSegment( s );
is.their = aSeg; is.their = aSeg;
is.p = *p; is.p = *p;
aIp.push_back( is ); aIp.push_back( is );
} }
} }
compareOriginDistance comp( aSeg.a ); compareOriginDistance comp( aSeg.a );
sort( aIp.begin(), aIp.end(), comp ); sort( aIp.begin(), aIp.end(), comp );
return aIp.size(); return aIp.size();
} }
int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const int SHAPE_LINE_CHAIN::Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const
{ {
BOX2I bb_other = aChain.BBox(); BOX2I bb_other = aChain.BBox();
for ( int s1 = 0; s1 < SegmentCount(); s1++ ) for ( int s1 = 0; s1 < SegmentCount(); s1++ )
{ {
const SEG& a = CSegment( s1 ); const SEG& a = CSegment( s1 );
const BOX2I bb_cur( a.a, a.b - a.a ); const BOX2I bb_cur( a.a, a.b - a.a );
if( !bb_other.Intersects( bb_cur ) ) if( !bb_other.Intersects( bb_cur ) )
continue; continue;
for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ ) for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
{ {
const SEG& b = aChain.CSegment( s2 ); const SEG& b = aChain.CSegment( s2 );
Intersection is; Intersection is;
if( a.Collinear( b ) ) if( a.Collinear( b ) )
{ {
if( a.Contains( b.a ) ) { is.p = b.a; aIp.push_back( is ); } if( a.Contains( b.a ) ) { is.p = b.a; aIp.push_back( is ); }
if( a.Contains( b.b ) ) { is.p = b.b; 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.a ) ) { is.p = a.a; aIp.push_back( is ); }
if( b.Contains( a.b ) ) { is.p = a.b; aIp.push_back( is ); } if( b.Contains( a.b ) ) { is.p = a.b; aIp.push_back( is ); }
} }
else else
{ {
OPT_VECTOR2I p = a.Intersect( b ); OPT_VECTOR2I p = a.Intersect( b );
if( p ) if( p )
{ {
is.p = *p; is.p = *p;
is.our = a; is.our = a;
is.their = b; is.their = b;
aIp.push_back( is ); aIp.push_back( is );
} }
} }
} }
} }
return aIp.size(); return aIp.size();
for( int s1 = 0; s1 < SegmentCount(); s1++ ) for( int s1 = 0; s1 < SegmentCount(); s1++ )
{ {
for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ ) for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
{ {
const SEG& a = CSegment( s1 ); const SEG& a = CSegment( s1 );
const SEG& b = aChain.CSegment( s2 ); const SEG& b = aChain.CSegment( s2 );
OPT_VECTOR2I p = a.Intersect( b ); OPT_VECTOR2I p = a.Intersect( b );
Intersection is; Intersection is;
if( p ) if( p )
{ {
is.p = *p; is.p = *p;
is.our = a; is.our = a;
is.their = b; is.their = b;
aIp.push_back( is ); aIp.push_back( is );
} }
else if( a.Collinear( b ) ) else if( a.Collinear( b ) )
{ {
if( a.a != b.a && a.a != b.b && b.Contains( a.a ) ) if( a.a != b.a && a.a != b.b && b.Contains( a.a ) )
{ {
is.p = a.a; is.p = a.a;
is.our = a; is.our = a;
is.their = b; is.their = b;
aIp.push_back( is ); aIp.push_back( is );
} }
else if( a.b != b.a && a.b != b.b && b.Contains( a.b ) ) else if( a.b != b.a && a.b != b.b && b.Contains( a.b ) )
{ {
is.p = a.b; is.p = a.b;
is.our = a; is.our = a;
is.their = b; is.their = b;
aIp.push_back( is ); aIp.push_back( is );
} }
} }
} }
} }
return aIp.size(); return aIp.size();
} }
int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const int SHAPE_LINE_CHAIN::PathLength( const VECTOR2I& aP ) const
{ {
int sum = 0; int sum = 0;
for( int i = 0; i < SegmentCount(); i++ ) for( int i = 0; i < SegmentCount(); i++ )
{ {
const SEG seg = CSegment( i ); const SEG seg = CSegment( i );
int d = seg.Distance( aP ); int d = seg.Distance( aP );
if( d <= 1 ) if( d <= 1 )
{ {
sum += ( aP - seg.a ).EuclideanNorm(); sum += ( aP - seg.a ).EuclideanNorm();
return sum; return sum;
} }
else else
sum += seg.Length(); sum += seg.Length();
} }
return -1; return -1;
} }
bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
{ {
if( !m_closed || SegmentCount() < 3 ) if( !m_closed || SegmentCount() < 3 )
return false; return false;
int cur = CSegment(0).Side( aP ); int cur = CSegment(0).Side( aP );
if( cur == 0 ) if( cur == 0 )
return false; return false;
for( int i = 1; i < SegmentCount(); i++ ) for( int i = 1; i < SegmentCount(); i++ )
{ {
const SEG s = CSegment( i ); const SEG s = CSegment( i );
if( aP == s.a || aP == s.b ) // edge does not belong to the interior! if( aP == s.a || aP == s.b ) // edge does not belong to the interior!
return false; return false;
if( s.Side(aP) != cur ) if( s.Side(aP) != cur )
return false; return false;
} }
return true; return true;
} }
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
{ {
if( SegmentCount() < 1 ) if( SegmentCount() < 1 )
return m_points[0] == aP; return m_points[0] == aP;
for( int i = 1; i < SegmentCount(); i++ ) for( int i = 1; i < SegmentCount(); i++ )
{ {
const SEG s = CSegment( i ); const SEG s = CSegment( i );
if( s.a == aP || s.b == aP )
return true;
if( s.Distance(aP) <= 1 ) if( s.a == aP || s.b == aP )
return true; return true;
}
return false; if( s.Distance(aP) <= 1 )
return true;
}
return false;
} }
const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersecting() const const optional<SHAPE_LINE_CHAIN::Intersection> SHAPE_LINE_CHAIN::SelfIntersecting() const
{ {
for( int s1 = 0; s1 < SegmentCount(); s1++ ) for( int s1 = 0; s1 < SegmentCount(); s1++ )
{ {
for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ ) for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ )
{ {
const VECTOR2I s2a = CSegment( s2 ).a, s2b = CSegment( s2 ).b; const VECTOR2I s2a = CSegment( s2 ).a, s2b = CSegment( s2 ).b;
if( s1 + 1 != s2 && CSegment( s1 ).Contains( s2a ) ) if( s1 + 1 != s2 && CSegment( s1 ).Contains( s2a ) )
{ {
Intersection is; Intersection is;
is.our = CSegment( s1 ); is.our = CSegment( s1 );
is.their = CSegment( s2 ); is.their = CSegment( s2 );
is.p = s2a; is.p = s2a;
return is; return is;
} }
else if( CSegment( s1 ).Contains(s2b ) ) else if( CSegment( s1 ).Contains(s2b ) )
{ {
Intersection is; Intersection is;
is.our = CSegment( s1 ); is.our = CSegment( s1 );
is.their = CSegment( s2 ); is.their = CSegment( s2 );
is.p = s2b; is.p = s2b;
return is; return is;
} }
else else
{ {
OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true ); OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true );
if( p ) if( p )
{ {
Intersection is; Intersection is;
is.our = CSegment( s1 ); is.our = CSegment( s1 );
is.their = CSegment( s2 ); is.their = CSegment( s2 );
is.p = *p; is.p = *p;
return is; return is;
} }
} }
} }
} }
return optional<Intersection>(); return optional<Intersection>();
} }
SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify() SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify()
{ {
vector<VECTOR2I> pts_unique; vector<VECTOR2I> pts_unique;
if( PointCount() < 2 ) if( PointCount() < 2 )
{ {
return *this; return *this;
} }
else if( PointCount() == 2 ) else if( PointCount() == 2 )
{ {
if( m_points[0] == m_points[1] ) if( m_points[0] == m_points[1] )
m_points.erase( m_points.end() ); m_points.erase( m_points.end() );
return *this; return *this;
} }
int i = 0; int i = 0;
int np = PointCount(); int np = PointCount();
// stage 1: eliminate duplicate vertices // stage 1: eliminate duplicate vertices
while ( i < np ) while ( i < np )
{ {
int j = i + 1; int j = i + 1;
while( j < np && CPoint(i) == CPoint( j ) ) while( j < np && CPoint(i) == CPoint( j ) )
j++; j++;
pts_unique.push_back( CPoint( i ) ); pts_unique.push_back( CPoint( i ) );
i = j; i = j;
} }
m_points.clear(); m_points.clear();
np = pts_unique.size(); np = pts_unique.size();
i = 0; i = 0;
// stage 1: eliminate collinear segments // stage 1: eliminate collinear segments
while( i < np - 2 ) while( i < np - 2 )
{ {
const VECTOR2I p0 = pts_unique[i]; const VECTOR2I p0 = pts_unique[i];
const VECTOR2I p1 = pts_unique[i+1]; const VECTOR2I p1 = pts_unique[i+1];
int n = i; int n = i;
while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 ) while( n < np - 2 && SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1 )
n++; n++;
m_points.push_back( p0 ); m_points.push_back( p0 );
if( n > i ) if( n > i )
i = n; i = n;
if( n == np ) if( n == np )
{ {
m_points.push_back( pts_unique[n - 1] ); m_points.push_back( pts_unique[n - 1] );
return *this; return *this;
} }
i++; i++;
} }
if( np > 1 ) if( np > 1 )
m_points.push_back( pts_unique[np - 2] ); m_points.push_back( pts_unique[np - 2] );
m_points.push_back( pts_unique[np - 1] ); m_points.push_back( pts_unique[np - 1] );
return *this; return *this;
} }
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
{ {
int min_d = INT_MAX; int min_d = INT_MAX;
int nearest = 0; int nearest = 0;
for ( int i = 0; i < SegmentCount(); i++ ) for ( int i = 0; i < SegmentCount(); i++ )
{ {
int d = CSegment( i ).Distance( aP ); int d = CSegment( i ).Distance( aP );
if( d < min_d ) if( d < min_d )
{ {
min_d = d; min_d = d;
nearest = i; nearest = i;
} }
} }
return CSegment( nearest ).NearestPoint( aP ); return CSegment( nearest ).NearestPoint( aP );
} }
const string SHAPE_LINE_CHAIN::Format() const 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++ ) return ss.str();
ss << m_points[i].x << " " << m_points[i].y << " ";// Format() << " ";
return ss.str();
} }
/* /*
Boost::Context assembly wrapper - done to avoid compiling the whole boost binary library 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 which may be unpleasant, in particular under Windows (we don't support VC++, while boost::context
does not support mingw */ does not support mingw */
#ifdef __APPLE__ #ifdef __APPLE__
......
...@@ -9,39 +9,39 @@ ...@@ -9,39 +9,39 @@
.align 2 .align 2
_make_fcontext: _make_fcontext:
mov 0x4(%esp),%eax mov 0x4(%esp),%eax
lea -0x34(%eax),%eax lea -0x34(%eax),%eax
and $0xfffffff0,%eax and $0xfffffff0,%eax
mov 0x4(%esp),%ecx mov 0x4(%esp),%ecx
mov %ecx,0x18(%eax) mov %ecx,0x18(%eax)
mov 0x8(%esp),%edx mov 0x8(%esp),%edx
mov %edx,0x1c(%eax) mov %edx,0x1c(%eax)
neg %edx neg %edx
lea (%edx,%ecx,1),%ecx lea (%edx,%ecx,1),%ecx
mov %ecx,0x20(%eax) mov %ecx,0x20(%eax)
mov 0xc(%esp),%ecx mov 0xc(%esp),%ecx
mov %ecx,0x14(%eax) mov %ecx,0x14(%eax)
stmxcsr 0x2c(%eax) stmxcsr 0x2c(%eax)
fnstcw 0x30(%eax) fnstcw 0x30(%eax)
lea -0x1c(%eax),%edx lea -0x1c(%eax),%edx
mov %edx,0x10(%eax) mov %edx,0x10(%eax)
mov $0x0,%ecx mov $0x0,%ecx
mov %ecx,(%edx) mov %ecx,(%edx)
mov %fs:0x18,%ecx mov %fs:0x18,%ecx
mov (%ecx),%edx mov (%ecx),%edx
inc %edx inc %edx
je _make_fcontext+0x4c // <_make_fcontext+0x4c> je _make_fcontext+0x4c // <_make_fcontext+0x4c>
dec %edx dec %edx
xchg %edx,%ecx xchg %edx,%ecx
jmp _make_fcontext+0x42 // <_make_fcontext+0x42> jmp _make_fcontext+0x42 // <_make_fcontext+0x42>
mov 0x4(%ecx),%ecx mov 0x4(%ecx),%ecx
mov 0x10(%eax),%edx mov 0x10(%eax),%edx
mov %ecx,0x18(%edx) mov %ecx,0x18(%edx)
mov $0xffffffff,%ecx mov $0xffffffff,%ecx
mov %ecx,0x14(%edx) mov %ecx,0x14(%edx)
lea 0x14(%edx),%ecx lea 0x14(%edx),%ecx
mov %ecx,0x24(%eax) mov %ecx,0x24(%eax)
ret ret
finish: finish:
xor %eax,%eax xor %eax,%eax
......
...@@ -31,14 +31,14 @@ ...@@ -31,14 +31,14 @@
CONTEXT_MENU::CONTEXT_MENU() : CONTEXT_MENU::CONTEXT_MENU() :
m_titleSet( false ), m_handler( this ), m_tool( NULL ) m_titleSet( false ), m_handler( this ), m_tool( NULL )
{ {
m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ), m_menu.Connect( wxEVT_MENU_HIGHLIGHT, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler ); NULL, &m_handler );
m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ), m_menu.Connect( wxEVT_COMMAND_MENU_SELECTED, wxEventHandler( CMEventHandler::onEvent ),
NULL, &m_handler ); NULL, &m_handler );
// Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu) // Workaround for the case when mouse cursor never reaches menu (it hangs up tools using menu)
wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu ); wxMenuEvent menuEvent( wxEVT_MENU_HIGHLIGHT, -1, &m_menu );
m_menu.AddPendingEvent( menuEvent ); m_menu.AddPendingEvent( menuEvent );
} }
...@@ -72,16 +72,16 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle ) ...@@ -72,16 +72,16 @@ void CONTEXT_MENU::SetTitle( const wxString& aTitle )
// TODO handle an empty string (remove title and separator) // TODO handle an empty string (remove title and separator)
// Unfortunately wxMenu::SetTitle() does nothing.. // Unfortunately wxMenu::SetTitle() does nothing..
if( m_titleSet ) if( m_titleSet )
{ {
m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle ); m_menu.FindItemByPosition( 0 )->SetItemLabel( aTitle );
} }
else else
{ {
m_menu.InsertSeparator( 0 ); m_menu.InsertSeparator( 0 );
m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) ); m_menu.Insert( 0, new wxMenuItem( &m_menu, -1, aTitle, wxEmptyString, wxITEM_NORMAL ) );
m_titleSet = true; m_titleSet = true;
} }
} }
...@@ -92,7 +92,7 @@ void CONTEXT_MENU::Add( const wxString& aLabel, int aId ) ...@@ -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" wxLogWarning( wxT( "Adding more than one menu entry with the same ID may result in"
"undefined behaviour" ) ); "undefined behaviour" ) );
#endif #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 ) ...@@ -104,7 +104,7 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
if( aAction.HasHotKey() ) if( aAction.HasHotKey() )
menuEntry = wxString( ( aAction.GetMenuItem() + '\t' + getHotKeyDescription( aAction ) ).c_str(), menuEntry = wxString( ( aAction.GetMenuItem() + '\t' + getHotKeyDescription( aAction ) ).c_str(),
wxConvUTF8 ); wxConvUTF8 );
else else
menuEntry = wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 ); menuEntry = wxString( aAction.GetMenuItem().c_str(), wxConvUTF8 );
...@@ -117,13 +117,13 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction ) ...@@ -117,13 +117,13 @@ void CONTEXT_MENU::Add( const TOOL_ACTION& aAction )
void CONTEXT_MENU::Clear() void CONTEXT_MENU::Clear()
{ {
m_titleSet = false; m_titleSet = false;
// Remove all the entries from context menu // Remove all the entries from context menu
for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i ) for( unsigned i = 0; i < m_menu.GetMenuItemCount(); ++i )
m_menu.Destroy( m_menu.FindItemByPosition( 0 ) ); m_menu.Destroy( m_menu.FindItemByPosition( 0 ) );
m_toolActions.clear(); m_toolActions.clear();
} }
......
...@@ -27,23 +27,23 @@ ...@@ -27,23 +27,23 @@
KiGfx::VIEW* TOOL_BASE::getView() const KiGfx::VIEW* TOOL_BASE::getView() const
{ {
return m_toolMgr->GetView(); return m_toolMgr->GetView();
} }
KiGfx::VIEW_CONTROLS* TOOL_BASE::getViewControls() const KiGfx::VIEW_CONTROLS* TOOL_BASE::getViewControls() const
{ {
return m_toolMgr->GetViewControls(); return m_toolMgr->GetViewControls();
} }
wxWindow* TOOL_BASE::getEditFrameInt() const wxWindow* TOOL_BASE::getEditFrameInt() const
{ {
return m_toolMgr->GetEditFrame(); return m_toolMgr->GetEditFrame();
} }
EDA_ITEM* TOOL_BASE::getModelInt() const EDA_ITEM* TOOL_BASE::getModelInt() const
{ {
return m_toolMgr->GetModel(); return m_toolMgr->GetModel();
} }
...@@ -42,52 +42,52 @@ using boost::optional; ...@@ -42,52 +42,52 @@ using boost::optional;
///> Stores information about a mouse button state ///> Stores information about a mouse button state
struct TOOL_DISPATCHER::ButtonState struct TOOL_DISPATCHER::ButtonState
{ {
ButtonState( TOOL_MouseButtons aButton, const wxEventType& aDownEvent, ButtonState( TOOL_MouseButtons aButton, const wxEventType& aDownEvent,
const wxEventType& aUpEvent ) : const wxEventType& aUpEvent ) :
button( aButton ), button( aButton ),
downEvent( aDownEvent ), downEvent( aDownEvent ),
upEvent( aUpEvent ) upEvent( aUpEvent )
{}; {};
///> Flag indicating that dragging is active for the given button. ///> Flag indicating that dragging is active for the given button.
bool dragging; bool dragging;
///> Flag indicating that the given button is pressed. ///> Flag indicating that the given button is pressed.
bool pressed; bool pressed;
///> Point where dragging has started (in world coordinates). ///> Point where dragging has started (in world coordinates).
VECTOR2D dragOrigin; VECTOR2D dragOrigin;
///> Point where click event has occurred. ///> Point where click event has occurred.
VECTOR2D downPosition; VECTOR2D downPosition;
///> Difference between drag origin point and current mouse position (expressed as distance in ///> Difference between drag origin point and current mouse position (expressed as distance in
///> pixels). ///> pixels).
double dragMaxDelta; double dragMaxDelta;
///> Determines the mouse button for which information are stored. ///> Determines the mouse button for which information are stored.
TOOL_MouseButtons button; TOOL_MouseButtons button;
///> The type of wxEvent that determines mouse button press. ///> The type of wxEvent that determines mouse button press.
wxEventType downEvent; wxEventType downEvent;
///> The type of wxEvent that determines mouse button release. ///> The type of wxEvent that determines mouse button release.
wxEventType upEvent; wxEventType upEvent;
///> Time stamp for the last mouse button press event. ///> Time stamp for the last mouse button press event.
wxLongLong downTimestamp; wxLongLong downTimestamp;
///> Restores initial state. ///> Restores initial state.
void Reset() void Reset()
{ {
dragging = false; dragging = false;
pressed = false; pressed = false;
} }
}; };
TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditFrame ) : 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_Left, wxEVT_LEFT_DOWN, wxEVT_LEFT_UP ) );
m_buttons.push_back( new ButtonState( MB_Right, wxEVT_RIGHT_DOWN, wxEVT_RIGHT_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 ...@@ -99,135 +99,135 @@ TOOL_DISPATCHER::TOOL_DISPATCHER( TOOL_MANAGER* aToolMgr, PCB_BASE_FRAME* aEditF
TOOL_DISPATCHER::~TOOL_DISPATCHER() TOOL_DISPATCHER::~TOOL_DISPATCHER()
{ {
BOOST_FOREACH( ButtonState* st, m_buttons ) BOOST_FOREACH( ButtonState* st, m_buttons )
delete st; delete st;
} }
void TOOL_DISPATCHER::ResetState() void TOOL_DISPATCHER::ResetState()
{ {
BOOST_FOREACH( ButtonState* st, m_buttons ) BOOST_FOREACH( ButtonState* st, m_buttons )
st->Reset(); st->Reset();
} }
KiGfx::VIEW* TOOL_DISPATCHER::getView() 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 ) bool TOOL_DISPATCHER::handleMouseButton( wxEvent& aEvent, int aIndex, bool aMotion )
{ {
ButtonState* st = m_buttons[aIndex]; ButtonState* st = m_buttons[aIndex];
wxEventType type = aEvent.GetEventType(); wxEventType type = aEvent.GetEventType();
optional<TOOL_EVENT> evt; optional<TOOL_EVENT> evt;
bool isClick = false; bool isClick = false;
bool up = type == st->upEvent; bool up = type == st->upEvent;
bool down = type == st->downEvent; bool down = type == st->downEvent;
int mods = decodeModifiers<wxMouseEvent>( static_cast<wxMouseEvent*>( &aEvent ) ); int mods = decodeModifiers<wxMouseEvent>( static_cast<wxMouseEvent*>( &aEvent ) );
int args = st->button | mods; int args = st->button | mods;
if( down ) // Handle mouse button press if( down ) // Handle mouse button press
{ {
st->downTimestamp = wxGetLocalTimeMillis(); st->downTimestamp = wxGetLocalTimeMillis();
st->dragOrigin = m_lastMousePos; st->dragOrigin = m_lastMousePos;
st->downPosition = m_lastMousePos; st->downPosition = m_lastMousePos;
st->dragMaxDelta = 0; st->dragMaxDelta = 0;
st->pressed = true; st->pressed = true;
evt = TOOL_EVENT( TC_Mouse, TA_MouseDown, args ); evt = TOOL_EVENT( TC_Mouse, TA_MouseDown, args );
} }
else if( up ) // Handle mouse button release else if( up ) // Handle mouse button release
{ {
st->pressed = false; st->pressed = false;
if( st->dragging ) if( st->dragging )
{ {
wxLongLong t = wxGetLocalTimeMillis(); wxLongLong t = wxGetLocalTimeMillis();
// Determine if it was just a single click or beginning of dragging // Determine if it was just a single click or beginning of dragging
if( t - st->downTimestamp < DragTimeThreshold && if( t - st->downTimestamp < DragTimeThreshold &&
st->dragMaxDelta < DragDistanceThreshold ) st->dragMaxDelta < DragDistanceThreshold )
isClick = true; isClick = true;
else else
evt = TOOL_EVENT( TC_Mouse, TA_MouseUp, args ); evt = TOOL_EVENT( TC_Mouse, TA_MouseUp, args );
} }
else else
isClick = true; isClick = true;
if( isClick ) if( isClick )
evt = TOOL_EVENT( TC_Mouse, TA_MouseClick, args ); evt = TOOL_EVENT( TC_Mouse, TA_MouseClick, args );
st->dragging = false; st->dragging = false;
} }
if( st->pressed && aMotion ) if( st->pressed && aMotion )
{ {
st->dragging = true; st->dragging = true;
double dragPixelDistance = getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm(); double dragPixelDistance = getView()->ToScreen( m_lastMousePos - st->dragOrigin, false ).EuclideanNorm();
st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance ); st->dragMaxDelta = std::max( st->dragMaxDelta, dragPixelDistance );
wxLongLong t = wxGetLocalTimeMillis(); wxLongLong t = wxGetLocalTimeMillis();
if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold ) if( t - st->downTimestamp > DragTimeThreshold || st->dragMaxDelta > DragDistanceThreshold )
{ {
evt = TOOL_EVENT( TC_Mouse, TA_MouseDrag, args ); evt = TOOL_EVENT( TC_Mouse, TA_MouseDrag, args );
evt->SetMouseDragOrigin( st->dragOrigin ); evt->SetMouseDragOrigin( st->dragOrigin );
evt->SetMouseDelta( m_lastMousePos - st->dragOrigin ); evt->SetMouseDelta( m_lastMousePos - st->dragOrigin );
} }
} }
if( evt ) if( evt )
{ {
evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos ); evt->SetMousePosition( isClick ? st->downPosition : m_lastMousePos );
m_toolMgr->ProcessEvent( *evt ); m_toolMgr->ProcessEvent( *evt );
return true; return true;
} }
return false; return false;
} }
void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
{ {
bool motion = false, buttonEvents = false; bool motion = false, buttonEvents = false;
optional<TOOL_EVENT> evt; optional<TOOL_EVENT> evt;
int type = aEvent.GetEventType(); int type = aEvent.GetEventType();
// Mouse handling // Mouse handling
if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL || if( type == wxEVT_MOTION || type == wxEVT_MOUSEWHEEL ||
type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP || type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP || type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP || type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
// Event issued whem mouse retains position in screen coordinates, // Event issued whem mouse retains position in screen coordinates,
// but changes in world coordinates (eg. autopanning) // but changes in world coordinates (eg. autopanning)
type == KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE ) type == KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
{ {
VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetCursorPosition(); VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetCursorPosition();
VECTOR2D pos = getView()->ToWorld( screenPos ); VECTOR2D pos = getView()->ToWorld( screenPos );
if( pos != m_lastMousePos || type == KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE ) if( pos != m_lastMousePos || type == KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
{ {
motion = true; motion = true;
m_lastMousePos = pos; m_lastMousePos = pos;
} }
for( unsigned int i = 0; i < m_buttons.size(); i++ ) for( unsigned int i = 0; i < m_buttons.size(); i++ )
buttonEvents |= handleMouseButton( aEvent, i, motion ); buttonEvents |= handleMouseButton( aEvent, i, motion );
if( !buttonEvents && motion ) if( !buttonEvents && motion )
{ {
evt = TOOL_EVENT( TC_Mouse, TA_MouseMotion ); evt = TOOL_EVENT( TC_Mouse, TA_MouseMotion );
evt->SetMousePosition( pos ); evt->SetMousePosition( pos );
} }
} }
// Keyboard handling // Keyboard handling
else if( type == wxEVT_KEY_UP || type == wxEVT_KEY_DOWN ) else if( type == wxEVT_KEY_UP || type == wxEVT_KEY_DOWN )
{ {
wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent ); wxKeyEvent* ke = static_cast<wxKeyEvent*>( &aEvent );
int key = ke->GetKeyCode(); int key = ke->GetKeyCode();
...@@ -246,33 +246,33 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent ) ...@@ -246,33 +246,33 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
} }
} }
if( evt ) if( evt )
m_toolMgr->ProcessEvent( *evt ); m_toolMgr->ProcessEvent( *evt );
// pass the event to the GUI, it might still be interested in it // pass the event to the GUI, it might still be interested in it
aEvent.Skip(); aEvent.Skip();
} }
void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent ) void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent )
{ {
bool activateTool = false; bool activateTool = false;
std::string toolName; std::string toolName;
// fixme: use TOOL_ACTIONs here // fixme: use TOOL_ACTIONs here
switch( aEvent.GetId() ) switch( aEvent.GetId() )
{ {
case ID_PNS_ROUTER_TOOL: case ID_PNS_ROUTER_TOOL:
toolName = "pcbnew.InteractiveRouter"; toolName = "pcbnew.InteractiveRouter";
activateTool = true; activateTool = true;
break; break;
case ID_SELECTION_TOOL: case ID_SELECTION_TOOL:
toolName = "pcbnew.InteractiveSelection"; toolName = "pcbnew.InteractiveSelection";
activateTool = true; activateTool = true;
break; break;
} }
// do nothing if the legacy view is active // do nothing if the legacy view is active
if( activateTool && m_editFrame->IsGalCanvasActive() ) if( activateTool && m_editFrame->IsGalCanvasActive() )
m_toolMgr->InvokeTool( toolName ); m_toolMgr->InvokeTool( toolName );
} }
...@@ -35,22 +35,22 @@ using namespace std; ...@@ -35,22 +35,22 @@ using namespace std;
struct FlagString struct FlagString
{ {
int flag; int flag;
std::string str; std::string str;
}; };
static const std::string flag2string( int flag, const FlagString* exps ) 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++ ) for( int i = 0; exps[i].str.length(); i++ )
{ {
if( exps[i].flag & flag ) if( exps[i].flag & flag )
rv += exps[i].str + " "; rv += exps[i].str + " ";
} }
return rv; return rv;
} }
...@@ -62,97 +62,97 @@ bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const ...@@ -62,97 +62,97 @@ bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const
const std::string TOOL_EVENT::Format() const const std::string TOOL_EVENT::Format() const
{ {
std::string ev; std::string ev;
const FlagString categories[] = { const FlagString categories[] = {
{ TC_Mouse, "mouse" }, { TC_Mouse, "mouse" },
{ TC_Keyboard, "keyboard" }, { TC_Keyboard, "keyboard" },
{ TC_Command, "command" }, { TC_Command, "command" },
{ TC_Message, "message" }, { TC_Message, "message" },
{ TC_View, "view" }, { TC_View, "view" },
{ 0, "" } { 0, "" }
}; };
const FlagString actions[] = { const FlagString actions[] = {
{ TA_MouseClick, "click" }, { TA_MouseClick, "click" },
{ TA_MouseUp, "button-up" }, { TA_MouseUp, "button-up" },
{ TA_MouseDown, "button-down" }, { TA_MouseDown, "button-down" },
{ TA_MouseDrag, "drag" }, { TA_MouseDrag, "drag" },
{ TA_MouseMotion, "motion" }, { TA_MouseMotion, "motion" },
{ TA_MouseWheel, "wheel" }, { TA_MouseWheel, "wheel" },
{ TA_KeyUp, "key-up" }, { TA_KeyUp, "key-up" },
{ TA_KeyDown, "key-down" }, { TA_KeyDown, "key-down" },
{ TA_ViewRefresh, "view-refresh" }, { TA_ViewRefresh, "view-refresh" },
{ TA_ViewZoom, "view-zoom" }, { TA_ViewZoom, "view-zoom" },
{ TA_ViewPan, "view-pan" }, { TA_ViewPan, "view-pan" },
{ TA_ViewDirty, "view-dirty" }, { TA_ViewDirty, "view-dirty" },
{ TA_ChangeLayer, "change-layer" }, { TA_ChangeLayer, "change-layer" },
{ TA_CancelTool, "cancel-tool" }, { TA_CancelTool, "cancel-tool" },
{ TA_ContextMenuUpdate, "context-menu-update" }, { TA_ContextMenuUpdate, "context-menu-update" },
{ TA_ContextMenuChoice, "context-menu-choice" }, { TA_ContextMenuChoice, "context-menu-choice" },
{ TA_Action, "action" }, { TA_Action, "action" },
{ 0, "" } { 0, "" }
}; };
const FlagString buttons[] = { const FlagString buttons[] = {
{ MB_None, "none" }, { MB_None, "none" },
{ MB_Left, "left" }, { MB_Left, "left" },
{ MB_Right, "right" }, { MB_Right, "right" },
{ MB_Middle, "middle" }, { MB_Middle, "middle" },
{ 0, "" } { 0, "" }
}; };
const FlagString modifiers[] = { const FlagString modifiers[] = {
{ MD_ModShift, "shift" }, { MD_ModShift, "shift" },
{ MD_ModCtrl, "ctrl" }, { MD_ModCtrl, "ctrl" },
{ MD_ModAlt, "alt" }, { MD_ModAlt, "alt" },
{ 0, "" } { 0, "" }
}; };
ev = "category: "; ev = "category: ";
ev += flag2string( m_category, categories ); ev += flag2string( m_category, categories );
ev += " action: "; ev += " action: ";
ev += flag2string( m_actions, actions ); ev += flag2string( m_actions, actions );
if( m_actions & TA_Mouse ) if( m_actions & TA_Mouse )
{ {
ev += " btns: "; ev += " btns: ";
ev += flag2string( m_mouseButtons, buttons ); ev += flag2string( m_mouseButtons, buttons );
} }
if( m_actions & TA_Keyboard ) if( m_actions & TA_Keyboard )
{ {
char tmp[128]; char tmp[128];
sprintf( tmp, "key: %d", m_keyCode ); sprintf( tmp, "key: %d", m_keyCode );
ev += tmp; ev += tmp;
} }
if( m_actions & ( TA_Mouse | TA_Keyboard ) ) if( m_actions & ( TA_Mouse | TA_Keyboard ) )
{ {
ev += " mods: "; ev += " mods: ";
ev += flag2string( m_modifiers, modifiers ); ev += flag2string( m_modifiers, modifiers );
} }
if( m_commandId ) if( m_commandId )
{ {
char tmp[128]; char tmp[128];
sprintf( tmp, "cmd-id: %d", *m_commandId ); sprintf( tmp, "cmd-id: %d", *m_commandId );
ev += tmp; ev += tmp;
} }
if( m_commandStr ) if( m_commandStr )
ev += "cmd-str: " + ( *m_commandStr ); ev += "cmd-str: " + ( *m_commandStr );
return ev; return ev;
} }
const std::string TOOL_EVENT_LIST::Format() const 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 ) return s;
s += e.Format() + " ";
return s;
} }
...@@ -30,13 +30,13 @@ ...@@ -30,13 +30,13 @@
#include <tool/context_menu.h> #include <tool/context_menu.h>
TOOL_INTERACTIVE::TOOL_INTERACTIVE( TOOL_ID aId, const std::string& aName ) : 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_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() TOOL_INTERACTIVE::~TOOL_INTERACTIVE()
...@@ -46,18 +46,18 @@ TOOL_INTERACTIVE::~TOOL_INTERACTIVE() ...@@ -46,18 +46,18 @@ TOOL_INTERACTIVE::~TOOL_INTERACTIVE()
OPT_TOOL_EVENT TOOL_INTERACTIVE::Wait( const TOOL_EVENT_LIST& aEventList ) 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 ) 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 ) void TOOL_INTERACTIVE::SetContextMenu( CONTEXT_MENU* aMenu, CONTEXT_MENU_TRIGGER aTrigger )
{ {
aMenu->setTool( this ); aMenu->setTool( this );
m_toolMgr->ScheduleContextMenu( this, aMenu, aTrigger ); m_toolMgr->ScheduleContextMenu( this, aMenu, aTrigger );
} }
...@@ -52,50 +52,50 @@ using namespace std; ...@@ -52,50 +52,50 @@ using namespace std;
struct TOOL_MANAGER::TOOL_STATE struct TOOL_MANAGER::TOOL_STATE
{ {
/// The tool itself /// The tool itself
TOOL_BASE* theTool; TOOL_BASE* theTool;
/// Is the tool active (pending execution) or disabled at the moment
bool idle;
/// Flag defining if the tool is waiting for any event (i.e. if it /// Is the tool active (pending execution) or disabled at the moment
/// issued a Wait() call). bool idle;
bool pendingWait;
/// Is there a context menu being displayed /// Flag defining if the tool is waiting for any event (i.e. if it
bool pendingContextMenu; /// issued a Wait() call).
bool pendingWait;
/// Context menu currently used by the tool /// Is there a context menu being displayed
CONTEXT_MENU* contextMenu; bool pendingContextMenu;
/// Defines when the context menu is opened /// Context menu currently used by the tool
CONTEXT_MENU_TRIGGER contextMenuTrigger; CONTEXT_MENU* contextMenu;
/// Tool execution context /// Defines when the context menu is opened
COROUTINE<int, TOOL_EVENT&>* cofunc; CONTEXT_MENU_TRIGGER contextMenuTrigger;
/// The event that triggered the execution/wakeup of the tool after Wait() call
TOOL_EVENT wakeupEvent;
/// List of events the tool is currently waiting for /// Tool execution context
TOOL_EVENT_LIST waitEvents; COROUTINE<int, TOOL_EVENT&>* cofunc;
/// List of possible transitions (ie. association of events and state handlers that are executed /// The event that triggered the execution/wakeup of the tool after Wait() call
/// upon the event reception TOOL_EVENT wakeupEvent;
std::vector<TRANSITION> transitions;
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_model( NULL ), m_view( NULL )
{ {
m_actionMgr = new ACTION_MANAGER( this ); m_actionMgr = new ACTION_MANAGER( this );
...@@ -119,37 +119,37 @@ TOOL_MANAGER::~TOOL_MANAGER() ...@@ -119,37 +119,37 @@ TOOL_MANAGER::~TOOL_MANAGER()
void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool ) void TOOL_MANAGER::RegisterTool( TOOL_BASE* aTool )
{ {
TOOL_STATE* st = new TOOL_STATE; TOOL_STATE* st = new TOOL_STATE;
st->theTool = aTool; st->theTool = aTool;
st->idle = true; st->idle = true;
st->pendingWait = false; st->pendingWait = false;
st->pendingContextMenu = false; st->pendingContextMenu = false;
st->cofunc = NULL; st->cofunc = NULL;
st->contextMenuTrigger = CMENU_OFF; st->contextMenuTrigger = CMENU_OFF;
m_toolState[aTool] = st; m_toolState[aTool] = st;
m_toolNameIndex[aTool->GetName()] = st; m_toolNameIndex[aTool->GetName()] = st;
m_toolIdIndex[aTool->GetId()] = st; m_toolIdIndex[aTool->GetId()] = st;
aTool->m_toolMgr = this; aTool->m_toolMgr = this;
if( aTool->GetType() == TOOL_Interactive ) if( aTool->GetType() == TOOL_Interactive )
{ {
bool initState = static_cast<TOOL_INTERACTIVE*>( aTool )->Init(); bool initState = static_cast<TOOL_INTERACTIVE*>( aTool )->Init();
if( !initState ) if( !initState )
{ {
wxLogError( wxT( "Initialization of the %s tool failed" ), aTool->GetName().c_str() ); wxLogError( wxT( "Initialization of the %s tool failed" ), aTool->GetName().c_str() );
// Unregister the tool // Unregister the tool
m_toolState.erase( aTool ); m_toolState.erase( aTool );
m_toolNameIndex.erase( aTool->GetName() ); m_toolNameIndex.erase( aTool->GetName() );
m_toolIdIndex.erase( aTool->GetId() ); m_toolIdIndex.erase( aTool->GetId() );
delete st; delete st;
delete aTool; delete aTool;
} }
} }
} }
...@@ -268,89 +268,89 @@ TOOL_BASE* TOOL_MANAGER::FindTool( const std::string& aName ) const ...@@ -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, void TOOL_MANAGER::ScheduleNextState( TOOL_BASE* aTool, TOOL_STATE_FUNC& aHandler,
const TOOL_EVENT_LIST& aConditions ) const TOOL_EVENT_LIST& aConditions )
{ {
TOOL_STATE* st = m_toolState[aTool]; TOOL_STATE* st = m_toolState[aTool];
st->transitions.push_back( TRANSITION( aConditions, aHandler ) ); st->transitions.push_back( TRANSITION( aConditions, aHandler ) );
} }
optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool, optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* aTool,
const TOOL_EVENT_LIST& aConditions ) const TOOL_EVENT_LIST& aConditions )
{ {
TOOL_STATE* st = m_toolState[aTool]; 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;
// switch context back to event dispatcher loop // indicate to the manager that we are going to sleep and we shall be
st->cofunc->Yield(); // 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 ) void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
{ {
// iterate over all registered tools // iterate over all registered tools
BOOST_FOREACH( TOOL_ID toolId, m_activeTools ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
TOOL_STATE* st = m_toolIdIndex[toolId]; TOOL_STATE* st = m_toolIdIndex[toolId];
// the tool state handler is waiting for events (i.e. called Wait() method) // the tool state handler is waiting for events (i.e. called Wait() method)
if( st->pendingWait ) if( st->pendingWait )
{ {
if( st->waitEvents.Matches( aEvent ) ) if( st->waitEvents.Matches( aEvent ) )
{ {
// By default, already processed events are not passed further // By default, already processed events are not passed further
m_passEvent = false; m_passEvent = false;
// got matching event? clear wait list and wake up the coroutine // got matching event? clear wait list and wake up the coroutine
st->wakeupEvent = aEvent; st->wakeupEvent = aEvent;
st->pendingWait = false; st->pendingWait = false;
st->waitEvents.clear(); st->waitEvents.clear();
if( st->cofunc && !st->cofunc->Resume() ) if( st->cofunc && !st->cofunc->Resume() )
finishTool( st ); // The couroutine has finished finishTool( st ); // The couroutine has finished
// If the tool did not request to propagate // If the tool did not request to propagate
// the event to other tools, we should stop it now // the event to other tools, we should stop it now
if( !m_passEvent ) if( !m_passEvent )
break; break;
} }
} }
} }
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values ) BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
{ {
// the tool scheduled next state(s) by calling Go() // the tool scheduled next state(s) by calling Go()
if( !st->pendingWait ) if( !st->pendingWait )
{ {
// no state handler in progress - check if there are any transitions (defined by // no state handler in progress - check if there are any transitions (defined by
// Go() method that match the event. // Go() method that match the event.
if( st->transitions.size() ) if( st->transitions.size() )
{ {
BOOST_FOREACH( TRANSITION tr, st->transitions ) BOOST_FOREACH( TRANSITION tr, st->transitions )
{ {
if( tr.first.Matches( aEvent ) ) if( tr.first.Matches( aEvent ) )
{ {
st->transitions.clear(); st->transitions.clear();
// no tool context allocated yet? Create one. // no tool context allocated yet? Create one.
if( !st->cofunc ) if( !st->cofunc )
st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second ); st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second );
else else
st->cofunc->SetEntry( tr.second ); st->cofunc->SetEntry( tr.second );
// got match? Run the handler. // got match? Run the handler.
st->cofunc->Call( aEvent ); st->cofunc->Call( aEvent );
if( !st->cofunc->Running() ) if( !st->cofunc->Running() )
finishTool( st ); // The couroutine has finished immediately? finishTool( st ); // The couroutine has finished immediately?
} }
} }
} }
} }
} }
} }
...@@ -411,90 +411,90 @@ void TOOL_MANAGER::finishTool( TOOL_STATE* aState ) ...@@ -411,90 +411,90 @@ void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent ) 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 // Early dispatch of events destined for the TOOL_MANAGER
if( !dispatchStandardEvents( aEvent ) ) if( !dispatchStandardEvents( aEvent ) )
return false; return false;
dispatchInternal( aEvent ); dispatchInternal( aEvent );
// popup menu handling // popup menu handling
BOOST_FOREACH( TOOL_ID toolId, m_activeTools ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
TOOL_STATE* st = m_toolIdIndex[toolId]; TOOL_STATE* st = m_toolIdIndex[toolId];
// the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode) // 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. // or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
if( st->contextMenuTrigger != CMENU_OFF ) if( st->contextMenuTrigger != CMENU_OFF )
{ {
if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) ) if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) )
break; break;
st->pendingWait = true; st->pendingWait = true;
st->waitEvents = TOOL_EVENT( TC_Any, TA_Any ); st->waitEvents = TOOL_EVENT( TC_Any, TA_Any );
if( st->contextMenuTrigger == CMENU_NOW ) if( st->contextMenuTrigger == CMENU_NOW )
st->contextMenuTrigger = CMENU_OFF; st->contextMenuTrigger = CMENU_OFF;
boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) ); boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
GetEditFrame()->PopupMenu( menu->GetMenu() ); GetEditFrame()->PopupMenu( menu->GetMenu() );
// //
TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice ); TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice );
dispatchInternal( evt ); dispatchInternal( evt );
break; break;
} }
} }
if( m_view->IsDirty() ) if( m_view->IsDirty() )
{ {
PCB_EDIT_FRAME* f = static_cast<PCB_EDIT_FRAME*>( GetEditFrame() ); PCB_EDIT_FRAME* f = static_cast<PCB_EDIT_FRAME*>( GetEditFrame() );
f->GetGalCanvas()->Refresh(); // fixme: ugly hack, provide a method in TOOL_DISPATCHER. 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, void TOOL_MANAGER::ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
CONTEXT_MENU_TRIGGER aTrigger ) CONTEXT_MENU_TRIGGER aTrigger )
{ {
TOOL_STATE* st = m_toolState[aTool]; TOOL_STATE* st = m_toolState[aTool];
st->contextMenu = aMenu; st->contextMenu = aMenu;
st->contextMenuTrigger = aTrigger; st->contextMenuTrigger = aTrigger;
// the tool wants the menu immediately? Preempt it and do so :) // the tool wants the menu immediately? Preempt it and do so :)
if( aTrigger == CMENU_NOW ) if( aTrigger == CMENU_NOW )
st->cofunc->Yield(); st->cofunc->Yield();
} }
TOOL_ID TOOL_MANAGER::MakeToolId( const std::string& aToolName ) TOOL_ID TOOL_MANAGER::MakeToolId( const std::string& aToolName )
{ {
static int currentId; static int currentId;
return currentId++; return currentId++;
} }
void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView, void TOOL_MANAGER::SetEnvironment( EDA_ITEM* aModel, KiGfx::VIEW* aView,
KiGfx::VIEW_CONTROLS* aViewControls, wxWindow* aFrame ) KiGfx::VIEW_CONTROLS* aViewControls, wxWindow* aFrame )
{ {
m_model = aModel; m_model = aModel;
m_view = aView; m_view = aView;
m_viewControls = aViewControls; m_viewControls = aViewControls;
m_editFrame = aFrame; m_editFrame = aFrame;
// Reset state of the registered tools // Reset state of the registered tools
BOOST_FOREACH( TOOL_ID toolId, m_activeTools ) BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{ {
TOOL_BASE* tool = m_toolIdIndex[toolId]->theTool; TOOL_BASE* tool = m_toolIdIndex[toolId]->theTool;
if( tool->GetType() == TOOL_Interactive ) if( tool->GetType() == TOOL_Interactive )
static_cast<TOOL_INTERACTIVE*>( tool )->Reset(); static_cast<TOOL_INTERACTIVE*>( tool )->Reset();
} }
} }
......
...@@ -87,7 +87,7 @@ public: ...@@ -87,7 +87,7 @@ public:
{ {
return m_view; return m_view;
} }
/** /**
* Function GetViewControls() * Function GetViewControls()
* Returns a pointer to the VIEW_CONTROLS instance used in the panel. * Returns a pointer to the VIEW_CONTROLS instance used in the panel.
......
...@@ -131,7 +131,7 @@ public: ...@@ -131,7 +131,7 @@ public:
* Saturates the color to a given factor (in HSV model) * Saturates the color to a given factor (in HSV model)
*/ */
COLOR4D& Saturate( double aFactor ); COLOR4D& Saturate( double aFactor );
/** /**
* Function Brightened * Function Brightened
* Returns a color that is brighter by a given factor, without modifying object. * Returns a color that is brighter by a given factor, without modifying object.
......
...@@ -172,11 +172,11 @@ private: ...@@ -172,11 +172,11 @@ private:
void programInfo( GLuint aProgram ); void programInfo( GLuint aProgram );
/** /**
* @brief Get the shader information. * @brief Get the shader information.
* *
* @param aShader is the shader number. * @param aShader is the shader number.
*/ */
void shaderInfo( GLuint aShader ); void shaderInfo( GLuint aShader );
/** /**
* @brief Read the shader source file * @brief Read the shader source file
......
...@@ -36,278 +36,278 @@ typedef boost::optional<VECTOR2I> OPT_VECTOR2I; ...@@ -36,278 +36,278 @@ typedef boost::optional<VECTOR2I> OPT_VECTOR2I;
class SEG class SEG
{ {
private: private:
typedef VECTOR2I::extended_type ecoord; typedef VECTOR2I::extended_type ecoord;
public: public:
friend inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg ); 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 /* 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 * to an object the segment belongs to (e.g. a line chain) or references to locally stored points
* (m_a, m_b). * (m_a, m_b).
*/ */
VECTOR2I& a, b; VECTOR2I& a, b;
/** Default constructor /** Default constructor
* Creates an empty (0, 0) segment, locally-referenced * Creates an empty (0, 0) segment, locally-referenced
*/ */
SEG() : a( m_a ), b( m_b ) SEG() : a( m_a ), b( m_b )
{ {
a = m_a; a = m_a;
b = m_b; b = m_b;
m_is_local = true; m_is_local = true;
m_index = -1; m_index = -1;
} }
/** /**
* Constructor * Constructor
* Creates a segment between (aX1, aY1) and (aX2, aY2), locally referenced * 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 ) SEG( int aX1, int aY1, int aX2, int aY2 ) : a( m_a ), b( m_b )
{ {
m_a = VECTOR2I( aX1, aY1 ); m_a = VECTOR2I( aX1, aY1 );
m_b = VECTOR2I( aX2, aY2 ); m_b = VECTOR2I( aX2, aY2 );
a = m_a; a = m_a;
b = m_b; b = m_b;
m_is_local = true; m_is_local = true;
m_index = -1; m_index = -1;
} }
/** /**
* Constructor * Constructor
* Creates a segment between (aA) and (aB), locally referenced * 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 ) SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : a( m_a ), b( m_b ), m_a( aA ), m_b( aB )
{ {
a = m_a; a = m_a;
b = m_b; b = m_b;
m_is_local = true; m_is_local = true;
m_index = -1; m_index = -1;
} }
/** /**
* Constructor * Constructor
* Creates a segment between (aA) and (aB), referenced to a multi-segment shape * 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 aA reference to the start point in the parent shape
* @param aB reference to the end 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 * @param aIndex index of the segment within the parent shape
*/ */
SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ) : a( aA ), b( aB ) SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ) : a( aA ), b( aB )
{ {
m_is_local = false; m_is_local = false;
m_index = aIndex; m_index = aIndex;
} }
/** /**
* Copy constructor * Copy constructor
*/ */
SEG ( const SEG& aSeg ) : a( m_a ), b( m_b ) SEG ( const SEG& aSeg ) : a( m_a ), b( m_b )
{ {
if (aSeg.m_is_local) if (aSeg.m_is_local)
{ {
m_a = aSeg.m_a; m_a = aSeg.m_a;
m_b = aSeg.m_b; m_b = aSeg.m_b;
a = m_a; a = m_a;
b = m_b; b = m_b;
m_is_local = true; m_is_local = true;
m_index = -1; m_index = -1;
} else { } else {
a = aSeg.a; a = aSeg.a;
b = aSeg.b; b = aSeg.b;
m_index = aSeg.m_index; m_index = aSeg.m_index;
m_is_local = false; m_is_local = false;
} }
} }
SEG& operator=( const SEG& aSeg ) SEG& operator=( const SEG& aSeg )
{ {
a = aSeg.a; a = aSeg.a;
b = aSeg.b; b = aSeg.b;
m_a = aSeg.m_a; m_a = aSeg.m_a;
m_b = aSeg.m_b; m_b = aSeg.m_b;
m_index = aSeg.m_index; m_index = aSeg.m_index;
m_is_local = aSeg.m_is_local; m_is_local = aSeg.m_is_local;
return *this; return *this;
} }
/** /**
* Function LineProject() * Function LineProject()
* *
* Computes the perpendicular projection point of aP on a line passing through * Computes the perpendicular projection point of aP on a line passing through
* ends of the segment. * ends of the segment.
* @param aP point to project * @param aP point to project
* @return projected point * @return projected point
*/ */
VECTOR2I LineProject( const VECTOR2I& aP ) const; VECTOR2I LineProject( const VECTOR2I& aP ) const;
/** /**
* Function Side() * Function Side()
* *
* Determines on which side of directed line passing via segment ends point aP lies. * Determines on which side of directed line passing via segment ends point aP lies.
* @param aP point to determine the orientation wrs to self * @param aP point to determine the orientation wrs to self
* @return: < 0: left, 0 : on the line, > 0 : right * @return: < 0: left, 0 : on the line, > 0 : right
*/ */
int Side( const VECTOR2I& aP ) const int Side( const VECTOR2I& aP ) const
{ {
const ecoord det = ( b - a ).Cross( aP - a ); const ecoord det = ( b - a ).Cross( aP - a );
return det < 0 ? -1 : ( det > 0 ? 1 : 0 ); return det < 0 ? -1 : ( det > 0 ? 1 : 0 );
} }
/** /**
* Function LineDistance() * Function LineDistance()
* *
* Returns the closest Euclidean distance between point aP and the line defined by * Returns the closest Euclidean distance between point aP and the line defined by
* the ends of segment (this). * the ends of segment (this).
* @param aDetermineSide: when true, the sign of the returned value indicates * @param aDetermineSide: when true, the sign of the returned value indicates
* the side of the line at which we are (negative = left) * the side of the line at which we are (negative = left)
* @return the distance * @return the distance
*/ */
int LineDistance( const VECTOR2I& aP, bool aDetermineSide = false ) const; int LineDistance( const VECTOR2I& aP, bool aDetermineSide = false ) const;
/** /**
* Function NearestPoint() * Function NearestPoint()
* *
* Computes a point on the segment (this) that is closest to point aP. * Computes a point on the segment (this) that is closest to point aP.
* @return: nearest point * @return: nearest point
*/ */
const VECTOR2I NearestPoint( const VECTOR2I &aP ) const; const VECTOR2I NearestPoint( const VECTOR2I &aP ) const;
/** /**
* Function Intersect() * Function Intersect()
* *
* Computes intersection point of segment (this) with segment aSeg. * Computes intersection point of segment (this) with segment aSeg.
* @param aSeg: segment to intersect with * @param aSeg: segment to intersect with
* @param aIgnoreEndpoints: don't treat corner cases (i.e. end of one segment touching the other) * @param aIgnoreEndpoints: don't treat corner cases (i.e. end of one segment touching the other)
* as intersections. * as intersections.
* @param aLines: treat segments as infinite lines * @param aLines: treat segments as infinite lines
* @return intersection point, if exists * @return intersection point, if exists
*/ */
OPT_VECTOR2I Intersect( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false ) const; OPT_VECTOR2I Intersect( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false ) const;
/** /**
* Function IntersectLines() * Function IntersectLines()
* *
* Computes the intersection point of lines passing through ends of (this) and aSeg * Computes the intersection point of lines passing through ends of (this) and aSeg
* @param aSeg segment defining the line to intersect with * @param aSeg segment defining the line to intersect with
* @return intersection point, if exists * @return intersection point, if exists
*/ */
OPT_VECTOR2I IntersectLines( const SEG& aSeg ) const OPT_VECTOR2I IntersectLines( const SEG& aSeg ) const
{ {
return Intersect( aSeg, false, true ); return Intersect( aSeg, false, true );
} }
bool Collide( const SEG& aSeg, int aClearance ) const; bool Collide( const SEG& aSeg, int aClearance ) const;
/** /**
* Function Distance() * Function Distance()
* *
* Computes minimum Euclidean distance to segment aSeg. * Computes minimum Euclidean distance to segment aSeg.
* @param aSeg other segment * @param aSeg other segment
* @return minimum distance * @return minimum distance
*/ */
ecoord SquaredDistance( const SEG& aSeg ) const; ecoord SquaredDistance( const SEG& aSeg ) const;
int Distance( const SEG& aSeg ) const int Distance( const SEG& aSeg ) const
{ {
return sqrt( SquaredDistance( aSeg ) ); return sqrt( SquaredDistance( aSeg ) );
} }
/** /**
* Function Distance() * Function Distance()
* *
* Computes minimum Euclidean distance to point aP. * Computes minimum Euclidean distance to point aP.
* @param aP the point * @param aP the point
* @return minimum distance * @return minimum distance
*/ */
ecoord SquaredDistance( const VECTOR2I& aP ) const ecoord SquaredDistance( const VECTOR2I& aP ) const
{ {
return ( NearestPoint( aP ) - aP ).SquaredEuclideanNorm(); return ( NearestPoint( aP ) - aP ).SquaredEuclideanNorm();
} }
int Distance( const VECTOR2I& aP ) const int Distance( const VECTOR2I& aP ) const
{ {
return sqrt( SquaredDistance( aP ) ); return sqrt( SquaredDistance( aP ) );
} }
/** /**
* Function Collinear() * Function Collinear()
* *
* Checks if segment aSeg lies on the same line as (this). * Checks if segment aSeg lies on the same line as (this).
* @param aSeg the segment to chech colinearity with * @param aSeg the segment to chech colinearity with
* @return true, when segments are collinear. * @return true, when segments are collinear.
*/ */
bool Collinear( const SEG& aSeg ) const bool Collinear( const SEG& aSeg ) const
{ {
ecoord qa1 = a.y - b.y; ecoord qa1 = a.y - b.y;
ecoord qb1 = b.x - a.x; ecoord qb1 = b.x - a.x;
ecoord qc1 = -qa1 * a.x - qb1 * a.y; ecoord qc1 = -qa1 * a.x - qb1 * a.y;
ecoord qa2 = aSeg.a.y - aSeg.b.y; ecoord qa2 = aSeg.a.y - aSeg.b.y;
ecoord qb2 = aSeg.b.x - aSeg.a.x; ecoord qb2 = aSeg.b.x - aSeg.a.x;
ecoord qc2 = -qa2 * aSeg.a.x - qb2 * aSeg.a.y; ecoord qc2 = -qa2 * aSeg.a.x - qb2 * aSeg.a.y;
return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 ); return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 );
} }
/** /**
* Function Length() * Function Length()
* *
* Returns the length (this) * Returns the length (this)
* @return length * @return length
*/ */
int Length() const int Length() const
{ {
return ( a - b ).EuclideanNorm(); return ( a - b ).EuclideanNorm();
} }
ecoord SquaredLength() const ecoord SquaredLength() const
{ {
return ( a - b ).SquaredEuclideanNorm(); return ( a - b ).SquaredEuclideanNorm();
} }
/** /**
* Function Index() * Function Index()
* *
* Return the index of this segment in its parent shape (applicable only to non-local segments) * Return the index of this segment in its parent shape (applicable only to non-local segments)
* @return index value * @return index value
*/ */
int Index() const int Index() const
{ {
return m_index; return m_index;
} }
bool Contains( const VECTOR2I& aP ) const; bool Contains( const VECTOR2I& aP ) const;
bool PointCloserThan( const VECTOR2I& aP, int aDist ) const; bool PointCloserThan( const VECTOR2I& aP, int aDist ) const;
// friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg ); // friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
private: private:
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const; bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
///> locally stored start/end coordinates (used when m_is_local == true) ///> locally stored start/end coordinates (used when m_is_local == true)
VECTOR2I m_a, m_b; VECTOR2I m_a, m_b;
///> index withing the parent shape (used when m_is_local == false) ///> index withing the parent shape (used when m_is_local == false)
int m_index; int m_index;
///> locality flag ///> locality flag
bool m_is_local; bool m_is_local;
}; };
inline VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const inline VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const
{ {
// fixme: numerical errors for large integers // fixme: numerical errors for large integers
assert( false ); assert( false );
return VECTOR2I( 0, 0 ); return VECTOR2I( 0, 0 );
} }
inline int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const inline int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const
{ {
ecoord p = a.y - b.y; ecoord p = a.y - b.y;
ecoord q = b.x - a.x; 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 ); 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 ...@@ -321,14 +321,14 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
if( l_squared == 0 ) if( l_squared == 0 )
return a; return a;
ecoord t = d.Dot( aP - a ); ecoord t = d.Dot( aP - a );
if( t < 0 ) if( t < 0 )
return a; return a;
else if( t > l_squared ) else if( t > l_squared )
return b; return b;
int xp = rescale( t, (ecoord)d.x, l_squared ); int xp = rescale( t, (ecoord)d.x, l_squared );
int yp = rescale( t, (ecoord)d.y, l_squared ); int yp = rescale( t, (ecoord)d.y, l_squared );
...@@ -338,7 +338,7 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const ...@@ -338,7 +338,7 @@ inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg ) inline std::ostream& operator<<( std::ostream& aStream, const SEG& aSeg )
{ {
if( aSeg.m_is_local ) if( aSeg.m_is_local )
aStream << "[ local " << aSeg.a << " - " << aSeg.b << " ]"; aStream << "[ local " << aSeg.a << " - " << aSeg.b << " ]";
return aStream; return aStream;
} }
......
...@@ -36,109 +36,109 @@ ...@@ -36,109 +36,109 @@
*/ */
enum ShapeType { enum ShapeType {
SH_RECT = 0, ///> axis-aligned rectangle SH_RECT = 0, ///> axis-aligned rectangle
SH_SEGMENT, ///> line segment SH_SEGMENT, ///> line segment
SH_LINE_CHAIN, ///> line chain (polyline) SH_LINE_CHAIN, ///> line chain (polyline)
SH_CIRCLE ///> circle SH_CIRCLE ///> circle
}; };
/** /**
* Class SHAPE * Class SHAPE
* *
* Represents an abstract shape on 2D plane. * Represents an abstract shape on 2D plane.
*/ */
class SHAPE { class SHAPE {
protected: protected:
typedef VECTOR2I::extended_type ecoord; typedef VECTOR2I::extended_type ecoord;
public: public:
/** /**
* Constructor * Constructor
* *
* Creates an empty shape of type aType * Creates an empty shape of type aType
*/ */
SHAPE ( ShapeType aType ) : m_type( aType ) { }; SHAPE ( ShapeType aType ) : m_type( aType ) { };
// Destructor // Destructor
virtual ~SHAPE() {}; virtual ~SHAPE() {};
/** /**
* Function Type() * Function Type()
* *
* Returns the type of the shape. * Returns the type of the shape.
* @retval the type * @retval the type
*/ */
ShapeType Type() const { return m_type; } ShapeType Type() const { return m_type; }
/** /**
* Function Clone() * Function Clone()
* *
* Returns a dynamically allocated copy of the shape * Returns a dynamically allocated copy of the shape
* @retval copy of the shape * @retval copy of the shape
*/ */
virtual SHAPE* Clone() const { virtual SHAPE* Clone() const {
assert( false ); assert( false );
return NULL; return NULL;
}; };
/** /**
* Function Collide() * Function Collide()
* *
* Checks if the boundary of shape (this) lies closer to the point aP than aClearance, indicating * Checks if the boundary of shape (this) lies closer to the point aP than aClearance, indicating
* a collision. * a collision.
* @return true, if there is a collision. * @return true, if there is a collision.
*/ */
virtual bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const virtual bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const
{ {
return Collide( SEG( aP, aP ), aClearance ); return Collide( SEG( aP, aP ), aClearance );
} }
/** /**
* Function Collide() * Function Collide()
* *
* Checks if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating * Checks if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating
* a collision. * a collision.
* @param aShape shape to check collision against * @param aShape shape to check collision against
* @param aClearance minimum clearance * @param aClearance minimum clearance
* @param aMTV minimum translation vector * @param aMTV minimum translation vector
* @return true, if there is a collision. * @return true, if there is a collision.
*/ */
virtual bool Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const; virtual bool Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const;
virtual bool Collide( const SHAPE* aShape, int aClerance = 0 ) const; virtual bool Collide( const SHAPE* aShape, int aClerance = 0 ) const;
/** /**
* Function Collide() * Function Collide()
* *
* Checks if the boundary of shape (this) lies closer to the segment aSeg than aClearance, indicating * Checks if the boundary of shape (this) lies closer to the segment aSeg than aClearance, indicating
* a collision. * a collision.
* @return true, if there is a collision. * @return true, if there is a collision.
*/ */
virtual bool Collide( const SEG& aSeg, int aClearance = 0 ) const = 0; virtual bool Collide( const SEG& aSeg, int aClearance = 0 ) const = 0;
/** /**
* Function Collide() * Function Collide()
* *
* Computes a bounding box of the shape, with a margin of aClearance * Computes a bounding box of the shape, with a margin of aClearance
* a collision. * a collision.
* @aClearance how much the bounding box is expanded wrs to the minimum enclosing rectangle for the shape. * @aClearance how much the bounding box is expanded wrs to the minimum enclosing rectangle for the shape.
* @return the bounding box. * @return the bounding box.
*/ */
virtual const BOX2I BBox( int aClearance = 0 ) const = 0; virtual const BOX2I BBox( int aClearance = 0 ) const = 0;
/** /**
* Function Centre() * Function Centre()
* *
* Computes a center-of-mass of the shape * Computes a center-of-mass of the shape
* @return the center-of-mass point * @return the center-of-mass point
*/ */
virtual VECTOR2I Centre() const virtual VECTOR2I Centre() const
{ {
return BBox( 0 ).Centre(); // if nothing better is available.... return BBox( 0 ).Centre(); // if nothing better is available....
} }
private: private:
///> type of our shape ///> type of our shape
ShapeType m_type; ShapeType m_type;
}; };
......
...@@ -30,48 +30,48 @@ ...@@ -30,48 +30,48 @@
class SHAPE_CIRCLE : public SHAPE { class SHAPE_CIRCLE : public SHAPE {
public: public:
SHAPE_CIRCLE(): SHAPE_CIRCLE():
SHAPE( SH_CIRCLE ), m_radius( 0 ) {}; 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_CIRCLE( const VECTOR2I& aCenter, int aRadius ):
SHAPE( SH_CIRCLE ), m_radius( aRadius ), m_center( aCenter ) {};
const BOX2I BBox( int aClearance = 0 ) const ~SHAPE_CIRCLE() {};
{
const VECTOR2I rc( m_radius + aClearance, m_radius + aClearance );
return BOX2I( m_center - rc, rc * 2 );
}
bool Collide( const SEG& aSeg, int aClearance = 0 ) const const BOX2I BBox( int aClearance = 0 ) const
{ {
int rc = aClearance + m_radius; const VECTOR2I rc( m_radius + aClearance, m_radius + aClearance );
return aSeg.Distance( m_center ) <= rc; return BOX2I( m_center - rc, rc * 2 );
} }
void SetRadius( int aRadius ) bool Collide( const SEG& aSeg, int aClearance = 0 ) const
{ {
m_radius = aRadius; int rc = aClearance + m_radius;
} return aSeg.Distance( m_center ) <= rc;
}
void SetCenter( const VECTOR2I& aCenter ) void SetRadius( int aRadius )
{ {
m_center = aCenter; m_radius = aRadius;
} }
int GetRadius() const void SetCenter( const VECTOR2I& aCenter )
{ {
return m_radius; m_center = aCenter;
} }
const VECTOR2I GetCenter() const int GetRadius() const
{ {
return m_center; return m_radius;
} }
const VECTOR2I GetCenter() const
{
return m_center;
}
private: private:
int m_radius; int m_radius;
VECTOR2I m_center; VECTOR2I m_center;
}; };
#endif #endif
...@@ -276,11 +276,11 @@ class SHAPE_INDEX ...@@ -276,11 +276,11 @@ class SHAPE_INDEX
{ {
BOX2I box = aShape->BBox(); BOX2I box = aShape->BBox();
box.Inflate( aMinDistance ); 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 );
} }
/** /**
......
...@@ -29,205 +29,205 @@ ...@@ -29,205 +29,205 @@
template <class T> const SHAPE* defaultShapeFunctor( const T aItem ) 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> > template <class T, const SHAPE* (ShapeFunctor)(const T) = defaultShapeFunctor<T> >
class SHAPE_INDEX_LIST { class SHAPE_INDEX_LIST {
struct ShapeEntry { struct ShapeEntry {
ShapeEntry( T aParent ) ShapeEntry( T aParent )
{ {
shape = ShapeFunctor( aParent ); shape = ShapeFunctor( aParent );
bbox = shape->BBox( 0 ); bbox = shape->BBox( 0 );
parent = aParent; parent = aParent;
} }
~ShapeEntry() ~ShapeEntry()
{ {
} }
T parent; T parent;
const SHAPE* shape; const SHAPE* shape;
BOX2I bbox; BOX2I bbox;
}; };
typedef std::vector<ShapeEntry> ShapeVec; typedef std::vector<ShapeEntry> ShapeVec;
typedef typename std::vector<ShapeEntry>::iterator ShapeVecIter; typedef typename std::vector<ShapeEntry>::iterator ShapeVecIter;
public: public:
// "Normal" iterator interface, for STL algorithms. // "Normal" iterator interface, for STL algorithms.
class iterator { class iterator {
public: public:
iterator() {}; iterator() {};
iterator( ShapeVecIter aCurrent ) iterator( ShapeVecIter aCurrent )
: m_current( aCurrent ) {}; : m_current( aCurrent ) {};
iterator( const iterator &aB ) : iterator( const iterator &aB ) :
m_current( aB.m_current ) {}; m_current( aB.m_current ) {};
T operator*() const T operator*() const
{ {
return (*m_current).parent; return (*m_current).parent;
} }
void operator++() void operator++()
{ {
++m_current; ++m_current;
} }
iterator& operator++( int aDummy ) iterator& operator++( int aDummy )
{ {
++m_current; ++m_current;
return *this; return *this;
} }
bool operator==( const iterator& aRhs ) const bool operator==( const iterator& aRhs ) const
{ {
return m_current == aRhs.m_current; return m_current == aRhs.m_current;
} }
bool operator!=( const iterator& aRhs ) const bool operator!=( const iterator& aRhs ) const
{ {
return m_current != aRhs.m_current; return m_current != aRhs.m_current;
} }
const iterator& operator=( const iterator& aRhs ) const iterator& operator=( const iterator& aRhs )
{ {
m_current = aRhs.m_current; m_current = aRhs.m_current;
return *this; return *this;
} }
private: private:
ShapeVecIter m_current; ShapeVecIter m_current;
}; };
// "Query" iterator, for iterating over a set of spatially matching shapes. // "Query" iterator, for iterating over a set of spatially matching shapes.
class query_iterator { class query_iterator {
public: public:
query_iterator() query_iterator()
{ {
} }
query_iterator( ShapeVecIter aCurrent, ShapeVecIter aEnd, SHAPE* aShape, query_iterator( ShapeVecIter aCurrent, ShapeVecIter aEnd, SHAPE* aShape,
int aMinDistance, bool aExact ) : int aMinDistance, bool aExact ) :
m_end( aEnd ), m_end( aEnd ),
m_current( aCurrent ), m_current( aCurrent ),
m_shape( aShape ), m_shape( aShape ),
m_minDistance( aMinDistance ), m_minDistance( aMinDistance ),
m_exact( aExact ) m_exact( aExact )
{ {
if( aShape ) if( aShape )
{ {
m_refBBox = aShape->BBox(); m_refBBox = aShape->BBox();
next(); next();
} }
} }
query_iterator( const query_iterator &aB ) : query_iterator( const query_iterator &aB ) :
m_end( aB.m_end ), m_end( aB.m_end ),
m_current( aB.m_current ), m_current( aB.m_current ),
m_shape( aB.m_shape ), m_shape( aB.m_shape ),
m_minDistance( aB.m_minDistance ), m_minDistance( aB.m_minDistance ),
m_exact( aB.m_exact ), m_exact( aB.m_exact ),
m_refBBox( aB.m_refBBox ) m_refBBox( aB.m_refBBox )
{ {
} }
T operator*() const T operator*() const
{ {
return (*m_current).parent; return (*m_current).parent;
} }
query_iterator& operator++() query_iterator& operator++()
{ {
++m_current; ++m_current;
next(); next();
return *this; return *this;
} }
query_iterator& operator++( int aDummy ) query_iterator& operator++( int aDummy )
{ {
++m_current; ++m_current;
next(); next();
return *this; return *this;
} }
bool operator==( const query_iterator& aRhs ) const bool operator==( const query_iterator& aRhs ) const
{ {
return m_current == aRhs.m_current; return m_current == aRhs.m_current;
} }
bool operator!=( const query_iterator& aRhs ) const bool operator!=( const query_iterator& aRhs ) const
{ {
return m_current != aRhs.m_current; return m_current != aRhs.m_current;
} }
const query_iterator& operator=( const query_iterator& aRhs ) const query_iterator& operator=( const query_iterator& aRhs )
{ {
m_end = aRhs.m_end; m_end = aRhs.m_end;
m_current = aRhs.m_current; m_current = aRhs.m_current;
m_shape = aRhs.m_shape; m_shape = aRhs.m_shape;
m_minDistance = aRhs.m_minDistance; m_minDistance = aRhs.m_minDistance;
m_exact = aRhs.m_exact; m_exact = aRhs.m_exact;
m_refBBox = aRhs.m_refBBox; m_refBBox = aRhs.m_refBBox;
return *this; return *this;
} }
private: private:
void next() void next()
{ {
while( m_current != m_end ) while( m_current != m_end )
{ {
if( m_refBBox.Distance( m_current->bbox ) <= m_minDistance ) if( m_refBBox.Distance( m_current->bbox ) <= m_minDistance )
{ {
if( !m_exact || m_current->shape->Collide( m_shape, m_minDistance ) ) if( !m_exact || m_current->shape->Collide( m_shape, m_minDistance ) )
return; return;
} }
++m_current; ++m_current;
} }
} }
ShapeVecIter m_end; ShapeVecIter m_end;
ShapeVecIter m_current; ShapeVecIter m_current;
BOX2I m_refBBox; BOX2I m_refBBox;
bool m_exact; bool m_exact;
SHAPE *m_shape; SHAPE *m_shape;
int m_minDistance; int m_minDistance;
}; };
void Add( T aItem ) void Add( T aItem )
{ {
ShapeEntry s( aItem ); ShapeEntry s( aItem );
m_shapes.push_back(s); m_shapes.push_back(s);
} }
void Remove( const T aItem ) void Remove( const T aItem )
{ {
ShapeVecIter i; ShapeVecIter i;
for( i = m_shapes.begin(); i != m_shapes.end(); ++i ) for( i = m_shapes.begin(); i != m_shapes.end(); ++i )
{ {
if( i->parent == aItem ) if( i->parent == aItem )
break; break;
} }
if( i == m_shapes.end() ) if( i == m_shapes.end() )
return; return;
m_shapes.erase( i ); m_shapes.erase( i );
} }
int Size() const int Size() const
{ {
return m_shapes.size(); return m_shapes.size();
} }
template<class Visitor> template<class Visitor>
int Query( const SHAPE *aShape, int aMinDistance, Visitor &aV, bool aExact = true ) //const int Query( const SHAPE *aShape, int aMinDistance, Visitor &aV, bool aExact = true ) //const
{ {
ShapeVecIter i; ShapeVecIter i;
...@@ -251,33 +251,33 @@ public: ...@@ -251,33 +251,33 @@ public:
return n; return n;
} }
void Clear() void Clear()
{ {
m_shapes.clear(); m_shapes.clear();
} }
query_iterator qbegin( SHAPE* aShape, int aMinDistance, bool aExact ) query_iterator qbegin( SHAPE* aShape, int aMinDistance, bool aExact )
{ {
return query_iterator( m_shapes.begin(), m_shapes.end(), aShape, aMinDistance, aExact ); return query_iterator( m_shapes.begin(), m_shapes.end(), aShape, aMinDistance, aExact );
} }
const query_iterator qend() const query_iterator qend()
{ {
return query_iterator( m_shapes.end(), m_shapes.end(), NULL, 0, false ); return query_iterator( m_shapes.end(), m_shapes.end(), NULL, 0, false );
} }
iterator begin() iterator begin()
{ {
return iterator( m_shapes.begin() ); return iterator( m_shapes.begin() );
} }
iterator end() iterator end()
{ {
return iterator( m_shapes.end() ); return iterator( m_shapes.end() );
} }
private: private:
ShapeVec m_shapes; ShapeVec m_shapes;
}; };
#endif #endif
...@@ -38,504 +38,504 @@ ...@@ -38,504 +38,504 @@
* Class SHAPE_LINE_CHAIN * Class SHAPE_LINE_CHAIN
* *
* Represents a polyline (an zero-thickness chain of connected line segments). * 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! * SHAPE_LINE_CHAIN class shall not be used for polygons!
*/ */
class SHAPE_LINE_CHAIN : public SHAPE { class SHAPE_LINE_CHAIN : public SHAPE {
private: private:
typedef std::vector<VECTOR2I>::iterator point_iter; typedef std::vector<VECTOR2I>::iterator point_iter;
typedef std::vector<VECTOR2I>::const_iterator point_citer; typedef std::vector<VECTOR2I>::const_iterator point_citer;
public: public:
/** /**
* Struct Intersection * Struct Intersection
* *
* Represents an intersection between two line segments * Represents an intersection between two line segments
*/ */
struct Intersection struct Intersection
{ {
/// segment belonging from the (this) argument of Intersect() /// segment belonging from the (this) argument of Intersect()
SEG our; SEG our;
/// segment belonging from the aOther argument of Intersect() /// segment belonging from the aOther argument of Intersect()
SEG their; SEG their;
/// point of intersection between our and their. /// point of intersection between our and their.
VECTOR2I p; VECTOR2I p;
}; };
typedef std::vector<Intersection> Intersections; typedef std::vector<Intersection> Intersections;
/** /**
* Constructor * Constructor
* Initializes an empty line chain. * Initializes an empty line chain.
*/ */
SHAPE_LINE_CHAIN(): SHAPE_LINE_CHAIN():
SHAPE( SH_LINE_CHAIN ), m_closed( false ) {}; SHAPE( SH_LINE_CHAIN ), m_closed( false ) {};
/** /**
* Copy Constructor * Copy Constructor
*/ */
SHAPE_LINE_CHAIN( const SHAPE_LINE_CHAIN& aShape ) : SHAPE_LINE_CHAIN( const SHAPE_LINE_CHAIN& aShape ) :
SHAPE( SH_LINE_CHAIN ), m_points( aShape.m_points ), m_closed( aShape.m_closed ) {}; SHAPE( SH_LINE_CHAIN ), m_points( aShape.m_points ), m_closed( aShape.m_closed ) {};
/** /**
* Constructor * Constructor
* Initializes a 2-point line chain (a single segment) * Initializes a 2-point line chain (a single segment)
*/ */
SHAPE_LINE_CHAIN( const VECTOR2I& aA, const VECTOR2I& aB ) : SHAPE_LINE_CHAIN( const VECTOR2I& aA, const VECTOR2I& aB ) :
SHAPE( SH_LINE_CHAIN ), SHAPE( SH_LINE_CHAIN ),
m_closed( false ) m_closed( false )
{ {
m_points.resize( 2 ); m_points.resize( 2 );
m_points[0] = aA; m_points[0] = aA;
m_points[1] = aB; m_points[1] = aB;
} }
SHAPE_LINE_CHAIN( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ): SHAPE_LINE_CHAIN( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ):
SHAPE( SH_LINE_CHAIN ), SHAPE( SH_LINE_CHAIN ),
m_closed( false ) m_closed( false )
{ {
m_points.resize( 3 ); m_points.resize( 3 );
m_points[0] = aA; m_points[0] = aA;
m_points[1] = aB; m_points[1] = aB;
m_points[2] = aC; m_points[2] = aC;
} }
SHAPE_LINE_CHAIN(const VECTOR2I* aV, int aCount ) : SHAPE_LINE_CHAIN(const VECTOR2I* aV, int aCount ) :
SHAPE( SH_LINE_CHAIN ), SHAPE( SH_LINE_CHAIN ),
m_closed( false ) m_closed( false )
{ {
m_points.resize( aCount ); m_points.resize( aCount );
for( int i = 0; i < aCount; i++ ) for( int i = 0; i < aCount; i++ )
m_points[i] = *aV++; m_points[i] = *aV++;
} }
~SHAPE_LINE_CHAIN() {}; ~SHAPE_LINE_CHAIN() {};
/** /**
* Function Clear() * Function Clear()
* Removes all points from the line chain. * Removes all points from the line chain.
*/ */
void Clear() void Clear()
{ {
m_points.clear(); m_points.clear();
m_closed = false; m_closed = false;
} }
/** /**
* Function SetClosed() * Function SetClosed()
* *
* Marks the line chain as closed (i.e. with a segment connecting the last point with the first point). * 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. * @param aClosed: whether the line chain is to be closed or not.
*/ */
void SetClosed( bool aClosed ) void SetClosed( bool aClosed )
{ {
m_closed = aClosed; m_closed = aClosed;
} }
/** /**
* Function IsClosed() * Function IsClosed()
* *
* @return aClosed: true, when our line is closed. * @return aClosed: true, when our line is closed.
*/ */
bool IsClosed() const bool IsClosed() const
{ {
return m_closed; return m_closed;
} }
/** /**
* Function SegmentCount() * Function SegmentCount()
* *
* Returns number of segments in this line chain. * Returns number of segments in this line chain.
* @return number of segments * @return number of segments
*/ */
int SegmentCount() const int SegmentCount() const
{ {
int c = m_points.size() - 1; int c = m_points.size() - 1;
if( m_closed ) if( m_closed )
c++; c++;
return std::max( 0, c ); return std::max( 0, c );
} }
/** /**
* Function PointCount() * Function PointCount()
* *
* Returns the number of points (vertices) in this line chain * Returns the number of points (vertices) in this line chain
* @return number of points * @return number of points
*/ */
int PointCount() const int PointCount() const
{ {
return m_points.size(); return m_points.size();
} }
/** /**
* Function Segment() * Function Segment()
* *
* Returns a segment referencing to the segment (index) in the line chain. * 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. * 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 * @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) * the last segment in the line chain)
* @return SEG referenced to given segment in the line chain * @return SEG referenced to given segment in the line chain
*/ */
SEG Segment( int aIndex ) SEG Segment( int aIndex )
{ {
if( aIndex < 0 ) if( aIndex < 0 )
aIndex += SegmentCount(); aIndex += SegmentCount();
if( aIndex == ( m_points.size() - 1 ) && m_closed ) if( aIndex == ( m_points.size() - 1 ) && m_closed )
return SEG( m_points[aIndex], m_points[0], aIndex ); return SEG( m_points[aIndex], m_points[0], aIndex );
else else
return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex ); return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
} }
/** /**
* Function CSegment() * Function CSegment()
* *
* Returns a read-only segment referencing to the segment (index) in the line chain. * 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 * @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) * the last segment in the line chain)
* @return SEG referenced to given segment in the line chain * @return SEG referenced to given segment in the line chain
*/ */
const SEG CSegment( int aIndex ) const const SEG CSegment( int aIndex ) const
{ {
if( aIndex < 0 ) if( aIndex < 0 )
aIndex += SegmentCount(); aIndex += SegmentCount();
if( aIndex == ( m_points.size() - 1 ) && m_closed ) if( aIndex == ( m_points.size() - 1 ) && m_closed )
return SEG( const_cast<VECTOR2I&>( m_points[aIndex] ), return SEG( const_cast<VECTOR2I&>( m_points[aIndex] ),
const_cast<VECTOR2I&>( m_points[0] ), aIndex ); const_cast<VECTOR2I&>( m_points[0] ), aIndex );
else else
return SEG( const_cast<VECTOR2I&>( m_points[aIndex] ), return SEG( const_cast<VECTOR2I&>( m_points[aIndex] ),
const_cast<VECTOR2I&>( m_points[aIndex + 1] ), aIndex ); const_cast<VECTOR2I&>( m_points[aIndex + 1] ), aIndex );
} }
/** /**
* Function Point() * Function Point()
* *
* Returns a reference to a given point in the line chain. * Returns a reference to a given point in the line chain.
* @param aIndex index of the point * @param aIndex index of the point
* @return reference to the point * @return reference to the point
*/ */
VECTOR2I& Point( int aIndex ) VECTOR2I& Point( int aIndex )
{ {
if( aIndex < 0 ) if( aIndex < 0 )
aIndex += PointCount(); aIndex += PointCount();
return m_points[aIndex]; return m_points[aIndex];
} }
/** /**
* Function CPoint() * Function CPoint()
* *
* Returns a const reference to a given point in the line chain. * Returns a const reference to a given point in the line chain.
* @param aIndex index of the point * @param aIndex index of the point
* @return const reference to the point * @return const reference to the point
*/ */
const VECTOR2I& CPoint( int aIndex ) const const VECTOR2I& CPoint( int aIndex ) const
{ {
if( aIndex < 0 ) if( aIndex < 0 )
aIndex += PointCount(); aIndex += PointCount();
return m_points[aIndex]; return m_points[aIndex];
} }
/// @copydoc SHAPE::BBox() /// @copydoc SHAPE::BBox()
const BOX2I BBox( int aClearance = 0 ) const const BOX2I BBox( int aClearance = 0 ) const
{ {
BOX2I bbox; BOX2I bbox;
bbox.Compute( m_points ); bbox.Compute( m_points );
return bbox; return bbox;
} }
/** /**
* Function Collide() * Function Collide()
* *
* Checks if point aP lies closer to us than aClearance. * Checks if point aP lies closer to us than aClearance.
* @param aP the point to check for collisions with * @param aP the point to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision. * @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found * @return true, when a collision has been found
*/ */
bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const; bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const;
/** /**
* Function Collide() * Function Collide()
* *
* Checks if box aBox lies closer to us than aClearance. * Checks if box aBox lies closer to us than aClearance.
* @param aP the box to check for collisions with * @param aP the box to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision. * @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found * @return true, when a collision has been found
*/ */
bool Collide( const BOX2I& aBox, int aClearance = 0 ) const; bool Collide( const BOX2I& aBox, int aClearance = 0 ) const;
/** /**
* Function Collide() * Function Collide()
* *
* Checks if segment aSeg lies closer to us than aClearance. * Checks if segment aSeg lies closer to us than aClearance.
* @param aSeg the segment to check for collisions with * @param aSeg the segment to check for collisions with
* @param aClearance minimum distance that does not qualify as a collision. * @param aClearance minimum distance that does not qualify as a collision.
* @return true, when a collision has been found * @return true, when a collision has been found
*/ */
bool Collide( const SEG& aSeg, int aClearance = 0 ) const; bool Collide( const SEG& aSeg, int aClearance = 0 ) const;
/** /**
* Function Distance() * Function Distance()
* *
* Computes the minimum distance between the line chain and a point aP. * Computes the minimum distance between the line chain and a point aP.
* @param aP the point * @param aP the point
* @return minimum distance. * @return minimum distance.
*/ */
int Distance( const VECTOR2I& aP ) const; int Distance( const VECTOR2I& aP ) const;
/** /**
* Function Reverse() * Function Reverse()
* *
* Reverses point order in the line chain. * Reverses point order in the line chain.
* @return line chain with reversed point order (original A-B-C-D: returned D-C-B-A) * @return line chain with reversed point order (original A-B-C-D: returned D-C-B-A)
*/ */
const SHAPE_LINE_CHAIN Reverse() const; const SHAPE_LINE_CHAIN Reverse() const;
/** /**
* Function Length() * Function Length()
* *
* Returns length of the line chain in Euclidean metric. * Returns length of the line chain in Euclidean metric.
* @return length of the line chain * @return length of the line chain
*/ */
int Length() const; int Length() const;
/** /**
* Function Append() * Function Append()
* *
* Appends a new point at the end of the line chain. * Appends a new point at the end of the line chain.
* @param aX is X coordinate of the new point * @param aX is X coordinate of the new point
* @param aY is Y coordinate of the new point * @param aY is Y coordinate of the new point
*/ */
void Append( int aX, int aY ) void Append( int aX, int aY )
{ {
VECTOR2I v( aX, aY ); VECTOR2I v( aX, aY );
Append( v ); Append( v );
} }
/** /**
* Function Append() * Function Append()
* *
* Appends a new point at the end of the line chain. * Appends a new point at the end of the line chain.
* @param aP the new point * @param aP the new point
*/ */
void Append( const VECTOR2I& aP ) void Append( const VECTOR2I& aP )
{ {
if( m_points.size() == 0 ) if( m_points.size() == 0 )
m_bbox = BOX2I( aP, VECTOR2I( 0, 0 ) ); m_bbox = BOX2I( aP, VECTOR2I( 0, 0 ) );
if( m_points.size() == 0 || CPoint( -1 ) != aP ) if( m_points.size() == 0 || CPoint( -1 ) != aP )
{ {
m_points.push_back( aP ); m_points.push_back( aP );
m_bbox.Merge( aP ); m_bbox.Merge( aP );
} }
} }
/** /**
* Function Append() * Function Append()
* *
* Appends another line chain at the end. * Appends another line chain at the end.
* @param aOtherLine the line chain to be appended. * @param aOtherLine the line chain to be appended.
*/ */
void Append( const SHAPE_LINE_CHAIN& aOtherLine ) void Append( const SHAPE_LINE_CHAIN& aOtherLine )
{ {
if( aOtherLine.PointCount() == 0 ) if( aOtherLine.PointCount() == 0 )
return; return;
else if( PointCount() == 0 || aOtherLine.CPoint( 0 ) != CPoint( -1 ) ) else if( PointCount() == 0 || aOtherLine.CPoint( 0 ) != CPoint( -1 ) )
{ {
const VECTOR2I p = aOtherLine.CPoint( 0 ); const VECTOR2I p = aOtherLine.CPoint( 0 );
m_points.push_back( p ); m_points.push_back( p );
m_bbox.Merge( p ); m_bbox.Merge( p );
} }
for( int i = 1; i < aOtherLine.PointCount(); i++ ) for( int i = 1; i < aOtherLine.PointCount(); i++ )
{ {
const VECTOR2I p = aOtherLine.CPoint( i ); const VECTOR2I p = aOtherLine.CPoint( i );
m_points.push_back( p ); m_points.push_back( p );
m_bbox.Merge( p ); m_bbox.Merge( p );
} }
} }
/** /**
* Function Replace() * Function Replace()
* *
* Replaces points with indices in range [start_index, end_index] with a single * Replaces points with indices in range [start_index, end_index] with a single
* point aP. * point aP.
* @param aStartIndex start of the point range to be replaced (inclusive) * @param aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive) * @param aEndIndex end of the point range to be replaced (inclusive)
* @param aP replacement point * @param aP replacement point
*/ */
void Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP ); void Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP );
/** /**
* Function Replace() * Function Replace()
* *
* Replaces points with indices in range [start_index, end_index] with the points from * Replaces points with indices in range [start_index, end_index] with the points from
* line chain aLine. * line chain aLine.
* @param aStartIndex start of the point range to be replaced (inclusive) * @param aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end of the point range to be replaced (inclusive) * @param aEndIndex end of the point range to be replaced (inclusive)
* @param aLine replacement line chain. * @param aLine replacement line chain.
*/ */
void Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine ); void Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine );
/** /**
* Function Remove() * Function Remove()
* *
* Removes the range of points [start_index, end_index] from the line chain. * 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 aStartIndex start of the point range to be replaced (inclusive)
* @param aEndIndex end 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 ); void Remove( int aStartIndex, int aEndIndex );
/** /**
* Function Split() * Function Split()
* *
* Inserts the point aP belonging to one of the our segments, splitting the adjacent * Inserts the point aP belonging to one of the our segments, splitting the adjacent
* segment in two. * segment in two.
* @param aP the point to be inserted * @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) * @return index of the newly inserted point (or a negative value if aP does not lie on our line)
*/ */
int Split( const VECTOR2I& aP ); int Split( const VECTOR2I& aP );
/** /**
* Function Find() * Function Find()
* *
* Searches for point aP. * Searches for point aP.
* @param aP the point to be looked for * @param aP the point to be looked for
* @return index of the correspoinding point in the line chain or negative when not found. * @return index of the correspoinding point in the line chain or negative when not found.
*/ */
int Find ( const VECTOR2I& aP ) const; int Find ( const VECTOR2I& aP ) const;
/** /**
* Function Slice() * Function Slice()
* *
* Returns a subset of this line chain containing the [start_index, end_index] range of points. * 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 aStartIndex start of the point range to be returned (inclusive)
* @param aEndIndex end of the point range to be returned (inclusive) * @param aEndIndex end of the point range to be returned (inclusive)
* @return cut line chain. * @return cut line chain.
*/ */
const SHAPE_LINE_CHAIN Slice( int aStartIndex, int aEndIndex = -1) const; const SHAPE_LINE_CHAIN Slice( int aStartIndex, int aEndIndex = -1) const;
struct compareOriginDistance struct compareOriginDistance
{ {
compareOriginDistance( VECTOR2I& aOrigin ): compareOriginDistance( VECTOR2I& aOrigin ):
m_origin( aOrigin ) {}; m_origin( aOrigin ) {};
bool operator()( const Intersection& aA, const Intersection& aB ) bool operator()( const Intersection& aA, const Intersection& aB )
{ {
return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm(); return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm();
} }
VECTOR2I m_origin; VECTOR2I m_origin;
}; };
/** /**
* Function Intersect() * Function Intersect()
* *
* Finds all intersection points between our line chain and the segment aSeg. * Finds all intersection points between our line chain and the segment aSeg.
* @param aSeg the segment chain to find intersections with * @param aSeg the segment chain to find intersections with
* @param aIp reference to a vector to store found intersections. Intersection points * @param aIp reference to a vector to store found intersections. Intersection points
* are sorted with increasing distances from point aSeg.a. * are sorted with increasing distances from point aSeg.a.
* @return number of intersections found * @return number of intersections found
*/ */
int Intersect ( const SEG& aSeg, Intersections& aIp ) const; int Intersect ( const SEG& aSeg, Intersections& aIp ) const;
/** /**
* Function Intersect() * Function Intersect()
* *
* Finds all intersection points between our line chain and the line chain aChain. * Finds all intersection points between our line chain and the line chain aChain.
* @param aChain the line chain to find intersections with * @param aChain the line chain to find intersections with
* @param aIp reference to a vector to store found intersections. Intersection points * @param aIp reference to a vector to store found intersections. Intersection points
* are sorted with increasing path lengths from the starting point of aChain. * are sorted with increasing path lengths from the starting point of aChain.
* @return number of intersections found * @return number of intersections found
*/ */
int Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const; int Intersect( const SHAPE_LINE_CHAIN& aChain, Intersections& aIp ) const;
/** /**
* Function PathLength() * Function PathLength()
* *
* Computes the walk path length from the beginning of the line chain and * Computes the walk path length from the beginning of the line chain and
* the point aP belonging to our line. * the point aP belonging to our line.
* @return: path length in Euclidean metric or negative if aP does not belong to the line chain. * @return: path length in Euclidean metric or negative if aP does not belong to the line chain.
*/ */
int PathLength( const VECTOR2I& aP ) const; int PathLength( const VECTOR2I& aP ) const;
/** /**
* Function PointInside() * Function PointInside()
* *
* Checks if point aP lies inside a convex polygon defined by the line chain. For closed * Checks if point aP lies inside a convex polygon defined by the line chain. For closed
* shapes only. * shapes only.
* @param aP point to check * @param aP point to check
* @return true if the point is inside the shape (edge is not treated as being inside). * @return true if the point is inside the shape (edge is not treated as being inside).
*/ */
bool PointInside( const VECTOR2I& aP ) const; bool PointInside( const VECTOR2I& aP ) const;
/** /**
* Function PointOnEdge() * Function PointOnEdge()
* *
* Checks if point aP lies on an edge or vertex of the line chain. * Checks if point aP lies on an edge or vertex of the line chain.
* @param aP point to check * @param aP point to check
* @return true if the point lies on the edge. * @return true if the point lies on the edge.
*/ */
bool PointOnEdge( const VECTOR2I& aP ) const; bool PointOnEdge( const VECTOR2I& aP ) const;
/** /**
* Function SelfIntersecting() * Function SelfIntersecting()
* *
* Checks if the line chain is self-intersecting. * Checks if the line chain is self-intersecting.
* @return (optional) first found self-intersection point. * @return (optional) first found self-intersection point.
*/ */
const boost::optional<Intersection> SelfIntersecting() const; const boost::optional<Intersection> SelfIntersecting() const;
/** /**
* Function Simplify() * Function Simplify()
* *
* Simplifies the line chain by removing colinear adjacent segments and duplicate vertices. * Simplifies the line chain by removing colinear adjacent segments and duplicate vertices.
* @return reference to self. * @return reference to self.
*/ */
SHAPE_LINE_CHAIN& Simplify(); SHAPE_LINE_CHAIN& Simplify();
/** /**
* Function NearestPoint() * Function NearestPoint()
* *
* Finds a point on the line chain that is closest to point aP. * Finds a point on the line chain that is closest to point aP.
* @return the nearest point. * @return the nearest point.
*/ */
const VECTOR2I NearestPoint( const VECTOR2I& aP ) const; const VECTOR2I NearestPoint( const VECTOR2I& aP ) const;
/// @copydoc SHAPE::Format() /// @copydoc SHAPE::Format()
const std::string Format() const; const std::string Format() const;
bool operator!=( const SHAPE_LINE_CHAIN& aRhs ) const bool operator!=( const SHAPE_LINE_CHAIN& aRhs ) const
{ {
if( PointCount() != aRhs.PointCount() ) if( PointCount() != aRhs.PointCount() )
return true; return true;
for( int i = 0; i < PointCount(); i++ ) for( int i = 0; i < PointCount(); i++ )
{ {
if( CPoint( i ) != aRhs.CPoint( i ) ) if( CPoint( i ) != aRhs.CPoint( i ) )
return true; return true;
} }
return false; return false;
} }
private: private:
/// array of vertices /// array of vertices
std::vector<VECTOR2I> m_points; std::vector<VECTOR2I> m_points;
/// is the line chain closed? /// is the line chain closed?
bool m_closed; bool m_closed;
/// cached bounding box /// cached bounding box
BOX2I m_bbox; BOX2I m_bbox;
}; };
#endif // __SHAPE_LINE_CHAIN #endif // __SHAPE_LINE_CHAIN
...@@ -31,114 +31,114 @@ ...@@ -31,114 +31,114 @@
#include <geometry/seg.h> #include <geometry/seg.h>
class SHAPE_RECT : public SHAPE { class SHAPE_RECT : public SHAPE {
public: public:
/** /**
* Constructor * Constructor
* Creates an empty (0-sized) rectangle * Creates an empty (0-sized) rectangle
*/ */
SHAPE_RECT() : SHAPE_RECT() :
SHAPE( SH_RECT ), m_w( 0 ), m_h( 0 ) {}; SHAPE( SH_RECT ), m_w( 0 ), m_h( 0 ) {};
/** /**
* Constructor * Constructor
* Creates a rectangle defined by top-left corner (aX0, aY0), width aW and height aH. * 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_RECT( int aX0, int aY0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aX0, aY0 ), m_w( aW ), m_h( aH ) {}; SHAPE( SH_RECT ), m_p0( aX0, aY0 ), m_w( aW ), m_h( aH ) {};
/** /**
* Constructor * Constructor
* Creates a rectangle defined by top-left corner aP0, width aW and height aH. * Creates a rectangle defined by top-left corner aP0, width aW and height aH.
*/ */
SHAPE_RECT( const VECTOR2I &aP0, int aW, int aH ) : SHAPE_RECT( const VECTOR2I &aP0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH ) {}; SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH ) {};
/// @copydoc SHAPE::BBox() /// @copydoc SHAPE::BBox()
const BOX2I BBox(int aClearance = 0) const const BOX2I BBox(int aClearance = 0) const
{ {
BOX2I bbox( VECTOR2I( m_p0.x - aClearance, m_p0.y - aClearance ), BOX2I bbox( VECTOR2I( m_p0.x - aClearance, m_p0.y - aClearance ),
VECTOR2I( m_w + 2 * aClearance, m_h + 2 * aClearance ) ); VECTOR2I( m_w + 2 * aClearance, m_h + 2 * aClearance ) );
//printf("bb : %s\n",bbox.Format().c_str()); //printf("bb : %s\n",bbox.Format().c_str());
return bbox; return bbox;
} }
/** /**
* Function Diagonal() * Function Diagonal()
* *
* Returns length of the diagonal of the rectangle * Returns length of the diagonal of the rectangle
* @return diagonal length * @return diagonal length
*/ */
int Diagonal() const int Diagonal() const
{ {
return VECTOR2I( m_w, m_h ).EuclideanNorm(); return VECTOR2I( m_w, m_h ).EuclideanNorm();
} }
/// @copydoc SHAPE::Collide() /// @copydoc SHAPE::Collide()
bool Collide( const SEG& aSeg, int aClearance = 0 ) const 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 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)); //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)); //BOX2I r(pmin, VECTOR2I(pmax.x - pmin.x, pmax.y - pmin.y));
//if (BBox(0).SquaredDistance(r) > aClearance * aClearance) //if (BBox(0).SquaredDistance(r) > aClearance * aClearance)
// return false; // return false;
if( BBox( 0 ).Contains( aSeg.a ) || BBox( 0 ).Contains( aSeg.b ) ) if( BBox( 0 ).Contains( aSeg.a ) || BBox( 0 ).Contains( aSeg.b ) )
return true; return true;
VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ), VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y + m_h ), 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 + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y ), VECTOR2I( m_p0.x + m_w, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y ) }; VECTOR2I( m_p0.x, m_p0.y ) };
for( int i = 0; i < 4; i++ ) for( int i = 0; i < 4; i++ )
{ {
SEG s( vts[i], vts[i + 1], i ); SEG s( vts[i], vts[i + 1], i );
if( s.Distance( aSeg ) <= aClearance ) if( s.Distance( aSeg ) <= aClearance )
return true; return true;
} }
return false; return false;
}; };
/** /**
* Function GetPosition() * Function GetPosition()
* *
* @return top-left corner of the rectangle * @return top-left corner of the rectangle
*/ */
const VECTOR2I& GetPosition() const { return m_p0; } const VECTOR2I& GetPosition() const { return m_p0; }
/** /**
* Function GetSize() * Function GetSize()
* *
* @return size of the rectangle * @return size of the rectangle
*/ */
const VECTOR2I GetSize() const { return VECTOR2I( m_w, m_h ); } const VECTOR2I GetSize() const { return VECTOR2I( m_w, m_h ); }
/** /**
* Function GetWidth() * Function GetWidth()
* *
* @return width of the rectangle * @return width of the rectangle
*/ */
const int GetWidth() const { return m_w; } const int GetWidth() const { return m_w; }
/** /**
* Function GetHeight() * Function GetHeight()
* *
* @return height of the rectangle * @return height of the rectangle
*/ */
const int GetHeight() const { return m_h; } const int GetHeight() const { return m_h; }
private: private:
///> Top-left corner ///> Top-left corner
VECTOR2I m_p0; VECTOR2I m_p0;
///> Width ///> Width
int m_w; int m_w;
///> Height ///> Height
int m_h; int m_h;
}; };
#endif // __SHAPE_RECT_H #endif // __SHAPE_RECT_H
...@@ -66,7 +66,7 @@ public: ...@@ -66,7 +66,7 @@ public:
BOX2( const Vec& aPos, const Vec& aSize ) : BOX2( const Vec& aPos, const Vec& aSize ) :
m_Pos( aPos ), m_Pos( aPos ),
m_Size( aSize ) m_Size( aSize )
{ {
Normalize(); Normalize();
} }
...@@ -420,7 +420,7 @@ public: ...@@ -420,7 +420,7 @@ public:
ecoord_type y2 = m_Pos.y + m_Size.y; 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 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 ); 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 ecoord_type Distance( const Vec& aP ) const
......
...@@ -224,7 +224,7 @@ public: ...@@ -224,7 +224,7 @@ public:
/// Division with a factor /// Division with a factor
VECTOR2<T> operator/( const T& aFactor ) const; VECTOR2<T> operator/( const T& aFactor ) const;
/// Equality operator /// Equality operator
const bool operator==( const VECTOR2<T>& aVector ) const; const bool operator==( const VECTOR2<T>& aVector ) const;
......
...@@ -37,105 +37,105 @@ class TOOL_INTERACTIVE; ...@@ -37,105 +37,105 @@ class TOOL_INTERACTIVE;
* Defines the structure of a context (usually right-click) popup menu * Defines the structure of a context (usually right-click) popup menu
* for a given tool. * for a given tool.
*/ */
class CONTEXT_MENU class CONTEXT_MENU
{ {
public: public:
///> Default constructor ///> Default constructor
CONTEXT_MENU(); CONTEXT_MENU();
///> Copy constructor ///> Copy constructor
CONTEXT_MENU( const CONTEXT_MENU& aMenu ); CONTEXT_MENU( const CONTEXT_MENU& aMenu );
/** /**
* Function SetTitle() * Function SetTitle()
* Sets title for the context menu. The title is shown as a text label shown on the top of * Sets title for the context menu. The title is shown as a text label shown on the top of
* the menu. * the menu.
* @param aTitle is the new title. * @param aTitle is the new title.
*/ */
void SetTitle( const wxString& aTitle ); void SetTitle( const wxString& aTitle );
/** /**
* Function Add() * Function Add()
* Adds an entry to the menu. After highlighting/selecting the entry, a TOOL_EVENT command is * Adds an entry to the menu. After highlighting/selecting the entry, a TOOL_EVENT command is
* sent that contains ID of the entry. * sent that contains ID of the entry.
* @param aLabel is the text label show in the menu. * @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. * @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 ); void Add( const wxString& aLabel, int aId );
/** /**
* Function Add() * Function Add()
* Adds an entry to the menu, basing on the TOOL_ACTION object. After selecting the entry, * 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. * a TOOL_EVENT command containing name of the action is sent.
* @param aAction is the action to be added to menu entry. * @param aAction is the action to be added to menu entry.
*/ */
void Add( const TOOL_ACTION& aAction ); void Add( const TOOL_ACTION& aAction );
/** /**
* Function Clear() * Function Clear()
* Removes all the entries from the menu (as well as its title). It leaves the menu in the * Removes all the entries from the menu (as well as its title). It leaves the menu in the
* initial state. * initial state.
*/ */
void Clear(); void Clear();
/** /**
* Function GetMenu() * Function GetMenu()
* Returns the instance of wxMenu object used to display the menu. * Returns the instance of wxMenu object used to display the menu.
*/ */
wxMenu* GetMenu() const wxMenu* GetMenu() const
{ {
return const_cast<wxMenu*>( &m_menu ); return const_cast<wxMenu*>( &m_menu );
} }
private: private:
///> Class CMEventHandler takes care of handling menu events. After reception of particular ///> Class CMEventHandler takes care of handling menu events. After reception of particular
///> events, it translates them to TOOL_EVENTs that may control tools. ///> events, it translates them to TOOL_EVENTs that may control tools.
class CMEventHandler : public wxEvtHandler class CMEventHandler : public wxEvtHandler
{ {
public: public:
///> Default constructor ///> Default constructor
///> aMenu is the CONTEXT_MENU instance for which it handles events. ///> aMenu is the CONTEXT_MENU instance for which it handles events.
CMEventHandler( CONTEXT_MENU* aMenu ) : m_menu( aMenu ) {}; CMEventHandler( CONTEXT_MENU* aMenu ) : m_menu( aMenu ) {};
///> Handler for menu events. ///> Handler for menu events.
void onEvent( wxEvent& aEvent ); void onEvent( wxEvent& aEvent );
private: private:
///> CONTEXT_MENU instance for which it handles events. ///> CONTEXT_MENU instance for which it handles events.
CONTEXT_MENU* m_menu; CONTEXT_MENU* m_menu;
}; };
friend class TOOL_INTERACTIVE; friend class TOOL_INTERACTIVE;
/** /**
* Function setTool() * Function setTool()
* Sets a tool that is the creator of the menu. * Sets a tool that is the creator of the menu.
* @param aTool is the tool that created the menu. * @param aTool is the tool that created the menu.
*/ */
void setTool( TOOL_INTERACTIVE* aTool ) void setTool( TOOL_INTERACTIVE* aTool )
{ {
m_tool = aTool; m_tool = aTool;
} }
/** /**
* Function getHotKeyDescription() * Function getHotKeyDescription()
* Returns a hot key in the string format accepted by wxMenu. * Returns a hot key in the string format accepted by wxMenu.
* @param aAction is the action with hot key to be translated.. * @param aAction is the action with hot key to be translated..
* @return Hot key in the string format compatible with wxMenu. * @return Hot key in the string format compatible with wxMenu.
*/ */
std::string getHotKeyDescription( const TOOL_ACTION& aAction ) const; std::string getHotKeyDescription( const TOOL_ACTION& aAction ) const;
///> Flag indicating that the menu title was set up. ///> Flag indicating that the menu title was set up.
bool m_titleSet; bool m_titleSet;
///> Instance of wxMenu used for display of the context menu. ///> Instance of wxMenu used for display of the context menu.
wxMenu m_menu; wxMenu m_menu;
///> Instance of menu event handler. ///> Instance of menu event handler.
CMEventHandler m_handler; CMEventHandler m_handler;
///> Creator of the menu ///> Creator of the menu
TOOL_INTERACTIVE* m_tool; TOOL_INTERACTIVE* m_tool;
/// Menu items with ID higher than that are considered TOOL_ACTIONs /// Menu items with ID higher than that are considered TOOL_ACTIONs
static const int m_actionId = 10000; static const int m_actionId = 10000;
......
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
/** /**
Class COROUNTINE. Class COROUNTINE.
Implements a coroutine. Wikipedia has a good explanation: Implements a coroutine. Wikipedia has a good explanation:
"Coroutines are computer program components that generalize subroutines to "Coroutines are computer program components that generalize subroutines to
allow multiple entry points for suspending and resuming execution at certain locations. 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 well-suited for implementing more familiar program components such as cooperative
tasks, exceptions, event loop, iterators, infinite lists and pipes." 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, preempted only when it deliberately yields the control to the caller. This way,
we avoid concurrency problems such as locking / race conditions. we avoid concurrency problems such as locking / race conditions.
...@@ -56,82 +56,82 @@ template<class ReturnType, class ArgType> ...@@ -56,82 +56,82 @@ template<class ReturnType, class ArgType>
class COROUTINE class COROUTINE
{ {
public: public:
COROUTINE() COROUTINE()
{ {
m_stackSize = c_defaultStackSize; m_stackSize = c_defaultStackSize;
m_stack = NULL; m_stack = NULL;
m_saved = NULL; m_saved = NULL;
} }
/** /**
* Constructor * Constructor
* Creates a coroutine from a member method of an object * Creates a coroutine from a member method of an object
*/ */
template<class T> template<class T>
COROUTINE( T* object, ReturnType (T::*ptr)( ArgType ) ) : COROUTINE( T* object, ReturnType (T::*ptr)( ArgType ) ) :
m_func( object, ptr ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ) m_func( object, ptr ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize )
{ {
} }
/** /**
* Constructor * Constructor
* Creates a coroutine from a delegate object * Creates a coroutine from a delegate object
*/ */
COROUTINE( DELEGATE<ReturnType, ArgType> aEntry ) : COROUTINE( DELEGATE<ReturnType, ArgType> aEntry ) :
m_func( aEntry ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize ) m_func( aEntry ), m_saved( NULL ), m_stack( NULL ), m_stackSize( c_defaultStackSize )
{}; {};
~COROUTINE() ~COROUTINE()
{ {
if( m_saved ) if( m_saved )
delete m_saved; delete m_saved;
if( m_stack ) if( m_stack )
free( m_stack ); free( m_stack );
} }
/** /**
* Function Yield() * Function Yield()
* *
* Stops execution of the coroutine and returns control to the caller. * Stops execution of the coroutine and returns control to the caller.
* After a yield, Call() or Resume() methods invoked by the caller will * After a yield, Call() or Resume() methods invoked by the caller will
* immediately return true, indicating that we are not done yet, just asleep. * immediately return true, indicating that we are not done yet, just asleep.
*/ */
void Yield() void Yield()
{ {
boost::context::jump_fcontext( m_self, m_saved, 0 ); boost::context::jump_fcontext( m_self, m_saved, 0 );
} }
/** /**
* Function Yield() * Function Yield()
* *
* Yield with a value - passes a value of given type to the caller. * Yield with a value - passes a value of given type to the caller.
* Useful for implementing generator objects. * Useful for implementing generator objects.
*/ */
void Yield( ReturnType& retVal ) void Yield( ReturnType& retVal )
{ {
m_retVal = retVal; m_retVal = retVal;
boost::context::jump_fcontext( m_self, m_saved, 0 ); boost::context::jump_fcontext( m_self, m_saved, 0 );
} }
/** /**
<F11>* Function SetEntry() <F11>* Function SetEntry()
* *
* Defines the entry point for the coroutine, if not set in the constructor. * Defines the entry point for the coroutine, if not set in the constructor.
*/ */
void SetEntry( DELEGATE<ReturnType, ArgType> aEntry ) void SetEntry( DELEGATE<ReturnType, ArgType> aEntry )
{ {
m_func = aEntry; m_func = aEntry;
} }
/* Function Call() /* Function Call()
* *
* Starts execution of a coroutine, passing args as its arguments. * Starts execution of a coroutine, passing args as its arguments.
* @return true, if the coroutine has yielded and false if it has finished its * @return true, if the coroutine has yielded and false if it has finished its
* execution (returned). * execution (returned).
*/ */
bool Call( ArgType args ) bool Call( ArgType args )
{ {
// fixme: Clean up stack stuff. Add a guard // fixme: Clean up stack stuff. Add a guard
m_stack = malloc( c_defaultStackSize ); m_stack = malloc( c_defaultStackSize );
// align to 16 bytes // align to 16 bytes
...@@ -145,87 +145,87 @@ public: ...@@ -145,87 +145,87 @@ public:
// off we go! // off we go!
boost::context::jump_fcontext( m_saved, m_self, reinterpret_cast<intptr_t>( this ) ); boost::context::jump_fcontext( m_saved, m_self, reinterpret_cast<intptr_t>( this ) );
return m_running; return m_running;
} }
/** /**
* Function Resume() * Function Resume()
* *
* Resumes execution of a previously yielded coroutine. * Resumes execution of a previously yielded coroutine.
* @return true, if the coroutine has yielded again and false if it has finished its * @return true, if the coroutine has yielded again and false if it has finished its
* execution (returned). * execution (returned).
*/ */
bool Resume() bool Resume()
{ {
boost::context::jump_fcontext( m_saved, m_self, 0 ); boost::context::jump_fcontext( m_saved, m_self, 0 );
return m_running; return m_running;
} }
/** /**
* Function ReturnValue() * Function ReturnValue()
* *
* Returns the yielded value (the argument Yield() was called with) * Returns the yielded value (the argument Yield() was called with)
*/ */
const ReturnType& ReturnValue() const const ReturnType& ReturnValue() const
{ {
return m_retVal; return m_retVal;
} }
/** /**
* Function Running() * Function Running()
* *
* @return true, if the coroutine is active * @return true, if the coroutine is active
*/ */
bool Running() const bool Running() const
{ {
return m_running; return m_running;
} }
private: private:
static const int c_defaultStackSize = 2000000; // fixme: make configurable static const int c_defaultStackSize = 2000000; // fixme: make configurable
/* real entry point of the coroutine */ /* real entry point of the coroutine */
static void callerStub( intptr_t data ) static void callerStub( intptr_t data )
{ {
// get pointer to self // get pointer to self
COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( data ); COROUTINE<ReturnType, ArgType>* cor = reinterpret_cast<COROUTINE<ReturnType, ArgType>*>( data );
// call the coroutine method // call the coroutine method
cor->m_retVal = cor->m_func( *cor->m_args ); cor->m_retVal = cor->m_func( *cor->m_args );
cor->m_running = false; cor->m_running = false;
// go back to wherever we came from. // go back to wherever we came from.
boost::context::jump_fcontext( cor->m_self, cor->m_saved, 0 ); //reinterpret_cast<intptr_t>( this )); boost::context::jump_fcontext( cor->m_self, cor->m_saved, 0 ); //reinterpret_cast<intptr_t>( this ));
} }
template <typename T> struct strip_ref template <typename T> struct strip_ref
{ {
typedef T result; typedef T result;
}; };
template <typename T> struct strip_ref<T&> template <typename T> struct strip_ref<T&>
{ {
typedef T result; typedef T result;
}; };
DELEGATE<ReturnType, ArgType> m_func; DELEGATE<ReturnType, ArgType> m_func;
///< pointer to coroutine entry arguments. Stripped of references ///< pointer to coroutine entry arguments. Stripped of references
///< to avoid compiler errors. ///< to avoid compiler errors.
typename strip_ref<ArgType>::result* m_args; typename strip_ref<ArgType>::result* m_args;
ReturnType m_retVal; ReturnType m_retVal;
///< saved caller context ///< saved caller context
boost::context::fcontext_t* m_saved; boost::context::fcontext_t* m_saved;
///< saved coroutine context ///< saved coroutine context
boost::context::fcontext_t* m_self; boost::context::fcontext_t* m_self;
///< coroutine stack ///< coroutine stack
void* m_stack; void* m_stack;
size_t m_stackSize; size_t m_stackSize;
bool m_running; bool m_running;
}; };
#endif #endif
...@@ -28,38 +28,38 @@ ...@@ -28,38 +28,38 @@
/** /**
* class DELEGATE * 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. * Check delegate_example.cpp for a coding sample.
*/ */
template<class ReturnType, class Arg> template<class ReturnType, class Arg>
class DELEGATE { class DELEGATE {
public: public:
typedef ReturnType (DELEGATE<ReturnType, Arg>::*MemberPointer)( Arg ); typedef ReturnType (DELEGATE<ReturnType, Arg>::*MemberPointer)( Arg );
typedef ReturnType _ReturnType; typedef ReturnType _ReturnType;
typedef Arg _ArgType; typedef Arg _ArgType;
DELEGATE () DELEGATE ()
{ {
} }
template<class T> template<class T>
DELEGATE ( T* object, ReturnType (T::*ptr)( Arg ) ) DELEGATE ( T* object, ReturnType (T::*ptr)( Arg ) )
{ {
m_ptr = reinterpret_cast<MemberPointer>( ptr ); m_ptr = reinterpret_cast<MemberPointer>( ptr );
m_object = reinterpret_cast<void *>( object ); m_object = reinterpret_cast<void *>( object );
}; };
ReturnType operator()( Arg a ) const ReturnType operator()( Arg a ) const
{ {
DELEGATE<ReturnType, Arg> *casted = reinterpret_cast<DELEGATE<ReturnType, Arg>*>( m_object ); DELEGATE<ReturnType, Arg> *casted = reinterpret_cast<DELEGATE<ReturnType, Arg>*>( m_object );
return (casted->*m_ptr)(a); return (casted->*m_ptr)(a);
} }
private: private:
MemberPointer m_ptr; MemberPointer m_ptr;
void *m_object; void *m_object;
}; };
/** /**
...@@ -67,32 +67,32 @@ private: ...@@ -67,32 +67,32 @@ private:
* Same as DELEGATE, but with no arguments. * Same as DELEGATE, but with no arguments.
*/ */
template<class ReturnType> template<class ReturnType>
class DELEGATE0 { class DELEGATE0 {
public: public:
typedef ReturnType ( DELEGATE0<ReturnType>::*MemberPointer )(); typedef ReturnType ( DELEGATE0<ReturnType>::*MemberPointer )();
typedef ReturnType _ReturnType; typedef ReturnType _ReturnType;
DELEGATE0 () DELEGATE0 ()
{ {
} }
template<class T> template<class T>
DELEGATE0 ( T* object, ReturnType (T::*ptr)( ) ) DELEGATE0 ( T* object, ReturnType (T::*ptr)( ) )
{ {
m_ptr = reinterpret_cast<MemberPointer>( ptr ); m_ptr = reinterpret_cast<MemberPointer>( ptr );
m_object = reinterpret_cast<void*>( object ); m_object = reinterpret_cast<void*>( object );
}; };
ReturnType operator()( ) const ReturnType operator()( ) const
{ {
DELEGATE0<ReturnType>* casted = reinterpret_cast<DELEGATE0<ReturnType>*>( m_object ); DELEGATE0<ReturnType>* casted = reinterpret_cast<DELEGATE0<ReturnType>*>( m_object );
return ( casted->*m_ptr )(); return ( casted->*m_ptr )();
} }
private: private:
MemberPointer m_ptr; MemberPointer m_ptr;
void *m_object; void *m_object;
}; };
#endif #endif
...@@ -9,40 +9,40 @@ typedef COROUTINE<int, int> MyCoroutine; ...@@ -9,40 +9,40 @@ typedef COROUTINE<int, int> MyCoroutine;
class MyClass { class MyClass {
public: public:
int CountTo(int n) int CountTo(int n)
{ {
printf("%s: Coroutine says hi. I will count from 1 to %d and yield each value.\n", __FUNCTION__, 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++) for(int i = 1; i <= n; i++)
{ {
printf("%s: Yielding %d\n", __FUNCTION__, i); printf("%s: Yielding %d\n", __FUNCTION__, i);
cofunc.Yield(i); cofunc.Yield(i);
} }
} }
void Run() void Run()
{ {
cofunc = MyCoroutine (this, &MyClass::CountTo); cofunc = MyCoroutine (this, &MyClass::CountTo);
printf("%s: Calling coroutine that will count from 1 to 5.\n", __FUNCTION__); printf("%s: Calling coroutine that will count from 1 to 5.\n", __FUNCTION__);
cofunc.Call(5); cofunc.Call(5);
while (cofunc.Running()) while (cofunc.Running())
{ {
printf("%s: Got value: %d\n", __FUNCTION__, cofunc.ReturnValue()); printf("%s: Got value: %d\n", __FUNCTION__, cofunc.ReturnValue());
cofunc.Resume(); cofunc.Resume();
} }
printf("%s: Done!\n", __FUNCTION__); printf("%s: Done!\n", __FUNCTION__);
} }
MyCoroutine cofunc; MyCoroutine cofunc;
}; };
main() main()
{ {
MyClass obj; MyClass obj;
obj.Run(); obj.Run();
return 0; return 0;
} }
...@@ -7,29 +7,29 @@ using namespace std; ...@@ -7,29 +7,29 @@ using namespace std;
class MyClass { class MyClass {
public: public:
int MyMethod(const string &arg) int MyMethod(const string &arg)
{ {
printf("MyClass(this = %p)::MyMethod() called with string '%s', length %d\n", this, arg.c_str(), arg.length()); printf("MyClass(this = %p)::MyMethod() called with string '%s', length %d\n", this, arg.c_str(), arg.length());
return arg.length(); return arg.length();
} }
}; };
typedef DELEGATE<int, const string&> MyDelegate; typedef DELEGATE<int, const string&> MyDelegate;
main() main()
{ {
MyClass t1; MyClass t1;
MyClass t2; MyClass t2;
MyDelegate ptr1 (&t1, &MyClass::MyMethod); MyDelegate ptr1 (&t1, &MyClass::MyMethod);
MyDelegate ptr2 (&t2, &MyClass::MyMethod); MyDelegate ptr2 (&t2, &MyClass::MyMethod);
int retval1, retval2; int retval1, retval2;
retval1 = ptr1("apples"); retval1 = ptr1("apples");
retval2 = ptr2("cherries"); retval2 = ptr2("cherries");
printf("Object 1 returned %d, object 2 returned %d\n", retval1, retval2); printf("Object 1 returned %d, object 2 returned %d\n", retval1, retval2);
return 0; return 0;
} }
...@@ -59,128 +59,128 @@ typedef DELEGATE<int, TOOL_EVENT&> TOOL_STATE_FUNC; ...@@ -59,128 +59,128 @@ typedef DELEGATE<int, TOOL_EVENT&> TOOL_STATE_FUNC;
* Base abstract interface for all kinds of tools. * Base abstract interface for all kinds of tools.
*/ */
class TOOL_BASE class TOOL_BASE
{ {
public: public:
TOOL_BASE( TOOL_Type aType, TOOL_ID aId, const std::string& aName = std::string( "" ) ) : TOOL_BASE( TOOL_Type aType, TOOL_ID aId, const std::string& aName = std::string( "" ) ) :
m_type( aType ), m_type( aType ),
m_toolId( aId ), m_toolId( aId ),
m_toolName( aName ), m_toolName( aName ),
m_toolMgr( NULL ){}; m_toolMgr( NULL ){};
virtual ~TOOL_BASE() {}; virtual ~TOOL_BASE() {};
/** /**
* Function GetType() * Function GetType()
* Returns the type of the tool. * Returns the type of the tool.
* @return The type of the tool. * @return The type of the tool.
*/ */
TOOL_Type GetType() const TOOL_Type GetType() const
{ {
return m_type; return m_type;
} }
/** /**
* Function GetId() * Function GetId()
* Returns the unique identifier of the tool. The identifier is set by an instance of * Returns the unique identifier of the tool. The identifier is set by an instance of
* TOOL_MANAGER. * TOOL_MANAGER.
* @return Identifier of the tool. * @return Identifier of the tool.
*/ */
TOOL_ID GetId() const TOOL_ID GetId() const
{ {
return m_toolId; return m_toolId;
} }
/** /**
* Function GetName() * Function GetName()
* Returns the name of the tool. Tool names are expected to obey the format: * Returns the name of the tool. Tool names are expected to obey the format:
* application.ToolName (eg. pcbnew.InteractiveSelection). * application.ToolName (eg. pcbnew.InteractiveSelection).
* @return The name of the tool. * @return The name of the tool.
*/ */
const std::string& GetName() const const std::string& GetName() const
{ {
return m_toolName; return m_toolName;
} }
/** /**
* Function GetManager() * Function GetManager()
* Returns the instance of TOOL_MANAGER that takes care of the tool. * 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 * @return Instance of the TOOL_MANAGER. If there is no TOOL_MANAGER associated, it returns
* NULL. * NULL.
*/ */
TOOL_MANAGER* GetManager() const TOOL_MANAGER* GetManager() const
{ {
return m_toolMgr; return m_toolMgr;
} }
protected: protected:
friend class TOOL_MANAGER; friend class TOOL_MANAGER;
/** /**
* Function attachManager() * Function attachManager()
* *
* Sets the TOOL_MANAGER the tool will belong to. * Sets the TOOL_MANAGER the tool will belong to.
* Called by TOOL_MANAGER::RegisterTool() * Called by TOOL_MANAGER::RegisterTool()
*/ */
void attachManager( TOOL_MANAGER* aManager ); void attachManager( TOOL_MANAGER* aManager );
/** /**
* Function getView() * Function getView()
* *
* Returns the instance of VIEW object used in the application. It allows tools to draw. * Returns the instance of VIEW object used in the application. It allows tools to draw.
* @return The instance of VIEW. * @return The instance of VIEW.
*/ */
KiGfx::VIEW* getView() const; KiGfx::VIEW* getView() const;
/** /**
* Function getViewControls() * Function getViewControls()
* *
* Returns the instance of VIEW_CONTROLS object used in the application. It allows tools to * 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.) * read & modify user input and its settings (eg. show cursor, enable snapping to grid, etc.)
* @return The instance of VIEW_CONTROLS. * @return The instance of VIEW_CONTROLS.
*/ */
KiGfx::VIEW_CONTROLS* getViewControls() const; KiGfx::VIEW_CONTROLS* getViewControls() const;
/** /**
* Function getEditFrame() * Function getEditFrame()
* *
* Returns the application window object, casted to requested user type. * Returns the application window object, casted to requested user type.
*/ */
template<typename T> template<typename T>
T* getEditFrame() const T* getEditFrame() const
{ {
return static_cast<T*>( getEditFrameInt() ); return static_cast<T*>( getEditFrameInt() );
} }
/** /**
* Function getModel() * Function getModel()
* *
* Returns the model object if it matches the requested type. * Returns the model object if it matches the requested type.
*/ */
template<typename T> template<typename T>
T* getModel( KICAD_T modelType ) const T* getModel( KICAD_T modelType ) const
{ {
EDA_ITEM* m = getModelInt(); EDA_ITEM* m = getModelInt();
return static_cast<T*>( m ); return static_cast<T*>( m );
} }
///> Stores the type of the tool. ///> Stores the type of the tool.
TOOL_Type m_type; TOOL_Type m_type;
///> Unique identifier for the tool, assigned by a TOOL_MANAGER instance. ///> Unique identifier for the tool, assigned by a TOOL_MANAGER instance.
TOOL_ID m_toolId; TOOL_ID m_toolId;
///> Name of the tool. Names are expected to obey the format application.ToolName ///> Name of the tool. Names are expected to obey the format application.ToolName
///> (eg. pcbnew.InteractiveSelection). ///> (eg. pcbnew.InteractiveSelection).
std::string m_toolName; std::string m_toolName;
TOOL_MANAGER* m_toolMgr; TOOL_MANAGER* m_toolMgr;
private: private:
// hide the implementation to avoid spreading half of // hide the implementation to avoid spreading half of
// kicad and wxWidgets headers to the tools that may not need them at all! // kicad and wxWidgets headers to the tools that may not need them at all!
EDA_ITEM* getModelInt() const; EDA_ITEM* getModelInt() const;
wxWindow* getEditFrameInt() const; wxWindow* getEditFrameInt() const;
}; };
#endif #endif
...@@ -33,12 +33,12 @@ class TOOL_MANAGER; ...@@ -33,12 +33,12 @@ class TOOL_MANAGER;
class PCB_BASE_FRAME; class PCB_BASE_FRAME;
namespace KiGfx { namespace KiGfx {
class VIEW; class VIEW;
}; };
/** /**
* Class TOOL_DISPATCHER * Class TOOL_DISPATCHER
* *
* - takes wx events, * - takes wx events,
* - fixes all wx quirks (mouse warping, panning, ordering problems, etc) * - fixes all wx quirks (mouse warping, panning, ordering problems, etc)
* - translates coordinates to world space * - translates coordinates to world space
......
...@@ -42,63 +42,63 @@ class TOOL_MANAGER; ...@@ -42,63 +42,63 @@ class TOOL_MANAGER;
*/ */
enum TOOL_EventCategory enum TOOL_EventCategory
{ {
TC_None = 0x00, TC_None = 0x00,
TC_Mouse = 0x01, TC_Mouse = 0x01,
TC_Keyboard = 0x02, TC_Keyboard = 0x02,
TC_Command = 0x04, TC_Command = 0x04,
TC_Message = 0x08, TC_Message = 0x08,
TC_View = 0x10, TC_View = 0x10,
TC_Any = 0xffffffff TC_Any = 0xffffffff
}; };
enum TOOL_Actions enum TOOL_Actions
{ {
// UI input events // UI input events
TA_None = 0x0000, TA_None = 0x0000,
TA_MouseClick = 0x0001, TA_MouseClick = 0x0001,
TA_MouseUp = 0x0002, TA_MouseUp = 0x0002,
TA_MouseDown = 0x0004, TA_MouseDown = 0x0004,
TA_MouseDrag = 0x0008, TA_MouseDrag = 0x0008,
TA_MouseMotion = 0x0010, TA_MouseMotion = 0x0010,
TA_MouseWheel = 0x0020, TA_MouseWheel = 0x0020,
TA_Mouse = 0x003f, TA_Mouse = 0x003f,
TA_KeyUp = 0x0040, TA_KeyUp = 0x0040,
TA_KeyDown = 0x0080, TA_KeyDown = 0x0080,
TA_Keyboard = TA_KeyUp | TA_KeyDown, TA_Keyboard = TA_KeyUp | TA_KeyDown,
// View related events // View related events
TA_ViewRefresh = 0x0100, TA_ViewRefresh = 0x0100,
TA_ViewZoom = 0x0200, TA_ViewZoom = 0x0200,
TA_ViewPan = 0x0400, TA_ViewPan = 0x0400,
TA_ViewDirty = 0x0800, TA_ViewDirty = 0x0800,
TA_ChangeLayer = 0x1000, TA_ChangeLayer = 0x1000,
// Tool cancel event. Issued automagically when the user hits escape or selects End Tool from // Tool cancel event. Issued automagically when the user hits escape or selects End Tool from
// the context menu. // the context menu.
TA_CancelTool = 0x2000, TA_CancelTool = 0x2000,
// Context menu update. Issued whenever context menu is open and the user hovers the mouse // 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 // over one of choices. Used in dynamic highligting in disambiguation menu
TA_ContextMenuUpdate = 0x4000, TA_ContextMenuUpdate = 0x4000,
// Context menu choice. Sent if the user picked something from the context menu or // Context menu choice. Sent if the user picked something from the context menu or
// closed it without selecting anything. // closed it without selecting anything.
TA_ContextMenuChoice = 0x8000, TA_ContextMenuChoice = 0x8000,
// Tool action (allows to control tools) // Tool action (allows to control tools)
TA_Action = 0x10000, TA_Action = 0x10000,
TA_Any = 0xffffffff TA_Any = 0xffffffff
}; };
enum TOOL_MouseButtons enum TOOL_MouseButtons
{ {
MB_None = 0x0, MB_None = 0x0,
MB_Left = 0x1, MB_Left = 0x1,
MB_Right = 0x2, MB_Right = 0x2,
MB_Middle = 0x4, MB_Middle = 0x4,
MB_ButtonMask = MB_Left | MB_Right | MB_Middle, MB_ButtonMask = MB_Left | MB_Right | MB_Middle,
MB_Any = 0xffffffff MB_Any = 0xffffffff
}; };
enum TOOL_Modifiers enum TOOL_Modifiers
...@@ -120,14 +120,14 @@ enum TOOL_ActionScope ...@@ -120,14 +120,14 @@ enum TOOL_ActionScope
/// Defines when a context menu is opened. /// Defines when a context menu is opened.
enum CONTEXT_MENU_TRIGGER enum CONTEXT_MENU_TRIGGER
{ {
CMENU_BUTTON = 0, // On the right button CMENU_BUTTON = 0, // On the right button
CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContextMenu) CMENU_NOW, // Right now (after TOOL_INTERACTIVE::SetContextMenu)
CMENU_OFF // Never CMENU_OFF // Never
}; };
/** /**
* Class TOOL_EVENT * Class TOOL_EVENT
* *
* Generic, UI-independent tool event. * Generic, UI-independent tool event.
*/ */
class TOOL_EVENT class TOOL_EVENT
...@@ -359,9 +359,9 @@ private: ...@@ -359,9 +359,9 @@ private:
typedef boost::optional<TOOL_EVENT> OPT_TOOL_EVENT; typedef boost::optional<TOOL_EVENT> OPT_TOOL_EVENT;
/** /**
* Class TOOL_EVENT_LIST * Class TOOL_EVENT_LIST
* *
* A list of TOOL_EVENTs, with overloaded || operators allowing for * A list of TOOL_EVENTs, with overloaded || operators allowing for
* concatenating TOOL_EVENTs with little code. * concatenating TOOL_EVENTs with little code.
*/ */
...@@ -473,20 +473,20 @@ private: ...@@ -473,20 +473,20 @@ private:
inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& a, const TOOL_EVENT& b ) 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( a );
l.Add( b ); l.Add( b );
return l; return l;
} }
inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& a, const TOOL_EVENT_LIST& b ) inline const TOOL_EVENT_LIST operator||( const TOOL_EVENT& a, const TOOL_EVENT_LIST& b )
{ {
TOOL_EVENT_LIST l( b ); TOOL_EVENT_LIST l( b );
l.Add( a ); l.Add( a );
return l; return l;
} }
#endif #endif
...@@ -39,23 +39,23 @@ public: ...@@ -39,23 +39,23 @@ public:
* Constructor * Constructor
* *
* Creates a tool with given id & name. The name must be unique. */ * Creates a tool with given id & name. The name must be unique. */
TOOL_INTERACTIVE( TOOL_ID aId, const std::string& aName ); TOOL_INTERACTIVE( TOOL_ID aId, const std::string& aName );
/** /**
* Constructor * Constructor
* *
* Creates a tool with given name. The name must be unique. */ * Creates a tool with given name. The name must be unique. */
TOOL_INTERACTIVE( const std::string& aName ); TOOL_INTERACTIVE( const std::string& aName );
virtual ~TOOL_INTERACTIVE(); virtual ~TOOL_INTERACTIVE();
/** /**
* Function Reset() * Function Reset()
* Brings the tool to a known, initial state. If the tool claimed anything from * 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. * the model or the view, it must release it when its reset.
*/ */
virtual void Reset() = 0; virtual void Reset() = 0;
/** /**
* Function Init() * Function Init()
* Init() is called once upon a registration of the tool. * Init() is called once upon a registration of the tool.
* *
...@@ -66,58 +66,58 @@ public: ...@@ -66,58 +66,58 @@ public:
return true; return true;
} }
/** /**
* Function SetContextMenu() * Function SetContextMenu()
* *
* Assigns a context menu and tells when it should be activated. * Assigns a context menu and tells when it should be activated.
* @param aMenu is the menu to be assigned. * @param aMenu is the menu to be assigned.
* @param aTrigger determines conditions upon which the context menu is activated. * @param aTrigger determines conditions upon which the context menu is activated.
*/ */
void SetContextMenu( CONTEXT_MENU* aMenu, CONTEXT_MENU_TRIGGER aTrigger = CMENU_BUTTON ); void SetContextMenu( CONTEXT_MENU* aMenu, CONTEXT_MENU_TRIGGER aTrigger = CMENU_BUTTON );
/** /**
* Function Go() * Function Go()
* *
* Defines which state (aStateFunc) to go when a certain event arrives (aConditions). * Defines which state (aStateFunc) to go when a certain event arrives (aConditions).
* No conditions means any event. * No conditions means any event.
*/ */
template<class T> template<class T>
void Go( int (T::*aStateFunc)( TOOL_EVENT& ), void Go( int (T::*aStateFunc)( TOOL_EVENT& ),
const TOOL_EVENT_LIST& aConditions = TOOL_EVENT( TC_Any, TA_Any ) ); const TOOL_EVENT_LIST& aConditions = TOOL_EVENT( TC_Any, TA_Any ) );
/** /**
* Function Wait() * Function Wait()
* *
* Suspends execution of the tool until an event specified in aEventList arrives. * Suspends execution of the tool until an event specified in aEventList arrives.
* No parameters means waiting for any event. * No parameters means waiting for any event.
*/ */
OPT_TOOL_EVENT Wait( const TOOL_EVENT_LIST& aEventList = TOOL_EVENT ( TC_Any, TA_Any ) ); 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 */ /** functions below are not yet implemented - their interface may change */
/*template<class Parameters, class ReturnValue> /*template<class Parameters, class ReturnValue>
bool InvokeTool( const std::string& aToolName, const Parameters& parameters, bool InvokeTool( const std::string& aToolName, const Parameters& parameters,
ReturnValue& returnValue ); ReturnValue& returnValue );
template<class Parameters, class ReturnValue> template<class Parameters, class ReturnValue>
bool InvokeWindow( const std::string& aWindowName, const Parameters& parameters, bool InvokeWindow( const std::string& aWindowName, const Parameters& parameters,
ReturnValue& returnValue ); ReturnValue& returnValue );
template<class T> template<class T>
void Yield( const T& returnValue );*/ void Yield( const T& returnValue );*/
protected: protected:
/* helper functions for constructing events for Wait() and Go() with less typing */ /* helper functions for constructing events for Wait() and Go() with less typing */
const TOOL_EVENT evActivate( std::string aToolName = "" ); const TOOL_EVENT evActivate( std::string aToolName = "" );
const TOOL_EVENT evCommand( int aCommandId = -1 ); const TOOL_EVENT evCommand( int aCommandId = -1 );
const TOOL_EVENT evCommand( std::string aCommandStr = "" ); const TOOL_EVENT evCommand( std::string aCommandStr = "" );
const TOOL_EVENT evMotion(); const TOOL_EVENT evMotion();
const TOOL_EVENT evClick( int aButton = MB_Any ); const TOOL_EVENT evClick( int aButton = MB_Any );
const TOOL_EVENT evDrag( int aButton = MB_Any ); const TOOL_EVENT evDrag( int aButton = MB_Any );
const TOOL_EVENT evButtonUp( int aButton = MB_Any ); const TOOL_EVENT evButtonUp( int aButton = MB_Any );
const TOOL_EVENT evButtonDown(int aButton = MB_Any ); const TOOL_EVENT evButtonDown(int aButton = MB_Any );
private: 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 // hide TOOL_MANAGER implementation
...@@ -125,8 +125,8 @@ template<class T> ...@@ -125,8 +125,8 @@ template<class T>
void TOOL_INTERACTIVE::Go( int (T::*aStateFunc)( TOOL_EVENT& ), void TOOL_INTERACTIVE::Go( int (T::*aStateFunc)( TOOL_EVENT& ),
const TOOL_EVENT_LIST& aConditions ) const TOOL_EVENT_LIST& aConditions )
{ {
TOOL_STATE_FUNC sptr( static_cast<T*>( this ), aStateFunc ); TOOL_STATE_FUNC sptr( static_cast<T*>( this ), aStateFunc );
goInternal( sptr, aConditions ); goInternal( sptr, aConditions );
} }
#endif #endif
...@@ -122,7 +122,7 @@ public: ...@@ -122,7 +122,7 @@ public:
virtual const VECTOR2D GetCursorPosition() const = 0; virtual const VECTOR2D GetCursorPosition() const = 0;
/** /**
* Function ForceCursorPosition() * Function ForceCursorPosition()
* Places the cursor immediately at a given point. Mouse movement is ignored. * Places the cursor immediately at a given point. Mouse movement is ignored.
* @param aEnabled enable forced cursor position * @param aEnabled enable forced cursor position
......
File mode changed from 100755 to 100644
...@@ -279,7 +279,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer ) ...@@ -279,7 +279,7 @@ void PCB_PAINTER::draw( const TRACK* aTrack, int aLayer )
NETINFO_ITEM* net = ( (BOARD*) aTrack->GetParent() )->FindNet( netNumber ); NETINFO_ITEM* net = ( (BOARD*) aTrack->GetParent() )->FindNet( netNumber );
if( !net ) if( !net )
return; return;
std::string netName = std::string( net->GetShortNetname().mb_str() ); std::string netName = std::string( net->GetShortNetname().mb_str() );
VECTOR2D textPosition = start + line / 2.0; // center of the track VECTOR2D textPosition = start + line / 2.0; // center of the track
double textOrientation = -atan( line.y / line.x ); double textOrientation = -atan( line.y / line.x );
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
/** /**
* Class PNS_ITEMSET * 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. * layers, etc.
**/ **/
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
/** /**
* Class PNS_JOINT * 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. * 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. * the items.
**/ **/
class PNS_JOINT : public PNS_ITEM class PNS_JOINT : public PNS_ITEM
...@@ -53,8 +53,8 @@ public: ...@@ -53,8 +53,8 @@ public:
PNS_JOINT() : PNS_JOINT() :
PNS_ITEM( JOINT ) {} PNS_ITEM( JOINT ) {}
PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers, PNS_JOINT( const VECTOR2I& aPos, const PNS_LAYERSET& aLayers,
int aNet = -1 ) : int aNet = -1 ) :
PNS_ITEM( JOINT ) PNS_ITEM( JOINT )
{ {
m_tag.pos = aPos; m_tag.pos = aPos;
...@@ -78,14 +78,14 @@ public: ...@@ -78,14 +78,14 @@ public:
return NULL; 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. /// segments of the same net, on the same layer.
bool IsLineCorner() const bool IsLineCorner() const
{ {
if( m_linkedItems.size() != 2 ) if( m_linkedItems.size() != 2 )
return false; return false;
if( m_linkedItems[0]->GetKind() != SEGMENT || if( m_linkedItems[0]->GetKind() != SEGMENT ||
m_linkedItems[1]->GetKind() != SEGMENT ) m_linkedItems[1]->GetKind() != SEGMENT )
return false; return false;
...@@ -99,7 +99,7 @@ public: ...@@ -99,7 +99,7 @@ public:
///> Links the joint to a given board item (when it's added to the PNS_NODE) ///> Links the joint to a given board item (when it's added to the PNS_NODE)
void Link( PNS_ITEM* aItem ) 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 ); m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() ) if( f != m_linkedItems.end() )
...@@ -112,7 +112,7 @@ public: ...@@ -112,7 +112,7 @@ public:
///> Returns true if the joint became dangling after unlinking. ///> Returns true if the joint became dangling after unlinking.
bool Unlink( PNS_ITEM* aItem ) 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 ); m_linkedItems.end(), aItem );
if( f != m_linkedItems.end() ) if( f != m_linkedItems.end() )
...@@ -142,7 +142,7 @@ public: ...@@ -142,7 +142,7 @@ public:
{ {
int n = 0; int n = 0;
for( LinkedItems::const_iterator i = m_linkedItems.begin(); for( LinkedItems::const_iterator i = m_linkedItems.begin();
i != m_linkedItems.end(); ++i ) i != m_linkedItems.end(); ++i )
if( (*i)->GetKind() & aMask ) if( (*i)->GetKind() & aMask )
n++; n++;
...@@ -172,7 +172,7 @@ public: ...@@ -172,7 +172,7 @@ public:
bool Overlaps( const PNS_JOINT& rhs ) const 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 ); m_tag.net == rhs.m_tag.net && m_layers.Overlaps( rhs.m_layers );
} }
...@@ -186,7 +186,7 @@ private: ...@@ -186,7 +186,7 @@ private:
// hash function & comparison operator for boost::unordered_map<> // 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 ) PNS_JOINT::HashTag const& p2 )
{ {
return p1.pos == p2.pos && p1.net == p2.net; return p1.pos == p2.pos && p1.net == p2.net;
......
...@@ -434,7 +434,7 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle, ...@@ -434,7 +434,7 @@ void PNS_LINE::NewWalkaround( const SHAPE_LINE_CHAIN& aObstacle,
path.Append( l_hull.CPoint( j ) ); path.Append( l_hull.CPoint( j ) );
li = l_orig.Find( 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]) ) outside[li + 1]) )
break; break;
} }
...@@ -514,7 +514,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line, ...@@ -514,7 +514,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line,
{ {
index_l = (reverse ? sc - 1 - i : i); index_l = (reverse ? sc - 1 - i : i);
ip = s.a; 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 ); is_vertex ? "vertex" : "edge", index_o );
return true; return true;
} }
...@@ -523,7 +523,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line, ...@@ -523,7 +523,7 @@ bool PNS_LINE::walkScan( const SHAPE_LINE_CHAIN& line,
{ {
index_l = (reverse ? sc - 1 - i - 1 : i + 1); index_l = (reverse ? sc - 1 - i - 1 : i + 1);
ip = s.b; 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 ); is_vertex ? "vertex" : "edge", index_o );
return true; return true;
} }
...@@ -562,7 +562,7 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN obstacle, ...@@ -562,7 +562,7 @@ bool PNS_LINE::Walkaround( SHAPE_LINE_CHAIN obstacle,
if( line.SegmentCount() < 1 ) if( line.SegmentCount() < 1 )
return false; return false;
if( obstacle.PointInside( line.CPoint( 0 ) ) || if( obstacle.PointInside( line.CPoint( 0 ) ) ||
obstacle.PointInside( line.CPoint( -1 ) ) ) obstacle.PointInside( line.CPoint( -1 ) ) )
return false; return false;
...@@ -714,7 +714,7 @@ bool PNS_LINE::Is45Degree() ...@@ -714,7 +714,7 @@ bool PNS_LINE::Is45Degree()
const SEG& s = m_line.CSegment( i ); const SEG& s = m_line.CSegment( i );
double angle = 180.0 / M_PI * 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 ); (double) s.b.x - (double) s.a.x );
if( angle < 0 ) if( angle < 0 )
......
...@@ -38,17 +38,17 @@ class PNS_VIA; ...@@ -38,17 +38,17 @@ class PNS_VIA;
/** /**
* Class PNS_LINE * Class PNS_LINE
* *
* Represents a track on a PCB, connecting two non-trivial joints (that is, * Represents a track on a PCB, connecting two non-trivial joints (that is,
* vias, pads, junctions between multiple traces or two traces different widths * 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). * 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 * Instead, they are assembled on-the-fly, based on a via/pad/segment that
* belongs/begins them. * belongs/begins them.
* *
* PNS_LINEs can be either loose (consisting of segments that do not belong to * 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 * any PNS_NODE) or owned (with segments taken from a PNS_NODE) - these are
* returned by PNS_NODE::AssembleLine and friends. * 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. * dragging/force propagation stuff.
*/ */
...@@ -141,7 +141,7 @@ public: ...@@ -141,7 +141,7 @@ public:
m_segmentRefs->push_back( aSeg ); 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) ///> line (or NULL if the line is loose)
LinkedSegments* GetLinkedSegments() LinkedSegments* GetLinkedSegments()
{ {
...@@ -157,7 +157,7 @@ public: ...@@ -157,7 +157,7 @@ public:
aSeg ) != m_segmentRefs->end(); 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. ///> along, to avoid collision.
const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const; const PNS_LINE ClipToNearestObstacle( PNS_NODE* aNode ) const;
...@@ -168,7 +168,7 @@ public: ...@@ -168,7 +168,7 @@ public:
///> Returns the number of corners of angles specified by mask aAngles. ///> Returns the number of corners of angles specified by mask aAngles.
int CountCorners( int 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). ///> of an obstacle object (aObstacle).
///> aPrePath = path from origin to the obstacle ///> aPrePath = path from origin to the obstacle
///> aWalkaroundPath = path around the obstacle ///> aWalkaroundPath = path around the obstacle
......
...@@ -63,7 +63,7 @@ void PNS_LINE_PLACER::ApplySettings( const PNS_ROUTING_SETTINGS& aSettings ) ...@@ -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 ) int aWidth, int aLayer )
{ {
m_direction = m_initial_direction; m_direction = m_initial_direction;
...@@ -177,14 +177,14 @@ bool PNS_LINE_PLACER::handlePullback() ...@@ -177,14 +177,14 @@ bool PNS_LINE_PLACER::handlePullback()
DIRECTION_45 last_tail( tail.Segment( -1 ) ); DIRECTION_45 last_tail( tail.Segment( -1 ) );
DIRECTION_45::AngleType angle = first_head.Angle( last_tail ); 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. // head goes in different one.
bool pullback_1 = false; // (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head); 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 // extremities form an acute or right angle, reduce the tail by one segment
// (and hope that further iterations) will result with a cleaner trace // (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); angle == DIRECTION_45::ANG_ACUTE);
if( pullback_1 || pullback_2 ) if( pullback_1 || pullback_2 )
...@@ -197,7 +197,7 @@ bool PNS_LINE_PLACER::handlePullback() ...@@ -197,7 +197,7 @@ bool PNS_LINE_PLACER::handlePullback()
n % last_tail.Format().c_str() % first_head.Format().c_str() ); n % last_tail.Format().c_str() % first_head.Format().c_str() );
// erase the last point in the tail, hoping that the next iteration will // 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. // current direction.
if( n < 2 ) if( n < 2 )
tail.Clear(); // don't leave a single-point tail tail.Clear(); // don't leave a single-point tail
...@@ -239,7 +239,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd ) ...@@ -239,7 +239,7 @@ bool PNS_LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
const SEG s = tail.CSegment( i ); const SEG s = tail.CSegment( i );
DIRECTION_45 dir( s ); 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 // the direction of the segment to be replaced
SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.a, aEnd ); SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.a, aEnd );
...@@ -289,7 +289,7 @@ bool PNS_LINE_PLACER::mergeHead() ...@@ -289,7 +289,7 @@ bool PNS_LINE_PLACER::mergeHead()
SHAPE_LINE_CHAIN& head = m_head.GetLine(); SHAPE_LINE_CHAIN& head = m_head.GetLine();
SHAPE_LINE_CHAIN& tail = m_tail.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_HALF_FULL |
DIRECTION_45::ANG_UNDEFINED; DIRECTION_45::ANG_UNDEFINED;
...@@ -366,7 +366,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) ...@@ -366,7 +366,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead )
if( v.PushoutForce( m_shove->GetCurrentNode(), lead, force, true, 20 ) ) 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( 0 ),
aHead.GetCLine().CPoint( -1 ) + force ); aHead.GetCLine().CPoint( -1 ) + force );
aHead = PNS_LINE( aHead, line ); aHead = PNS_LINE( aHead, line );
...@@ -379,7 +379,7 @@ bool PNS_LINE_PLACER::handleViaPlacement( PNS_LINE& aHead ) ...@@ -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 ) bool aCwWalkaround )
{ {
// STAGE 1: route a simple two-segment trace between m_p_start and aP... // STAGE 1: route a simple two-segment trace between m_p_start and aP...
...@@ -543,7 +543,7 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition() ...@@ -543,7 +543,7 @@ bool PNS_LINE_PLACER::optimizeTailHeadTransition()
PNS_LINE new_head( m_tail, opt_line ); PNS_LINE new_head( m_tail, opt_line );
// and see if it could be made simpler by merging obtuse/collnear segments. // 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 // the optimized line
// if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS)) // if(PNS_OPTIMIZER::Optimize(&new_head, PNS_OPTIMIZER::MERGE_SEGMENTS))
......
...@@ -39,7 +39,7 @@ class PNS_ROUTER_BASE; ...@@ -39,7 +39,7 @@ class PNS_ROUTER_BASE;
/** /**
* Class PNS_LINE_PLACER * 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. * algorithms when needed.
*/ */
...@@ -63,9 +63,9 @@ public: ...@@ -63,9 +63,9 @@ public:
/** /**
* Function Route() * Function Route()
* *
* Re-routes the current track to point aP. Returns true, when routing has * 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 * 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() * if the trace was stuck somewhere on the way. May call routeStep()
* repetitively due to mouse smoothing. * repetitively due to mouse smoothing.
* @param aP ending point of current route. * @param aP ending point of current route.
* @return true, if the routing is complete. * @return true, if the routing is complete.
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
///> Returns the "head" of the line being placed, that is the volatile part ///> Returns the "head" of the line being placed, that is the volatile part
///> that has not been settled yet ///> that has not been settled yet
const PNS_LINE& GetHead() const { return m_head; } 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) ///> fixed already (follow mouse mode only)
const PNS_LINE& GetTail() const { return m_tail; } const PNS_LINE& GetTail() const { return m_tail; }
...@@ -99,9 +99,9 @@ public: ...@@ -99,9 +99,9 @@ public:
return m_p_start; 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 ///> 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 ); PNS_NODE::ItemVector& aAdded );
///> Toggles the current posture (straight/diagonal) of the trace head. ///> Toggles the current posture (straight/diagonal) of the trace head.
...@@ -114,30 +114,30 @@ private: ...@@ -114,30 +114,30 @@ private:
static const double m_shoveLengthThreshold = 1.7; static const double m_shoveLengthThreshold = 1.7;
bool handleViaPlacement( PNS_LINE& aHead ); bool handleViaPlacement( PNS_LINE& aHead );
/** /**
* Function checkObtusity() * 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). * (in 45-degree regime).
* @return true, if angle (a, b) is obtuse * @return true, if angle (a, b) is obtuse
*/ */
bool checkObtusity( const SEG& a, const SEG& b ) const; bool checkObtusity( const SEG& a, const SEG& b ) const;
/** /**
* Function handleSelfIntersections() * 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 * tail up to the intersecting segment and fixes the head direction to match
* the last segment before the cut. * the last segment before the cut.
* @return true if the line has been changed. * @return true if the line has been changed.
*/ */
bool handleSelfIntersections(); bool handleSelfIntersections();
/** /**
* Function handlePullback() * 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. * wrs to the current tail direction.
* @return true if the line has been changed. * @return true if the line has been changed.
*/ */
...@@ -146,7 +146,7 @@ private: ...@@ -146,7 +146,7 @@ private:
/** /**
* Function mergeHead() * 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. * conditions are met.
* @return true, if the line has been changed. * @return true, if the line has been changed.
*/ */
...@@ -155,20 +155,20 @@ private: ...@@ -155,20 +155,20 @@ private:
/** /**
* Function reduceTail() * Function reduceTail()
* *
* Attempts to reduce the numer of segments in the tail by trying to replace a * 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 * certain number of latest tail segments with a direct trace leading to aEnd
* that does not collide with anything. * that does not collide with anything.
* @param aEnd: current routing destination point. * @param aEnd: current routing destination point.
* @return true if the line has been changed. * @return true if the line has been changed.
*/ */
bool reduceTail( const VECTOR2I& aEnd ); bool reduceTail( const VECTOR2I& aEnd );
void fixHeadPosture(); void fixHeadPosture();
/** /**
* Function optimizeTailHeadTransition() * 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. * merging obtuse/collinear segments.
* @return true, if the line has been changed. * @return true, if the line has been changed.
*/ */
...@@ -177,12 +177,12 @@ private: ...@@ -177,12 +177,12 @@ private:
/** /**
* Function routeHead() * Function routeHead()
* *
* Computes the head trace between the current start point (m_p_start) and * 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 * point aP, starting with direction defined in m_direction. The trace walks
* around all colliding solid or non-movable items. Movable segments are * around all colliding solid or non-movable items. Movable segments are
* ignored, as they'll be handled later by the shove algorithm. * 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 ); bool aCwWalkaround = true );
/** /**
...@@ -197,7 +197,7 @@ private: ...@@ -197,7 +197,7 @@ private:
///> routing mode (walkaround, shove, etc.) ///> routing mode (walkaround, shove, etc.)
PNS_MODE m_mode; 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 ///> as the cursor moves
bool m_follow_mouse; bool m_follow_mouse;
......
...@@ -71,7 +71,7 @@ PNS_NODE::~PNS_NODE() ...@@ -71,7 +71,7 @@ PNS_NODE::~PNS_NODE()
allocNodes.erase( this ); 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 ) i != m_index->end(); ++i )
if( (*i)->BelongsTo( this ) ) if( (*i)->BelongsTo( this ) )
delete *i; delete *i;
...@@ -111,14 +111,14 @@ PNS_NODE* PNS_NODE::Branch() ...@@ -111,14 +111,14 @@ PNS_NODE* PNS_NODE::Branch()
child->m_clearanceFunctor = m_clearanceFunctor; child->m_clearanceFunctor = m_clearanceFunctor;
child->m_root = isRoot() ? this : m_root; child->m_root = isRoot() ? this : m_root;
// immmediate offspring of the root branch needs not copy anything. // immmediate offspring of the root branch needs not copy anything.
// For the rest, deep-copy joints, overridden item map and pointers // For the rest, deep-copy joints, overridden item map and pointers
// to stored items. // to stored items.
if( !isRoot() ) if( !isRoot() )
{ {
JointMap::iterator j; 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 ) i != m_index->end(); ++i )
child->m_index->Add( *i ); child->m_index->Add( *i );
...@@ -150,7 +150,7 @@ void PNS_NODE::unlinkParent() ...@@ -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 // the actual collision refining
struct PNS_NODE::obstacleVisitor struct PNS_NODE::obstacleVisitor
{ {
...@@ -200,7 +200,7 @@ struct PNS_NODE::obstacleVisitor ...@@ -200,7 +200,7 @@ struct PNS_NODE::obstacleVisitor
if( !aItem->OfKind( m_kindMask ) ) if( !aItem->OfKind( m_kindMask ) )
return true; 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. // (possibily modified) version of this item.
if( m_override && m_override->overrides( aItem ) ) if( m_override && m_override->overrides( aItem ) )
return true; return true;
...@@ -428,8 +428,8 @@ struct hitVisitor ...@@ -428,8 +428,8 @@ struct hitVisitor
const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint )
{ {
PNS_ITEMSET items; PNS_ITEMSET items;
// fixme: we treat a point as an infinitely small circle - this is inefficient. // fixme: we treat a point as an infinitely small circle - this is inefficient.
SHAPE_CIRCLE s( aPoint, 0 ); SHAPE_CIRCLE s( aPoint, 0 );
hitVisitor visitor( items, aPoint, this ); hitVisitor visitor( items, aPoint, this );
m_index->Query( &s, m_maxClearance, visitor ); m_index->Query( &s, m_maxClearance, visitor );
...@@ -537,12 +537,12 @@ void PNS_NODE::Add( PNS_ITEM* aItem ) ...@@ -537,12 +537,12 @@ void PNS_NODE::Add( PNS_ITEM* aItem )
void PNS_NODE::doRemove( 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 // mark it as overridden, but do not remove
if( aItem->BelongsTo( m_root ) && !isRoot() ) if( aItem->BelongsTo( m_root ) && !isRoot() )
m_override.insert( aItem ); 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 // or the root itself and we are the root: remove from the index
else if( !aItem->BelongsTo( m_root ) || isRoot() ) else if( !aItem->BelongsTo( m_root ) || isRoot() )
m_index->Remove( aItem ); m_index->Remove( aItem );
...@@ -948,7 +948,7 @@ void PNS_NODE::Commit( PNS_NODE* aNode ) ...@@ -948,7 +948,7 @@ void PNS_NODE::Commit( PNS_NODE* aNode )
BOOST_FOREACH( PNS_ITEM * item, aNode->m_override ) BOOST_FOREACH( PNS_ITEM * item, aNode->m_override )
Remove( item ); 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 ) i != aNode->m_index->end(); ++i )
Add( *i ); Add( *i );
......
...@@ -79,13 +79,13 @@ struct PNS_OBSTACLE ...@@ -79,13 +79,13 @@ struct PNS_OBSTACLE
/** /**
* Class PNS_NODE * 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. * hierarchical and indexed way.
* Features: * Features:
* - spatial-indexed container for PCB item shapes * - spatial-indexed container for PCB item shapes
* - collision search (with clearance checking) * - collision search (with clearance checking)
* - assembly of lines connecting joints, finding loops and unique paths * - 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) * springback)
**/ **/
...@@ -145,11 +145,11 @@ public: ...@@ -145,11 +145,11 @@ public:
void Remove( PNS_ITEM* aItem ); void Remove( PNS_ITEM* aItem );
void Replace( PNS_ITEM* aOldItem, PNS_ITEM* aNewItem ); 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. ///> any branches in use, their parents must NOT be deleted.
PNS_NODE* Branch(); 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. ///> segment aSeg belongs to.
PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg, PNS_LINE* AssembleLine( PNS_SEGMENT* aSeg,
const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() ); const OptJoint& a = OptJoint(), const OptJoint& b = OptJoint() );
...@@ -175,15 +175,15 @@ public: ...@@ -175,15 +175,15 @@ public:
const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet ); const OptJoint FindJoint( const VECTOR2I& aPos, int aLayer, int aNet );
///> finds all linest between a pair of joints. Used by the loop removal engine. ///> 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 ); std::vector<PNS_LINE*>& aLines );
///> finds the joints corresponding to the ends of line aLine ///> finds the joints corresponding to the ends of line aLine
void FindLineEnds( PNS_LINE* aLine, PNS_JOINT& a, PNS_JOINT& b ); 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. ///> (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 ); std::vector<PNS_JOINT*>& aConnectedJoints );
///> Destroys all child nodes. Applicable only to the root node. ///> Destroys all child nodes. Applicable only to the root node.
...@@ -201,15 +201,15 @@ private: ...@@ -201,15 +201,15 @@ private:
PNS_NODE& operator=( const PNS_NODE& b ); PNS_NODE& operator=( const PNS_NODE& b );
///> tries to find matching joint and creates a new one if not found ///> 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 ); int aNet );
///> touches a joint and links it to an item ///> 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 ); int aNet, PNS_ITEM* aWhere );
///> unlinks an item from a joint ///> 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 ); int aNet, PNS_ITEM* aWhere );
///> helpers for adding/removing items ///> helpers for adding/removing items
...@@ -231,7 +231,7 @@ private: ...@@ -231,7 +231,7 @@ private:
return m_parent == NULL; 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. ///> from the root branch.
bool overrides( PNS_ITEM* aItem ) const bool overrides( PNS_ITEM* aItem ) const
{ {
...@@ -249,7 +249,7 @@ private: ...@@ -249,7 +249,7 @@ private:
///> spatial index of all items ///> spatial index of all items
// SHAPE_INDEX_LIST<PNS_ITEM *> m_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. ///> their position, layer set and net.
JointMap m_joints; JointMap m_joints;
......
...@@ -109,7 +109,7 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther, ...@@ -109,7 +109,7 @@ bool PNS_COST_ESTIMATOR::IsBetter( PNS_COST_ESTIMATOR& aOther,
{ {
if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost ) if( aOther.m_cornerCost < m_cornerCost && aOther.m_lengthCost < m_lengthCost )
return true; return true;
else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost < else if( aOther.m_cornerCost < m_cornerCost * aCornerTollerance && aOther.m_lengthCost <
m_lengthCost * aLengthTollerance ) m_lengthCost * aLengthTollerance )
return true; return true;
...@@ -531,19 +531,19 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth, ...@@ -531,19 +531,19 @@ PNS_OPTIMIZER::BreakoutList PNS_OPTIMIZER::rectBreakouts( int aWidth,
if( s.x >= s.y ) 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 ) ) ); 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 ) ) ); 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 ) ) ); 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 ) ) ); c - d_offset - VECTOR2I( l, l ) ) );
} }
else else
{ {
// fixme: this could be done more efficiently // 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 ) ) ); 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 ) ) ); c - d_offset - VECTOR2I( -l, l ) ) );
...@@ -640,7 +640,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, ...@@ -640,7 +640,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
for( int diag = 0; diag < 2; diag++ ) for( int diag = 0; diag < 2; diag++ )
{ {
SHAPE_LINE_CHAIN v; 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 ); line.CPoint( p ), diag == 0 );
DIRECTION_45 dir_bkout( l.CSegment( -1 ) ); DIRECTION_45 dir_bkout( l.CSegment( -1 ) );
...@@ -691,7 +691,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, ...@@ -691,7 +691,7 @@ int PNS_OPTIMIZER::smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd,
if( !checkColliding( &tmp ) ) if( !checkColliding( &tmp ) )
{ {
/* if(aEnd) /* if(aEnd)
* PNSDisplayDebugLine (l_best, 6); * PNSDisplayDebugLine (l_best, 6);
* else * else
* PNSDisplayDebugLine (l_best, 5);*/ * PNSDisplayDebugLine (l_best, 5);*/
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
using namespace std; 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. // To be fixed sometime in the future.
static PNS_ROUTER* theRouter; static PNS_ROUTER* theRouter;
......
...@@ -429,7 +429,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead ) ...@@ -429,7 +429,7 @@ PNS_SHOVE::ShoveStatus PNS_SHOVE::ShoveLines( PNS_LINE* aCurrentHead )
break; break;
} }
/* if(lastWalkSolid == nearest->item) /* if(lastWalkSolid == nearest->item)
* { * {
* fail = true; * fail = true;
* break; * break;
......
...@@ -58,7 +58,7 @@ public: ...@@ -58,7 +58,7 @@ public:
private: private:
static const int ShoveTimeLimit = 3000; 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 ); PNS_SEGMENT& aObstacleSeg, PNS_LINE* aResult, bool aInvertWinding );
ShoveStatus shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, PNS_LINE* aObstacle, ShoveStatus shoveSingleLine( PNS_NODE* aNode, PNS_LINE* aCurrent, PNS_LINE* aObstacle,
......
...@@ -74,7 +74,7 @@ PNS_WALKAROUND::WalkaroundStatus PNS_WALKAROUND::singleStep( PNS_LINE& aPath, ...@@ -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 ); path_post[0], aWindingDirection );
aPath.NewWalkaround( current_obs->hull, path_pre[1], path_walk[1], aPath.NewWalkaround( current_obs->hull, path_pre[1], path_walk[1],
path_post[1], !aWindingDirection ); path_post[1], !aWindingDirection );
......
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
m_cursorApproachMode = aEnabled; m_cursorApproachMode = aEnabled;
} }
WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath, WalkaroundStatus Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
bool aOptimize = true ); bool aOptimize = true );
private: private:
......
...@@ -100,7 +100,7 @@ int ROUTER_TOOL::getDefaultWidth( int aNetCode ) ...@@ -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 ) int& aViaDiameter, int& aViaDrill )
{ {
BOARD* board = getModel<BOARD>( PCB_T ); BOARD* board = getModel<BOARD>( PCB_T );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment