Even more code comments and reformatting.

This commit is contained in:
Maciej Suminski 2013-09-27 18:51:21 +02:00
parent 3f320e4d68
commit 6b74b5771a
24 changed files with 412 additions and 338 deletions

View File

@ -31,36 +31,36 @@
typedef VECTOR2I::extended_type ecoord;
static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_CIRCLE& b, int clearance,
bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CIRCLE& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
ecoord min_dist = clearance + a.GetRadius() + b.GetRadius();
ecoord min_dist = aClearance + aA.GetRadius() + aB.GetRadius();
ecoord min_dist_sq = min_dist * min_dist;
const VECTOR2I delta = b.GetCenter() - a.GetCenter();
const VECTOR2I delta = aB.GetCenter() - aA.GetCenter();
ecoord dist_sq = delta.SquaredEuclideanNorm();
if ( dist_sq >= min_dist_sq )
return false;
if ( needMTV )
if ( aNeedMTV )
aMTV = delta.Resize( sqrt ( abs( min_dist_sq - dist_sq ) ) + 1 );
return true;
}
static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int clearance,
bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CIRCLE& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
const VECTOR2I c = b.GetCenter();
const VECTOR2I p0 = a.GetPosition();
const VECTOR2I size = a.GetSize();
const ecoord r = b.GetRadius();
const ecoord min_dist = clearance + r;
const VECTOR2I c = aB.GetCenter();
const VECTOR2I p0 = aA.GetPosition();
const VECTOR2I size = aA.GetSize();
const ecoord r = aB.GetRadius();
const ecoord min_dist = aClearance + r;
const ecoord min_dist_sq = min_dist * min_dist;
if ( a.BBox( 0 ).Contains( c ) )
if ( aA.BBox( 0 ).Contains( c ) )
return true;
const VECTOR2I vts[] = {
@ -86,7 +86,7 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
if( dist_sq < min_dist_sq )
{
if( !needMTV )
if( !aNeedMTV )
return true;
else
{
@ -102,7 +102,7 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
VECTOR2I delta = c - nearest;
if( !needMTV )
if( !aNeedMTV )
return true;
if( inside )
@ -114,12 +114,12 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_CIRCLE& b, int cle
}
static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_LINE_CHAIN& b, int clearance,
bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
for( int s = 0; s < b.SegmentCount(); s++ )
for( int s = 0; s < aB.SegmentCount(); s++ )
{
if ( a.Collide( b.CSegment( s ), clearance ) )
if ( aA.Collide( aB.CSegment( s ), aClearance ) )
return true;
}
@ -127,23 +127,23 @@ static inline bool Collide( const SHAPE_CIRCLE& a, const SHAPE_LINE_CHAIN& b, in
}
static inline bool Collide( const SHAPE_LINE_CHAIN& a, const SHAPE_LINE_CHAIN& b, int clearance,
bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
for( int i = 0; i < b.SegmentCount(); i++ )
if( a.Collide( b.CSegment(i), clearance ) )
for( int i = 0; i < aB.SegmentCount(); i++ )
if( aA.Collide( aB.CSegment(i), aClearance ) )
return true;
return false;
}
static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int clearance,
bool needMTV, VECTOR2I& aMTV )
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
bool aNeedMTV, VECTOR2I& aMTV )
{
for( int s = 0; s < b.SegmentCount(); s++ )
for( int s = 0; s < aB.SegmentCount(); s++ )
{
SEG seg = b.CSegment( s );
if( a.Collide( seg, clearance ) )
SEG seg = aB.CSegment( s );
if( aA.Collide( seg, aClearance ) )
return true;
}
@ -151,58 +151,58 @@ static inline bool Collide( const SHAPE_RECT& a, const SHAPE_LINE_CHAIN& b, int
}
bool CollideShapes( const SHAPE* a, const SHAPE* b, int clearance, bool needMTV, VECTOR2I& aMTV )
bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
{
switch( a->Type() )
switch( aA->Type() )
{
case SH_RECT:
switch( b->Type() )
switch( aB->Type() )
{
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_RECT*>( a ),
*static_cast<const SHAPE_CIRCLE*>( b ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_RECT*>( a ),
*static_cast<const SHAPE_LINE_CHAIN*>( b ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_RECT*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
default:
break;
}
case SH_CIRCLE:
switch( b->Type() )
switch( aB->Type() )
{
case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( b ),
*static_cast<const SHAPE_CIRCLE*>( a ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_CIRCLE*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( a ),
*static_cast<const SHAPE_CIRCLE*>( b ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_CIRCLE*>( aB ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_CIRCLE*>( a ),
*static_cast<const SHAPE_LINE_CHAIN *>( b ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_CIRCLE*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN *>( aB ), aClearance, aNeedMTV, aMTV );
default:
break;
}
case SH_LINE_CHAIN:
switch( b->Type() )
switch( aB->Type() )
{
case SH_RECT:
return Collide( *static_cast<const SHAPE_RECT*>( b ),
*static_cast<const SHAPE_LINE_CHAIN*>( a ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_RECT*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_CIRCLE:
return Collide( *static_cast<const SHAPE_CIRCLE*>( b ),
*static_cast<const SHAPE_LINE_CHAIN*>( a ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_CIRCLE*>( aB ),
*static_cast<const SHAPE_LINE_CHAIN*>( aA ), aClearance, aNeedMTV, aMTV );
case SH_LINE_CHAIN:
return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( a ),
*static_cast<const SHAPE_LINE_CHAIN*>( b ), clearance, needMTV, aMTV );
return Collide( *static_cast<const SHAPE_LINE_CHAIN*>( aA ),
*static_cast<const SHAPE_LINE_CHAIN*>( aB ), aClearance, aNeedMTV, aMTV );
default:
break;

View File

@ -99,6 +99,7 @@ bool ACTION_MANAGER::RunHotKey( int aHotKey ) const
void ACTION_MANAGER::runAction( const TOOL_ACTION* aAction ) const
{
TOOL_EVENT event = aAction->GetEvent();
TOOL_EVENT event = aAction->MakeEvent();
m_toolMgr->ProcessEvent( event );
}

View File

@ -151,24 +151,28 @@ void CONTEXT_MENU::CMEventHandler::onEvent( wxEvent& aEvent )
TOOL_EVENT evt;
wxEventType type = aEvent.GetEventType();
// When the currently chosen item in the menu is changed, an update event is issued.
// For example, the selection tool can use this to dynamically highlight the current item
// from selection clarification popup.
if( type == wxEVT_MENU_HIGHLIGHT )
evt = TOOL_EVENT( TC_Command, TA_ContextMenuUpdate, aEvent.GetId() );
// One of menu entries was selected..
else if( type == wxEVT_COMMAND_MENU_SELECTED )
{
if( aEvent.GetId() > m_actionId )
// Check if there is a TOOL_ACTION for the given ID
if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 )
{
// Handling TOOL_ACTIONs
if( m_menu->m_toolActions.count( aEvent.GetId() ) == 1 )
evt = m_menu->m_toolActions[aEvent.GetId()]->GetEvent();
evt = m_menu->m_toolActions[aEvent.GetId()]->MakeEvent();
}
else
{
// Handling common menu entries
// Handling non-action menu entries (e.g. items in clarification list)
evt = TOOL_EVENT( TC_Command, TA_ContextMenuChoice, aEvent.GetId() );
}
}
// forward the action/update event to the TOOL_MANAGER
if( m_menu->m_tool )
m_menu->m_tool->GetManager()->ProcessEvent( evt );
}

View File

@ -39,6 +39,7 @@
using boost::optional;
///> Stores information about a mouse button state
struct TOOL_DISPATCHER::ButtonState
{
ButtonState( TOOL_MouseButtons aButton, const wxEventType& aDownEvent,
@ -217,6 +218,8 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
type == wxEVT_LEFT_DOWN || type == wxEVT_LEFT_UP ||
type == wxEVT_MIDDLE_DOWN || type == wxEVT_MIDDLE_UP ||
type == wxEVT_RIGHT_DOWN || type == wxEVT_RIGHT_UP ||
// Event issued whem mouse retains position in screen coordinates,
// but changes in world coordinates (eg. autopanning)
type == KiGfx::WX_VIEW_CONTROLS::EVT_REFRESH_MOUSE )
{
VECTOR2D screenPos = m_toolMgr->GetViewControls()->GetCursorPosition();
@ -247,7 +250,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
if( type == wxEVT_KEY_UP )
{
if( key == WXK_ESCAPE )
if( key == WXK_ESCAPE ) // ESC is the special key for cancelling tools
evt = TOOL_EVENT( TC_Command, TA_CancelTool );
else
evt = TOOL_EVENT( TC_Keyboard, TA_KeyUp, key | mods );
@ -261,6 +264,7 @@ void TOOL_DISPATCHER::DispatchWxEvent( wxEvent& aEvent )
if( evt )
m_toolMgr->ProcessEvent( *evt );
// pass the event to the GUI, it might still be interested in it
aEvent.Skip();
}
@ -270,6 +274,7 @@ void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent )
bool activateTool = false;
std::string toolName;
// fixme: use TOOL_ACTIONs here
switch( aEvent.GetId() )
{
case ID_PNS_ROUTER_TOOL:
@ -282,6 +287,7 @@ void TOOL_DISPATCHER::DispatchWxCommand( const wxCommandEvent& aEvent )
break;
}
// do nothing if the legacy view is active
if( activateTool && m_editFrame->IsGalCanvasActive() )
m_toolMgr->InvokeTool( toolName );
}

View File

@ -25,9 +25,8 @@
#include <cstring>
#include <string>
//#include <base_struct.h>
#include <tool/tool_event.h>
#include <tool/tool_action.h>
#include <tool/tool_manager.h>
#include <boost/foreach.hpp>
@ -55,6 +54,12 @@ static const std::string flag2string( int flag, const FlagString* exps )
}
bool TOOL_EVENT::IsAction( const TOOL_ACTION* aAction ) const
{
return Matches( aAction->MakeEvent() );
}
const std::string TOOL_EVENT::Format() const
{
std::string ev;

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -39,6 +40,7 @@
#include <tool/tool_manager.h>
#include <tool/context_menu.h>
#include <tool/coroutine.h>
#include <tool/action_manager.h>
#include <wxPcbStruct.h>
#include <class_drawpanel_gal.h>
@ -46,37 +48,38 @@
using boost::optional;
using namespace std;
/// Struct describing the current state of a TOOL
/// Struct describing the current execution state of a TOOL
struct TOOL_MANAGER::TOOL_STATE
{
/// The tool itself
TOOL_BASE* theTool;
/// Is the tool active or idle at the moment
/// Is the tool active (pending execution) or disabled at the moment
bool idle;
/// Flag defining if the tool is waiting for any event
/// Flag defining if the tool is waiting for any event (i.e. if it
/// issued a Wait() call).
bool pendingWait;
/// Is there a context menu to be displayed
/// Is there a context menu being displayed
bool pendingContextMenu;
/// Context menu used by the tool
/// Context menu currently used by the tool
CONTEXT_MENU* contextMenu;
/// Defines when a context menu is opened
/// Defines when the context menu is opened
CONTEXT_MENU_TRIGGER contextMenuTrigger;
/// Coroutine launched upon an event trigger
/// Tool execution context
COROUTINE<int, TOOL_EVENT&>* cofunc;
/// The event that triggered the coroutine
/// The event that triggered the execution/wakeup of the tool after Wait() call
TOOL_EVENT wakeupEvent;
/// List of events that are triggering the coroutine
/// List of events the tool is currently waiting for
TOOL_EVENT_LIST waitEvents;
/// List of possible transitions (ie. association of events and functions that are executed
/// List of possible transitions (ie. association of events and state handlers that are executed
/// upon the event reception
std::vector<TRANSITION> transitions;
@ -93,8 +96,9 @@ struct TOOL_MANAGER::TOOL_STATE
TOOL_MANAGER::TOOL_MANAGER() :
m_actionMgr( this ), m_model( NULL ), m_view( NULL )
m_model( NULL ), m_view( NULL )
{
m_actionMgr = new ACTION_MANAGER( this );
}
@ -108,6 +112,8 @@ TOOL_MANAGER::~TOOL_MANAGER()
delete it->second; // delete TOOL_STATE
delete it->first; // delete the tool itself
}
delete m_actionMgr;
}
@ -154,7 +160,7 @@ bool TOOL_MANAGER::InvokeTool( TOOL_ID aToolId )
if( tool && tool->GetType() == TOOL_Interactive )
return invokeTool( tool );
return false;
return false; // there is no tool with the given id
}
@ -165,7 +171,19 @@ bool TOOL_MANAGER::InvokeTool( const std::string& aToolName )
if( tool && tool->GetType() == TOOL_Interactive )
return invokeTool( tool );
return false;
return false; // there is no tool with the given name
}
void TOOL_MANAGER::RegisterAction( TOOL_ACTION* aAction )
{
m_actionMgr->RegisterAction( aAction );
}
void TOOL_MANAGER::UnregisterAction( TOOL_ACTION* aAction )
{
m_actionMgr->UnregisterAction( aAction );
}
@ -187,7 +205,7 @@ bool TOOL_MANAGER::runTool( TOOL_ID aToolId )
if( tool && tool->GetType() == TOOL_Interactive )
return runTool( tool );
return false;
return false; // there is no tool with the given id
}
@ -198,7 +216,7 @@ bool TOOL_MANAGER::runTool( const std::string& aToolName )
if( tool && tool->GetType() == TOOL_Interactive )
return runTool( tool );
return false;
return false; // there is no tool with the given name
}
@ -260,8 +278,12 @@ optional<TOOL_EVENT> TOOL_MANAGER::ScheduleWait( TOOL_BASE* 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
st->cofunc->Yield();
return st->wakeupEvent;
@ -300,7 +322,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
{
// the tool state handler is waiting for events (i.e. called Wait() method)
// the tool scheduled next state(s) by calling Go()
if( !st->pendingWait )
{
// no state handler in progress - check if there are any transitions (defined by
@ -313,6 +335,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
{
st->transitions.clear();
// no tool context allocated yet? Create one.
if( !st->cofunc )
st->cofunc = new COROUTINE<int, TOOL_EVENT&>( tr.second );
else
@ -322,7 +345,7 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
st->cofunc->Call( aEvent );
if( !st->cofunc->Running() )
finishTool( st ); // The couroutine has finished
finishTool( st ); // The couroutine has finished immediately?
}
}
}
@ -331,8 +354,27 @@ void TOOL_MANAGER::dispatchInternal( TOOL_EVENT& aEvent )
}
bool TOOL_MANAGER::dispatchStandardEvents( TOOL_EVENT& aEvent )
{
if( aEvent.Action() == TA_KeyUp )
{
// Check if there is a hotkey associated
if( m_actionMgr->RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
return false; // hotkey event was handled so it does not go any further
}
else if( aEvent.Category() == TC_Command ) // it may be a tool activation event
{
dispatchActivation( aEvent );
// do not return false, as the event has to go on to the destined tool
}
return true;
}
bool TOOL_MANAGER::dispatchActivation( TOOL_EVENT& aEvent )
{
// Look for the tool that has the same name as parameter in the processed command TOOL_EVENT
BOOST_FOREACH( TOOL_STATE* st, m_toolState | boost::adaptors::map_values )
{
if( st->theTool->GetName() == aEvent.m_commandStr )
@ -359,7 +401,7 @@ void TOOL_MANAGER::finishTool( TOOL_STATE* aState )
if( it != m_activeTools.end() )
m_activeTools.erase( it );
else
wxLogWarning( wxT( "Tried to finish not active tool" ) );
wxLogWarning( wxT( "Tried to finish inactive tool" ) );
aState->idle = true;
delete aState->cofunc;
@ -371,22 +413,19 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
{
// wxLogDebug( "event: %s", aEvent.Format().c_str() );
if( aEvent.Action() == TA_KeyUp )
{
// Check if there is a hotkey associated
if( m_actionMgr.RunHotKey( aEvent.Modifier() | aEvent.KeyCode() ) )
return false; // hotkey event was handled so it does not go any further
} else if( aEvent.Category() == TC_Command ) // it may be a tool activation event
{
dispatchActivation( aEvent );
}
// Early dispatch of events destined for the TOOL_MANAGER
if( !dispatchStandardEvents( aEvent ) )
return false;
dispatchInternal( aEvent );
// popup menu handling
BOOST_FOREACH( TOOL_ID toolId, m_activeTools )
{
TOOL_STATE* st = m_toolIdIndex[toolId];
// the tool requested a context menu. The menu is activated on RMB click (CMENU_BUTTON mode)
// or immediately (CMENU_NOW) mode. The latter is used for clarification lists.
if( st->contextMenuTrigger != CMENU_OFF )
{
if( st->contextMenuTrigger == CMENU_BUTTON && !aEvent.IsClick( MB_Right ) )
@ -401,6 +440,7 @@ bool TOOL_MANAGER::ProcessEvent( TOOL_EVENT& aEvent )
boost::scoped_ptr<CONTEXT_MENU> menu( new CONTEXT_MENU( *st->contextMenu ) );
GetEditFrame()->PopupMenu( menu->GetMenu() );
//
TOOL_EVENT evt( TC_Command, TA_ContextMenuChoice );
dispatchInternal( evt );
@ -426,6 +466,7 @@ void TOOL_MANAGER::ScheduleContextMenu( TOOL_BASE* aTool, CONTEXT_MENU* aMenu,
st->contextMenu = aMenu;
st->contextMenuTrigger = aTrigger;
// the tool wants the menu immediately? Preempt it and do so :)
if( aTrigger == CMENU_NOW )
st->cofunc->Yield();
}

View File

@ -34,8 +34,8 @@
typedef boost::optional<VECTOR2I> OPT_VECTOR2I;
class SEG {
class SEG
{
private:
typedef VECTOR2I::extended_type ecoord;
@ -52,7 +52,7 @@ class SEG {
/** Default constructor
* 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;
b = m_b;
@ -62,12 +62,12 @@ class SEG {
/**
* Constructor
* Creates a segment between (x1, y1) and (x2, y2), locally referenced
* Creates a segment between (aX1, aY1) and (aX2, aY2), locally referenced
*/
SEG ( int x1, int y1, int x2, int y2 ) : a(m_a), b(m_b)
SEG( int aX1, int aY1, int aX2, int aY2 ) : a( m_a ), b( m_b )
{
m_a = VECTOR2I(x1, y1);
m_b = VECTOR2I(x2, y2);
m_a = VECTOR2I( aX1, aY1 );
m_b = VECTOR2I( aX2, aY2 );
a = m_a;
b = m_b;
m_is_local = true;
@ -78,7 +78,7 @@ class SEG {
* Constructor
* Creates a segment between (aA) and (aB), locally referenced
*/
SEG ( const VECTOR2I& aA, const VECTOR2I& aB ): a(m_a), b(m_b), m_a(aA), m_b(aB)
SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : a( m_a ), b( m_b ), m_a( aA ), m_b( aB )
{
a = m_a;
b = m_b;
@ -93,7 +93,7 @@ class SEG {
* @param aB reference to the end point in the parent shape
* @param aIndex index of the segment within the parent shape
*/
SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ): a(aA), b(aB)
SEG ( VECTOR2I& aA, VECTOR2I& aB, int aIndex ) : a( aA ), b( aB )
{
m_is_local = false;
m_index = aIndex;
@ -102,32 +102,32 @@ class SEG {
/**
* Copy constructor
*/
SEG ( const SEG& seg ): a(m_a), b(m_b)
SEG ( const SEG& aSeg ) : a( m_a ), b( m_b )
{
if (seg.m_is_local)
if (aSeg.m_is_local)
{
m_a = seg.m_a;
m_b = seg.m_b;
m_a = aSeg.m_a;
m_b = aSeg.m_b;
a = m_a;
b = m_b;
m_is_local = true;
m_index = -1;
} else {
a = seg.a;
b = seg.b;
m_index = seg.m_index;
a = aSeg.a;
b = aSeg.b;
m_index = aSeg.m_index;
m_is_local = false;
}
}
SEG& operator=(const SEG& seg)
SEG& operator=( const SEG& aSeg )
{
a = seg.a;
b = seg.b;
m_a = seg.m_a;
m_b = seg.m_b;
m_index = seg.m_index;
m_is_local = seg.m_is_local;
a = aSeg.a;
b = aSeg.b;
m_a = aSeg.m_a;
m_b = aSeg.m_b;
m_index = aSeg.m_index;
m_is_local = aSeg.m_is_local;
return *this;
}
@ -150,8 +150,9 @@ class SEG {
*/
int Side( const VECTOR2I& aP ) const
{
const ecoord det = (b - a).Cross(aP - a);
return det < 0 ? -1 : (det > 0 ? 1 : 0);
const ecoord det = ( b - a ).Cross( aP - a );
return det < 0 ? -1 : ( det > 0 ? 1 : 0 );
}
/**
@ -173,7 +174,6 @@ class SEG {
*/
const VECTOR2I NearestPoint( const VECTOR2I &aP ) const;
/**
* Function Intersect()
*
@ -186,8 +186,6 @@ class SEG {
*/
OPT_VECTOR2I Intersect( const SEG& aSeg, bool aIgnoreEndpoints = false, bool aLines = false ) const;
/**
* Function IntersectLines()
*
@ -195,9 +193,9 @@ class SEG {
* @param aSeg segment defining the line to intersect with
* @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;
@ -210,14 +208,13 @@ class SEG {
* @return minimum distance
*/
ecoord SquaredDistance( const SEG& aSeg ) const ;
ecoord SquaredDistance( const SEG& aSeg ) const;
int Distance( const SEG& aSeg ) const
{
return sqrt ( SquaredDistance(aSeg) );
return sqrt( SquaredDistance( aSeg ) );
}
/**
* Function Distance()
*
@ -225,18 +222,16 @@ class SEG {
* @param aP the point
* @return minimum distance
*/
ecoord SquaredDistance( const VECTOR2I& aP ) const
{
return (NearestPoint(aP) - aP).SquaredEuclideanNorm();
return ( NearestPoint( aP ) - aP ).SquaredEuclideanNorm();
}
int Distance( const VECTOR2I& aP ) const
{
return sqrt ( SquaredDistance( aP) );
return sqrt( SquaredDistance( aP ) );
}
/**
* Function Collinear()
*
@ -244,7 +239,6 @@ class SEG {
* @param aSeg the segment to chech colinearity with
* @return true, when segments are collinear.
*/
bool Collinear( const SEG& aSeg ) const
{
ecoord qa1 = a.y - b.y;
@ -254,7 +248,7 @@ class SEG {
ecoord qb2 = aSeg.b.x - aSeg.a.x;
ecoord qc2 = -qa2 * aSeg.a.x - qb2 * aSeg.a.y;
return (qa1 == qa2) && (qb1 == qb2) && (qc1 == qc2);
return ( qa1 == qa2 ) && ( qb1 == qb2 ) && ( qc1 == qc2 );
}
/**
@ -265,15 +259,14 @@ class SEG {
*/
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()
*
@ -285,20 +278,20 @@ class SEG {
return m_index;
}
bool Contains( const VECTOR2I& aP ) const;
bool Contains(const VECTOR2I& aP) const;
bool PointCloserThan ( const VECTOR2I& aP, int dist) const;
bool PointCloserThan( const VECTOR2I& aP, int aDist ) const;
// friend std::ostream& operator<<( std::ostream& stream, const SEG& aSeg );
private:
bool ccw ( const VECTOR2I& a, const VECTOR2I& b, const VECTOR2I &c ) const;
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
///> locally stored start/end coordinates (used when m_is_local == true)
VECTOR2I m_a, m_b;
///> index withing the parent shape (used when m_is_local == false)
int m_index;
///> locality flag
bool m_is_local;
};
@ -306,49 +299,47 @@ class SEG {
inline VECTOR2I SEG::LineProject( const VECTOR2I& aP ) const
{
// fixme: numerical errors for large integers
assert(false);
return VECTOR2I(0, 0);
assert( false );
return VECTOR2I( 0, 0 );
}
inline int SEG::LineDistance( const VECTOR2I& aP, bool aDetermineSide ) const
{
ecoord p = a.y - b.y;
ecoord q = b.x - a.x;
ecoord r = -p * a.x - q * a.y;
ecoord p = a.y - b.y;
ecoord q = b.x - a.x;
ecoord r = -p * a.x - q * a.y;
ecoord dist = ( p * aP.x + q * aP.y + r ) / sqrt( p * p + q * q );
return aDetermineSide ? dist : abs(dist);
ecoord dist = ( p * aP.x + q * aP.y + r ) / sqrt( p * p + q * q );
return aDetermineSide ? dist : abs( dist );
}
inline const VECTOR2I SEG::NearestPoint(const VECTOR2I& aP) const
inline const VECTOR2I SEG::NearestPoint( const VECTOR2I& aP ) const
{
VECTOR2I d = b - a;
ecoord l_squared = d.Dot(d);
VECTOR2I d = b - a;
ecoord l_squared = d.Dot( d );
if( l_squared == 0 )
return a;
ecoord t = d.Dot(aP - a);
ecoord t = d.Dot( aP - a );
if( t < 0 )
return a;
else if( t > l_squared )
return b;
int xp = rescale(t, (ecoord)d.x, l_squared);
int yp = rescale(t, (ecoord)d.y, l_squared);
int xp = rescale( t, (ecoord)d.x, l_squared );
int yp = rescale( t, (ecoord)d.y, l_squared );
return a + VECTOR2I(xp, yp);
return a + VECTOR2I( xp, yp );
}
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 << " ]";
return aStream;
}

View File

@ -45,7 +45,7 @@ enum ShapeType {
/**
* Class SHAPE
*
* Represents an abstract shape on 2D plane. All SHAPEs implement SHAPE interface.
* Represents an abstract shape on 2D plane.
*/
class SHAPE {
protected:
@ -58,7 +58,7 @@ class SHAPE {
* Creates an empty shape of type aType
*/
SHAPE ( ShapeType aType ): m_type( aType ) { };
SHAPE ( ShapeType aType ) : m_type( aType ) { };
// Destructor
virtual ~SHAPE() {};
@ -78,7 +78,7 @@ class SHAPE {
* @retval copy of the shape
*/
virtual SHAPE* Clone() const {
assert(false);
assert( false );
return NULL;
};
@ -89,9 +89,9 @@ class SHAPE {
* 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 );
}
/**
@ -99,10 +99,13 @@ class SHAPE {
*
* Checks if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating
* a collision.
* @param aShape shape to check collision against
* @param aClearance minimum clearance
* @param aMTV minimum translation vector
* @return true, if there is a collision.
*/
virtual bool Collide ( const SHAPE *aShape, int aClerance, VECTOR2I& aMTV ) const;
virtual bool Collide ( const SHAPE *aShape, int aClerance = 0 ) const;
virtual bool Collide( const SHAPE* aShape, int aClerance, VECTOR2I& aMTV ) const;
virtual bool Collide( const SHAPE* aShape, int aClerance = 0 ) const;
/**
* Function Collide()
*
@ -110,7 +113,7 @@ class SHAPE {
* 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()
@ -120,7 +123,7 @@ class SHAPE {
* @aClearance how much the bounding box is expanded wrs to the minimum enclosing rectangle for the shape.
* @return the bounding box.
*/
virtual const BOX2I BBox ( int aClearance = 0 ) const = 0;
virtual const BOX2I BBox( int aClearance = 0 ) const = 0;
/**
* Function Centre()
@ -130,7 +133,7 @@ class SHAPE {
*/
virtual VECTOR2I Centre() const
{
return BBox(0).Centre(); // if nothing better is available....
return BBox( 0 ).Centre(); // if nothing better is available....
}
private:
@ -139,6 +142,6 @@ class SHAPE {
};
bool CollideShapes ( const SHAPE *a, const SHAPE *b, int clearance, bool needMTV, VECTOR2I& aMTV );
bool CollideShapes( const SHAPE *aA, const SHAPE *aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV );
#endif // __SHAPE_H

View File

@ -31,32 +31,31 @@ class SHAPE_CIRCLE : public SHAPE {
public:
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( SH_CIRCLE ), m_radius( aRadius ), m_center( aCenter ) {};
~SHAPE_CIRCLE() {};
const BOX2I BBox(int aClearance = 0) const
const BOX2I BBox( int aClearance = 0 ) const
{
const VECTOR2I rc (m_radius + aClearance, m_radius + aClearance);
return BOX2I (m_center - rc, rc * 2);
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
bool Collide( const SEG& aSeg, int aClearance = 0 ) const
{
int rc = aClearance + m_radius;
return aSeg.Distance(m_center) <= rc;
return aSeg.Distance( m_center ) <= rc;
}
void SetRadius(int aRadius)
void SetRadius( int aRadius )
{
m_radius = aRadius;
}
void SetCenter (const VECTOR2I& aCenter)
void SetCenter( const VECTOR2I& aCenter )
{
m_center = aCenter;
}

View File

@ -62,9 +62,9 @@ const SHAPE* shapeFunctor( SHAPE* aItem );
* @return a BOX2I object containing the bounding box of the T object.
*/
template <class T>
BOX2I boundingBox( T object )
BOX2I boundingBox( T aObject )
{
return shapeFunctor(object)->BBox();
return shapeFunctor( aObject )->BBox();
}
/**
@ -77,9 +77,9 @@ BOX2I boundingBox( T object )
* @param visitor V visitor object
*/
template <class T, class V>
void acceptVisitor( T object, V visitor )
void acceptVisitor( T aObject, V aVisitor )
{
visitor(object);
aVisitor( aObject );
}
/**
@ -94,22 +94,23 @@ void acceptVisitor( T object, V visitor )
* @return if object and anotherObject collide
*/
template<class T, class U>
bool collide( T object, U anotherObject, int minDistance )
bool collide( T aObject, U aAnotherObject, int aMinDistance )
{
return shapeFunctor( object )->Collide( anotherObject, minDistance );
return shapeFunctor( aObject )->Collide( aAnotherObject, aMinDistance );
}
template<class T, class V>
bool queryCallback(T shape, void* context)
bool queryCallback( T aShape, void* aContext )
{
V* visitor = (V*) context;
acceptVisitor<T,V>( shape, *visitor );
V* visitor = (V*) aContext;
acceptVisitor<T,V>( aShape, *visitor );
return true;
}
template<class T = SHAPE*>
class SHAPE_INDEX {
class SHAPE_INDEX
{
public:
class Iterator
{
@ -123,9 +124,9 @@ class SHAPE_INDEX {
* Setup the internal tree iterator.
* @param tree pointer to a RTREE object
*/
void Init( RTree<T, int, 2, float>* tree )
void Init( RTree<T, int, 2, float>* aTree )
{
tree->GetFirst( iterator );
aTree->GetFirst( iterator );
}
public:
@ -135,9 +136,9 @@ class SHAPE_INDEX {
* Creates an iterator for the index object
* @param index SHAPE_INDEX object to iterate
*/
Iterator( SHAPE_INDEX* index )
Iterator( SHAPE_INDEX* aIndex )
{
Init( index->m_tree );
Init( aIndex->m_tree );
}
/**
@ -321,7 +322,7 @@ void SHAPE_INDEX<T>::Add( T aShape )
}
template<class T>
void SHAPE_INDEX<T>::Remove(T aShape)
void SHAPE_INDEX<T>::Remove( T aShape )
{
BOX2I box = boundingBox( aShape );
int min[2] = { box.GetX(), box.GetY() };

View File

@ -27,30 +27,29 @@
#include <boost/unordered_map.hpp>
template <class T> const SHAPE *defaultShapeFunctor( const T aItem )
template <class T> const SHAPE* defaultShapeFunctor( const T aItem )
{
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 {
struct ShapeEntry {
ShapeEntry(T aParent)
ShapeEntry( T aParent )
{
shape = ShapeFunctor(aParent);
bbox = shape->BBox(0);
shape = ShapeFunctor( aParent );
bbox = shape->BBox( 0 );
parent = aParent;
}
~ShapeEntry()
{
}
T parent;
const SHAPE *shape;
const SHAPE* shape;
BOX2I bbox;
};
@ -58,18 +57,16 @@ class SHAPE_INDEX_LIST {
typedef typename std::vector<ShapeEntry>::iterator ShapeVecIter;
public:
// "Normal" iterator interface, for STL algorithms.
// "Normal" iterator interface, for STL algorithms.
class iterator {
public:
iterator() {};
iterator( ShapeVecIter aCurrent)
: m_current(aCurrent) {};
iterator( ShapeVecIter aCurrent )
: m_current( aCurrent ) {};
iterator(const iterator &b) :
m_current(b.m_current) {};
iterator( const iterator &aB ) :
m_current( aB.m_current ) {};
T operator*() const
{
@ -81,25 +78,25 @@ public:
++m_current;
}
iterator& operator++(int dummy)
iterator& operator++( int aDummy )
{
++m_current;
return *this;
}
bool operator ==( const iterator& rhs ) const
bool operator==( const iterator& aRhs ) const
{
return m_current == rhs.m_current;
return m_current == aRhs.m_current;
}
bool operator !=( const iterator& rhs ) const
bool operator!=( const iterator& aRhs ) const
{
return m_current != rhs.m_current;
return m_current != aRhs.m_current;
}
const iterator& operator=(const iterator& rhs)
const iterator& operator=( const iterator& aRhs )
{
m_current = rhs.m_current;
m_current = aRhs.m_current;
return *this;
}
@ -107,41 +104,38 @@ public:
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 {
public:
query_iterator()
{
}
query_iterator( ShapeVecIter aCurrent, ShapeVecIter aEnd, SHAPE *aShape, int aMinDistance, bool aExact)
: m_end(aEnd),
m_current(aCurrent),
m_shape(aShape),
m_minDistance(aMinDistance),
m_exact(aExact)
query_iterator( ShapeVecIter aCurrent, ShapeVecIter aEnd, SHAPE* aShape,
int aMinDistance, bool aExact ) :
m_end( aEnd ),
m_current( aCurrent ),
m_shape( aShape ),
m_minDistance( aMinDistance ),
m_exact( aExact )
{
if(aShape)
if( aShape )
{
m_refBBox = aShape->BBox();
next();
}
}
query_iterator(const query_iterator &b)
: m_end(b.m_end),
m_current(b.m_current),
m_shape(b.m_shape),
m_minDistance(b.m_minDistance),
m_exact(b.m_exact),
m_refBBox(b.m_refBBox)
query_iterator( const query_iterator &aB ) :
m_end( aB.m_end ),
m_current( aB.m_current ),
m_shape( aB.m_shape ),
m_minDistance( aB.m_minDistance ),
m_exact( aB.m_exact ),
m_refBBox( aB.m_refBBox )
{
}
T operator*() const
{
return (*m_current).parent;
@ -154,45 +148,45 @@ public:
return *this;
}
query_iterator& operator++(int dummy)
query_iterator& operator++( int aDummy )
{
++m_current;
next();
return *this;
}
bool operator ==( const query_iterator& rhs ) const
bool operator==( const query_iterator& aRhs ) const
{
return m_current == rhs.m_current;
return m_current == aRhs.m_current;
}
bool operator !=( const query_iterator& rhs ) const
bool operator!=( const query_iterator& aRhs ) const
{
return m_current != rhs.m_current;
return m_current != aRhs.m_current;
}
const query_iterator& operator=(const query_iterator& rhs)
const query_iterator& operator=( const query_iterator& aRhs )
{
m_end = rhs.m_end;
m_current = rhs.m_current;
m_shape = rhs.m_shape;
m_minDistance = rhs.m_minDistance;
m_exact = rhs.m_exact;
m_refBBox = rhs.m_refBBox;
m_end = aRhs.m_end;
m_current = aRhs.m_current;
m_shape = aRhs.m_shape;
m_minDistance = aRhs.m_minDistance;
m_exact = aRhs.m_exact;
m_refBBox = aRhs.m_refBBox;
return *this;
}
private:
void next()
{
while(m_current != m_end)
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;
}
++m_current;
}
}
@ -205,27 +199,27 @@ public:
int m_minDistance;
};
void Add(T aItem)
void Add( T aItem )
{
ShapeEntry s (aItem);
ShapeEntry s( aItem );
m_shapes.push_back(s);
}
void Remove(const T aItem)
void Remove( const T aItem )
{
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;
}
if(i == m_shapes.end())
if( i == m_shapes.end() )
return;
m_shapes.erase(i);
m_shapes.erase( i );
}
int Size() const
@ -234,37 +228,37 @@ public:
}
template<class Visitor>
int Query( const SHAPE *aShape, int aMinDistance, Visitor &v, bool aExact = true) //const
{
ShapeVecIter i;
int n = 0;
VECTOR2I::extended_type minDistSq = (VECTOR2I::extended_type) aMinDistance * aMinDistance;
int Query( const SHAPE *aShape, int aMinDistance, Visitor &aV, bool aExact = true ) //const
{
ShapeVecIter i;
int n = 0;
VECTOR2I::extended_type minDistSq = (VECTOR2I::extended_type) aMinDistance * aMinDistance;
BOX2I refBBox = aShape->BBox();
BOX2I refBBox = aShape->BBox();
for(i = m_shapes.begin(); i!=m_shapes.end(); ++i)
{
if (refBBox.SquaredDistance(i->bbox) <= minDistSq)
{
if(!aExact || i->shape->Collide(aShape, aMinDistance))
{
n++;
if(!v( i->parent ))
return n;
}
}
}
return n;
}
for( i = m_shapes.begin(); i != m_shapes.end(); ++i )
{
if( refBBox.SquaredDistance( i->bbox ) <= minDistSq )
{
if( !aExact || i->shape->Collide( aShape, aMinDistance ) )
{
n++;
if( !aV( i->parent ) )
return n;
}
}
}
return n;
}
void 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()
@ -283,7 +277,6 @@ public:
}
private:
ShapeVec m_shapes;
};

View File

@ -36,28 +36,28 @@ class SHAPE_RECT : public SHAPE {
* Constructor
* Creates an empty (0-sized) rectangle
*/
SHAPE_RECT():
SHAPE( SH_RECT ), m_w (0), m_h(0) {};
SHAPE_RECT() :
SHAPE( SH_RECT ), m_w( 0 ), m_h( 0 ) {};
/**
* Constructor
* Creates a rectangle defined by top-left corner (x0, y0), width w and height h.
* Creates a rectangle defined by top-left corner (aX0, aY0), width aW and height aH.
*/
SHAPE_RECT( int x0, int y0, int w, int h ):
SHAPE(SH_RECT), m_p0(x0, y0), m_w(w), m_h(h) {};
SHAPE_RECT( int aX0, int aY0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aX0, aY0 ), m_w( aW ), m_h( aH ) {};
/**
* Constructor
* Creates a rectangle defined by top-left corner p0, width w and height h.
* Creates a rectangle defined by top-left corner aP0, width aW and height aH.
*/
SHAPE_RECT( const VECTOR2I &p0, int w, int h ):
SHAPE(SH_RECT), m_p0(p0), m_w(w), m_h(h) {};
SHAPE_RECT( const VECTOR2I &aP0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH ) {};
/// @copydoc SHAPE::BBox()
const BOX2I BBox(int aClearance = 0) const
{
BOX2I bbox( VECTOR2I (m_p0.x - aClearance, m_p0.y - aClearance ),
VECTOR2I (m_w + 2 * aClearance, m_h + 2 * aClearance ));
BOX2I bbox( VECTOR2I( m_p0.x - aClearance, m_p0.y - aClearance ),
VECTOR2I( m_w + 2 * aClearance, m_h + 2 * aClearance ) );
//printf("bb : %s\n",bbox.Format().c_str());
return bbox;
}
@ -70,11 +70,11 @@ class SHAPE_RECT : public SHAPE {
*/
int Diagonal() const
{
return VECTOR2I(m_w, m_h).EuclideanNorm();
return VECTOR2I( m_w, m_h ).EuclideanNorm();
}
/// @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 pmax = VECTOR2I(std::max(aSeg.a.x, aSeg.b.x), std::max(aSeg.a.y, aSeg.b.y));
@ -83,19 +83,19 @@ class SHAPE_RECT : public SHAPE {
//if (BBox(0).SquaredDistance(r) > aClearance * aClearance)
// 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;
VECTOR2I vts[] = { VECTOR2I(m_p0.x, m_p0.y),
VECTOR2I(m_p0.x, m_p0.y + m_h),
VECTOR2I(m_p0.x + m_w, m_p0.y + m_h),
VECTOR2I(m_p0.x + m_w, m_p0.y),
VECTOR2I(m_p0.x, m_p0.y) };
VECTOR2I vts[] = { VECTOR2I( m_p0.x, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y + m_h ),
VECTOR2I( m_p0.x + m_w, m_p0.y ),
VECTOR2I( m_p0.x, m_p0.y ) };
for (int i = 0; i < 4; i++)
for( int i = 0; i < 4; i++ )
{
SEG s(vts[i], vts[i+1], i);
if(s.Distance(aSeg) <= aClearance)
SEG s( vts[i], vts[i + 1], i );
if( s.Distance( aSeg ) <= aClearance )
return true;
}
@ -114,7 +114,7 @@ class SHAPE_RECT : public SHAPE {
*
* @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()
@ -133,8 +133,10 @@ class SHAPE_RECT : public SHAPE {
private:
///> Top-left corner
VECTOR2I m_p0;
///> Width
int m_w;
///> Height
int m_h;
};

View File

@ -32,6 +32,12 @@ class TOOL_BASE;
class TOOL_MANAGER;
class TOOL_ACTION;
/**
* Class ACTION_MANAGER
*
* Takes care of TOOL_ACTION objects. Registers them and allows to run them using associated
* hot keys, names or ids.
*/
class ACTION_MANAGER
{
public:

View File

@ -140,7 +140,7 @@ private:
/// Menu items with ID higher than that are considered TOOL_ACTIONs
static const int m_actionId = 10000;
/// Stores tool actions that are choosable from the menu. Does not take the ownership.
/// Associates tool actions with menu item IDs. Non-owning.
std::map<int, const TOOL_ACTION*> m_toolActions;
};

View File

@ -181,7 +181,7 @@ public:
}
private:
static const int c_defaultStackSize = 2000000;
static const int c_defaultStackSize = 2000000; // fixme: make configurable
/* real entry point of the coroutine */
static void callerStub( intptr_t data )

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,10 +32,16 @@
#include <tool/tool_base.h>
#include <tool/action_manager.h>
// TOOL_ACTION - represents a single action. For instance:
// - changing layer to top by pressing PgUp
// - running the DRC from the menu
// and so on, and so forth....
/**
* Class TOOL_ACTION
*
* Represents a single user action. For instance:
* - changing layer to top by pressing PgUp
* - running the DRC from the menu
* and so on, and so forth....
* Action class groups all necessary properties of an action, including explanation,
* icons, hotkeys,.menu items, etc.
*/
class TOOL_ACTION
{
public:
@ -133,13 +140,13 @@ public:
}
/**
* Function GetEvent()
* Function MakeEvent()
* Returns the event associated with the action (ie. the event that will be sent after
* activating the action).
*
* @return The event associated with the action.
*/
TOOL_EVENT GetEvent() const
TOOL_EVENT MakeEvent() const
{
return TOOL_EVENT( TC_Command, TA_Action, m_name, m_scope );
}

View File

@ -42,10 +42,10 @@ namespace KiGfx {
* Class TOOL_DISPATCHER
*
* - takes wx events,
* - fixes all wx quirks (mouse warping, etc)
* - fixes all wx quirks (mouse warping, panning, ordering problems, etc)
* - translates coordinates to world space
* - low-level input conditioning (drag/click threshold), updating mouse position during view auto-scroll/pan.
* - issues TOOL_EVENTS to the manager
* - issues TOOL_EVENTS to the tool manager
*/
class TOOL_DISPATCHER
@ -100,6 +100,7 @@ private:
///> Saves the state of key modifiers (Alt, Ctrl and so on).
int decodeModifiers( const wxKeyboardState* aState ) const;
///> Stores all the informations regarding a mouse button state.
struct ButtonState;

View File

@ -33,6 +33,7 @@
#include <boost/optional.hpp>
class TOOL_ACTION;
class TOOL_MANAGER;
/**
@ -313,6 +314,14 @@ public:
return true;
}
/**
* Function IsAction()
* Tests if the event contains an action issued upon activation of the given TOOL_ACTION.
* @param aAction is the TOOL_ACTION to be checked against.
* @return True if it matches the given TOOL_ACTION.
*/
bool IsAction( const TOOL_ACTION* aAction ) const;
boost::optional<int> GetCommandId()
{
return m_commandId;

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2013 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,11 +31,10 @@
#include <math/vector2d.h>
#include <tool/tool_event.h>
#include <tool/tool_base.h>
#include <tool/action_manager.h>
class TOOL_BASE;
class ACTION_MANAGER;
class CONTEXT_MENU;
class wxWindow;
@ -89,10 +89,7 @@ public:
*
* @param aAction is the action to be registered.
*/
void RegisterAction( TOOL_ACTION* aAction )
{
m_actionMgr.RegisterAction( aAction );
}
void RegisterAction( TOOL_ACTION* aAction );
/**
* Function UnregisterAction()
@ -100,10 +97,7 @@ public:
*
* @param aAction is the action to be unregistered.
*/
void UnregisterAction( TOOL_ACTION* aAction )
{
m_actionMgr.UnregisterAction( aAction );
}
void UnregisterAction( TOOL_ACTION* aAction );
/**
* Function FindTool()
@ -205,6 +199,14 @@ private:
void dispatchInternal( TOOL_EVENT& aEvent );
/**
* Function dispatchStandardEvents()
* Handles specific events, that are intended for TOOL_MANAGER rather than tools.
* @aEvent is the event to be processed.
* @return False if the event was processed and should not go any further.
*/
bool dispatchStandardEvents( TOOL_EVENT& aEvent );
/**
* Function dispatchActivation()
* Checks if it is a valid activation event and invokes a proper tool.
@ -215,7 +217,8 @@ private:
/**
* Function invokeTool()
* Invokes a tool by sending a proper event.
* Invokes a tool by sending a proper event (in contrary to runTool, which makes the tool run
* for real).
* @param aTool is the tool to be invoked.
*/
bool invokeTool( TOOL_BASE* aTool );
@ -291,7 +294,9 @@ private:
/// Stack of the active tools
std::deque<TOOL_ID> m_activeTools;
ACTION_MANAGER m_actionMgr;
/// Instance of ACTION_MANAGER that handles TOOL_ACTIONs
ACTION_MANAGER* m_actionMgr;
EDA_ITEM* m_model;
KiGfx::VIEW* m_view;
KiGfx::VIEW_CONTROLS* m_viewControls;

View File

@ -84,15 +84,16 @@ public:
/// @copydoc VIEW_CONTROLS::GetCursorPosition()
virtual const VECTOR2D GetCursorPosition() const;
/// Event that forces mouse move event in the dispatcher
/// Event that forces mouse move event in the dispatcher (eg. used in autopanning, when mouse
/// cursor does not move in screen coordinates, but does in world coordinates)
static const wxEventType EVT_REFRESH_MOUSE;
private:
/// Possible states for WX_VIEW_CONTROLS
enum State {
IDLE = 1,
DRAG_PANNING,
AUTO_PANNING,
IDLE = 1, /// Nothing is happening
DRAG_PANNING, /// Panning with mouse button pressed
AUTO_PANNING, /// Panning on approaching borders of the frame
};
/**

View File

@ -22,6 +22,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef ITEM_STATE_H_
#define ITEM_STATE_H_
#include <deque>
#include <class_board_item.h>
/**
* Class ITEM_STATE
*
@ -29,13 +35,6 @@
* the introduced changes. Does not take ownership of modified items, neither takes care of
* refreshing.
*/
#ifndef ITEM_STATE_H_
#define ITEM_STATE_H_
#include <deque>
#include <class_board_item.h>
class ITEM_STATE
{
public:
@ -278,4 +277,3 @@ private:
};
#endif /* ITEM_STATE_H_ */

View File

@ -53,7 +53,7 @@ MOVE_TOOL::~MOVE_TOOL()
void MOVE_TOOL::Reset()
{
// The tool launches upon reception of action event ("pcbnew.InteractiveMove")
Go( &MOVE_TOOL::Main, m_activate.GetEvent() );
Go( &MOVE_TOOL::Main, m_activate.MakeEvent() );
}
@ -115,12 +115,12 @@ int MOVE_TOOL::Main( TOOL_EVENT& aEvent )
{
VECTOR2D cursorPos = getView()->ToWorld( getViewControls()->GetCursorPosition() );
if( evt->Matches( m_rotate.GetEvent() ) ) // got rotation event?
if( evt->IsAction( &m_rotate ) ) // got rotation event?
{
m_state.Rotate( cursorPos, 900.0 );
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY );
}
else if( evt->Matches( m_flip.GetEvent() ) ) // got flip event?
else if( evt->IsAction( &m_flip ) ) // got flip event?
{
m_state.Flip( cursorPos );
m_items.ViewUpdate( VIEW_ITEM::GEOMETRY );

View File

@ -27,8 +27,8 @@
#include <math/vector2d.h>
#include <tool/tool_interactive.h>
#include <tool/item_state.h>
#include <view/view_group.h>
#include "item_state.h"
class BOARD_ITEM;
class SELECTION_TOOL;

View File

@ -68,7 +68,7 @@ void SELECTION_TOOL::Reset()
m_selectedItems.clear();
// The tool launches upon reception of action event ("pcbnew.InteractiveSelection")
Go( &SELECTION_TOOL::Main, m_activate.GetEvent() );
Go( &SELECTION_TOOL::Main, m_activate.MakeEvent() );
}
@ -266,7 +266,7 @@ bool SELECTION_TOOL::selectMultiple()
VIEW* view = getView();
getViewControls()->SetAutoPan( true );
// Those 2 lines remove the blink-in-the-random-place effect
// These 2 lines remove the blink-in-the-random-place effect
m_selArea->SetOrigin( VECTOR2I( 0, 0 ) );
m_selArea->SetEnd( VECTOR2I( 0, 0 ) );
view->Add( m_selArea );
@ -467,7 +467,6 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
break;
}
// All other items are selected only if the layer on which they exist is visible
return board->IsLayerVisible( aItem->GetLayer() );
}
@ -475,12 +474,14 @@ bool SELECTION_TOOL::selectable( const BOARD_ITEM* aItem ) const
bool SELECTION_TOOL::containsSelected( const VECTOR2I& aPoint ) const
{
const unsigned GRIP_MARGIN = 500000;
// Check if the point is located within any of the currently selected items bounding boxes
std::set<BOARD_ITEM*>::iterator it, it_end;
for( it = m_selectedItems.begin(), it_end = m_selectedItems.end(); it != it_end; ++it )
{
BOX2I itemBox = (*it)->ViewBBox();
itemBox.Inflate( 500000 ); // Give some margin for gripping an item
itemBox.Inflate( GRIP_MARGIN ); // Give some margin for gripping an item
if( itemBox.Contains( aPoint ) )
return true;