Schematic object hit testing improvements.

This commit is contained in:
Wayne Stambaugh 2010-12-13 10:59:00 -05:00
parent 95f3d88ba7
commit a8a99abefe
22 changed files with 373 additions and 167 deletions

View File

@ -4,6 +4,17 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2010-dec-13 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================
++common
* Make base marker hit test method const.
++EESchema
* Improve hit testing for schematic components.
* Add initial support for hit test filtering.
* Moved static function CountConnectedItems() into SCH_SCREEN object.
* Add IsConnected() method to SCH_ITEM object.
2010-dec-10 UPDATE Wayne Stambaugh <stambaughw@verizon.net> 2010-dec-10 UPDATE Wayne Stambaugh <stambaughw@verizon.net>
================================================================================ ================================================================================
++All ++All

View File

@ -112,9 +112,7 @@ void MARKER_BASE::SetData( int aErrorCode, const wxPoint& aMarkerPos,
} }
/******************************************************/ bool MARKER_BASE::HitTestMarker( const wxPoint& refPos ) const
bool MARKER_BASE::HitTestMarker( const wxPoint& refPos )
/******************************************************/
{ {
wxPoint rel_pos = refPos - m_Pos; wxPoint rel_pos = refPos - m_Pos;
rel_pos.x /= m_ScalingFactor; rel_pos.x /= m_ScalingFactor;
@ -123,6 +121,7 @@ bool MARKER_BASE::HitTestMarker( const wxPoint& refPos )
return m_ShapeBoundingBox.Inside( rel_pos ); return m_ShapeBoundingBox.Inside( rel_pos );
} }
/** /**
* Function GetBoundingBoxMarker * Function GetBoundingBoxMarker
* returns the orthogonal, bounding box of this object for display purposes. * returns the orthogonal, bounding box of this object for display purposes.

View File

@ -94,3 +94,12 @@ bool SCH_ITEM::Matches( const wxString& aText, wxFindReplaceData& aSearchData )
return text.MakeUpper().Find( searchText.MakeUpper() ) != wxNOT_FOUND; return text.MakeUpper().Find( searchText.MakeUpper() ) != wxNOT_FOUND;
} }
bool SCH_ITEM::IsConnected( const wxPoint& aPosition ) const
{
if( m_Flags & STRUCT_DELETED || m_Flags & SKIP_STRUCT )
return false;
return DoIsConnected( aPosition );
}

View File

@ -769,7 +769,7 @@ static bool IsTerminalPoint( SCH_SCREEN* screen, const wxPoint& pos, int layer )
if( item ) if( item )
return TRUE; return TRUE;
pin = LocateAnyPin( screen->GetDrawItems(), pos, &LibItem ); pin = screen->GetPin( pos, &LibItem );
if( pin && LibItem ) if( pin && LibItem )
{ {

View File

@ -66,7 +66,7 @@ SCH_ITEM* SCH_EDIT_FRAME::SchematicGeneralLocateAndDisplay( bool IncludePin )
break; break;
case SCH_COMPONENT_T: case SCH_COMPONENT_T:
Pin = LocateAnyPin( GetScreen()->GetDrawItems(), GetScreen()->m_Curseur, &LibItem ); Pin = GetScreen()->GetPin( GetScreen()->m_Curseur, &LibItem );
if( Pin ) if( Pin )
break; // Priority is probing a pin first break; // Priority is probing a pin first
LibItem = (SCH_COMPONENT*) DrawStruct; LibItem = (SCH_COMPONENT*) DrawStruct;
@ -74,7 +74,7 @@ SCH_ITEM* SCH_EDIT_FRAME::SchematicGeneralLocateAndDisplay( bool IncludePin )
break; break;
default: default:
Pin = LocateAnyPin( GetScreen()->GetDrawItems(), GetScreen()->m_Curseur, &LibItem ); Pin = GetScreen()->GetPin( GetScreen()->m_Curseur, &LibItem );
break; break;
case LIB_PIN_T: case LIB_PIN_T:

View File

@ -20,52 +20,6 @@
void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList ); void DeleteItemsInList( WinEDA_DrawPanel* panel, PICKED_ITEMS_LIST& aItemsList );
/*
* Count number of items connected to point pos :
* pins, end wire or bus, and junctions if TstJunction == TRUE
* Return this count
*
* Used by SCH_EDIT_FRAME::DeleteConnection()
*/
static int CountConnectedItems( SCH_EDIT_FRAME* frame, SCH_ITEM* ListStruct, wxPoint pos,
bool TstJunction )
{
SCH_ITEM* Struct;
int count = 0;
if( frame->LocatePinEnd( ListStruct, pos ) )
count++;
for( Struct = ListStruct; Struct != NULL; Struct = Struct->Next() )
{
if( Struct->m_Flags & STRUCT_DELETED )
continue;
if( Struct->m_Flags & SKIP_STRUCT )
continue;
if( TstJunction && ( Struct->Type() == SCH_JUNCTION_T ) )
{
#define JUNCTION ( (SCH_JUNCTION*) Struct )
if( JUNCTION->m_Pos == pos )
count++;
#undef JUNCTION
}
if( Struct->Type() != SCH_LINE_T )
continue;
#define SEGM ( (SCH_LINE*) Struct )
if( SEGM->IsEndPoint( pos ) )
count++;
#undef SEGM
}
return count;
}
/* /*
* Mark to "CANDIDATE" all wires or junction connected to "segment" in list * Mark to "CANDIDATE" all wires or junction connected to "segment" in list
* "ListStruct" * "ListStruct"
@ -123,24 +77,23 @@ static bool MarkConnected( SCH_EDIT_FRAME* frame, SCH_ITEM* ListStruct, SCH_LINE
*/ */
void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection ) void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
{ {
wxPoint refpos = GetScreen()->m_Curseur; SCH_SCREEN* screen = GetScreen();
wxPoint refpos = screen->m_Curseur;
SCH_ITEM* DelStruct; SCH_ITEM* DelStruct;
PICKED_ITEMS_LIST pickList; PICKED_ITEMS_LIST pickList;
/* Clear .m_Flags member for all items */ /* Clear .m_Flags member for all items */
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; DelStruct = DelStruct->Next() ) screen->ClearDrawingState();
DelStruct->m_Flags = 0; BreakSegmentOnJunction( screen );
BreakSegmentOnJunction( GetScreen() );
/* Locate all the wires, bus or junction under the mouse cursor, and put /* Locate all the wires, bus or junction under the mouse cursor, and put
* them in a list of items to delete * them in a list of items to delete
*/ */
ITEM_PICKER picker( NULL, UR_DELETED ); ITEM_PICKER picker( NULL, UR_DELETED );
SCH_SCREEN* screen = GetScreen();
// Save the list entry point of this screen // Save the list entry point of this screen
SCH_ITEM* savedItems = screen->GetDrawItems(); SCH_ITEM* savedItems = screen->GetDrawItems();
DelStruct = GetScreen()->GetDrawItems(); DelStruct = screen->GetDrawItems();
while( DelStruct while( DelStruct
&& ( DelStruct = PickStruct( screen->m_Curseur, screen, && ( DelStruct = PickStruct( screen->m_Curseur, screen,
@ -157,13 +110,13 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
screen->SetDrawItems( DelStruct ); screen->SetDrawItems( DelStruct );
} }
GetScreen()->SetDrawItems( savedItems ); screen->SetDrawItems( savedItems );
/* Mark all wires, junctions, .. connected to one of the item to delete /* Mark all wires, junctions, .. connected to one of the item to delete
*/ */
if( DeleteFullConnection ) if( DeleteFullConnection )
{ {
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; for( DelStruct = screen->GetDrawItems(); DelStruct != NULL;
DelStruct = DelStruct->Next() ) DelStruct = DelStruct->Next() )
{ {
if( !(DelStruct->m_Flags & SELECTEDNODE) ) if( !(DelStruct->m_Flags & SELECTEDNODE) )
@ -174,12 +127,12 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
if( DelStruct->Type() != SCH_LINE_T ) if( DelStruct->Type() != SCH_LINE_T )
continue; continue;
MarkConnected( this, GetScreen()->GetDrawItems(), SEGM ); MarkConnected( this, screen->GetDrawItems(), SEGM );
#undef SEGM #undef SEGM
} }
// Search all removable wires (i.e wire with one new dangling end ) // Search all removable wires (i.e wire with one new dangling end )
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; for( DelStruct = screen->GetDrawItems(); DelStruct != NULL;
DelStruct = DelStruct->Next() ) DelStruct = DelStruct->Next() )
{ {
bool noconnect = FALSE; bool noconnect = FALSE;
@ -200,7 +153,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
* an STRUCT_DELETED wire, and now is not connected, the wire can * an STRUCT_DELETED wire, and now is not connected, the wire can
* be deleted */ * be deleted */
EDA_ITEM* removed_struct; EDA_ITEM* removed_struct;
for( removed_struct = GetScreen()->GetDrawItems(); for( removed_struct = screen->GetDrawItems();
removed_struct != NULL; removed_struct != NULL;
removed_struct = removed_struct->Next() ) removed_struct = removed_struct->Next() )
{ {
@ -215,14 +168,13 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
break; break;
} }
if( WIRE && !CountConnectedItems( this, GetScreen()->GetDrawItems(), if( WIRE && !screen->CountConnectedItems( SEGM->m_Start, true ) )
SEGM->m_Start, TRUE ) )
noconnect = TRUE; noconnect = TRUE;
/* Test the SEGM->m_End point: if this point was connected to /* Test the SEGM->m_End point: if this point was connected to
* an STRUCT_DELETED wire, and now is not connected, the wire * an STRUCT_DELETED wire, and now is not connected, the wire
* can be deleted */ * can be deleted */
for( removed_struct = GetScreen()->GetDrawItems(); for( removed_struct = screen->GetDrawItems();
removed_struct != NULL; removed_struct != NULL;
removed_struct = removed_struct->Next() ) removed_struct = removed_struct->Next() )
{ {
@ -234,8 +186,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
break; break;
} }
if( removed_struct && if( removed_struct && !screen->CountConnectedItems( SEGM->m_End, true ) )
!CountConnectedItems( this, GetScreen()->GetDrawItems(), SEGM->m_End, TRUE ) )
noconnect = TRUE; noconnect = TRUE;
DelStruct->m_Flags &= ~SKIP_STRUCT; DelStruct->m_Flags &= ~SKIP_STRUCT;
@ -248,17 +199,16 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
picker.m_PickedItemType = DelStruct->Type(); picker.m_PickedItemType = DelStruct->Type();
pickList.PushItem( picker ); pickList.PushItem( picker );
DelStruct = GetScreen()->GetDrawItems(); DelStruct = screen->GetDrawItems();
} }
#undef SEGM #undef SEGM
} }
// Delete redundant junctions (junctions which connect < 3 end wires // Delete redundant junctions (junctions which connect < 3 end wires
// and no pin are removed) // and no pin are removed)
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; for( DelStruct = screen->GetDrawItems(); DelStruct != NULL;
DelStruct = DelStruct->Next() ) DelStruct = DelStruct->Next() )
{ {
int count;
if( DelStruct->m_Flags & STRUCT_DELETED ) if( DelStruct->m_Flags & STRUCT_DELETED )
continue; continue;
@ -268,9 +218,8 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
if( DelStruct->Type() == SCH_JUNCTION_T ) if( DelStruct->Type() == SCH_JUNCTION_T )
{ {
#define JUNCTION ( (SCH_JUNCTION*) DelStruct ) #define JUNCTION ( (SCH_JUNCTION*) DelStruct )
count = CountConnectedItems( this, GetScreen()->GetDrawItems(),
JUNCTION->m_Pos, FALSE ); if( screen->CountConnectedItems( JUNCTION->m_Pos, false ) <= 2 )
if( count <= 2 )
{ {
DelStruct->m_Flags |= STRUCT_DELETED; DelStruct->m_Flags |= STRUCT_DELETED;
@ -284,8 +233,9 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
} }
// Delete labels attached to wires // Delete labels attached to wires
wxPoint pos = GetScreen()->m_Curseur; wxPoint pos = screen->m_Curseur;
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL;
for( DelStruct = screen->GetDrawItems(); DelStruct != NULL;
DelStruct = DelStruct->Next() ) DelStruct = DelStruct->Next() )
{ {
if( DelStruct->m_Flags & STRUCT_DELETED ) if( DelStruct->m_Flags & STRUCT_DELETED )
@ -295,8 +245,7 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
continue; continue;
GetScreen()->m_Curseur = ( (SCH_TEXT*) DelStruct )->m_Pos; GetScreen()->m_Curseur = ( (SCH_TEXT*) DelStruct )->m_Pos;
EDA_ITEM* TstStruct = PickStruct( GetScreen()->m_Curseur, GetScreen(), EDA_ITEM* TstStruct = PickStruct( screen->m_Curseur, GetScreen(), WIREITEM | BUSITEM );
WIREITEM | BUSITEM );
if( TstStruct && TstStruct->m_Flags & STRUCT_DELETED ) if( TstStruct && TstStruct->m_Flags & STRUCT_DELETED )
{ {
@ -309,12 +258,10 @@ void SCH_EDIT_FRAME::DeleteConnection( bool DeleteFullConnection )
} }
} }
GetScreen()->m_Curseur = pos; screen->m_Curseur = pos;
} }
for( DelStruct = GetScreen()->GetDrawItems(); DelStruct != NULL; screen->ClearDrawingState();
DelStruct = DelStruct->Next() )
DelStruct->m_Flags = 0;
if( pickList.GetCount() ) if( pickList.GetCount() )
{ {
@ -356,8 +303,7 @@ bool LocateAndDeleteItem( SCH_EDIT_FRAME* frame, wxDC* DC )
if( DelStruct == NULL ) if( DelStruct == NULL )
DelStruct = PickStruct( screen->m_Curseur, screen, DRAWITEM ); DelStruct = PickStruct( screen->m_Curseur, screen, DRAWITEM );
if( DelStruct == NULL ) if( DelStruct == NULL )
DelStruct = PickStruct( screen->m_Curseur, screen, DelStruct = PickStruct( screen->m_Curseur, screen, TEXTITEM | LABELITEM );
TEXTITEM | LABELITEM );
if( DelStruct == NULL ) if( DelStruct == NULL )
DelStruct = PickStruct( screen->m_Curseur, screen, LIBITEM ); DelStruct = PickStruct( screen->m_Curseur, screen, LIBITEM );
if( DelStruct == NULL ) if( DelStruct == NULL )

View File

@ -20,8 +20,7 @@
static SCH_ITEM* LastSnappedStruct = NULL; static SCH_ITEM* LastSnappedStruct = NULL;
static bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, static bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList );
SCH_ITEM* DrawList, double aScaleFactor );
/** /**
@ -42,9 +41,9 @@ SCH_COMPONENT* LocateSmallestComponent( SCH_SCREEN* Screen )
while( DrawList ) while( DrawList )
{ {
if( !SnapPoint2( Screen->m_MousePosition, LIBITEM, DrawList, Screen->GetZoom() ) ) if( !SnapPoint2( Screen->m_MousePosition, LIBITEM, DrawList ) )
{ {
if( !SnapPoint2( Screen->m_Curseur, LIBITEM, DrawList, Screen->GetScalingFactor() ) ) if( !SnapPoint2( Screen->m_Curseur, LIBITEM, DrawList ) )
break; break;
} }
@ -106,7 +105,7 @@ SCH_ITEM* PickStruct( const wxPoint& refpos, SCH_SCREEN* screen, int SearchMask
if( screen == NULL || screen->GetDrawItems() == NULL ) if( screen == NULL || screen->GetDrawItems() == NULL )
return NULL; return NULL;
if( SnapPoint2( refpos, SearchMask, screen->GetDrawItems(), screen->GetScalingFactor() ) ) if( SnapPoint2( refpos, SearchMask, screen->GetDrawItems() ) )
{ {
return LastSnappedStruct; return LastSnappedStruct;
} }
@ -161,7 +160,7 @@ int PickItemsInBlock( BLOCK_SELECTOR& aBlock, SCH_SCREEN* aScreen )
* a point. This variable is global to this module only (see above). * * a point. This variable is global to this module only (see above). *
* The routine returns true if point was snapped. * * The routine returns true if point was snapped. *
*****************************************************************************/ *****************************************************************************/
bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList, double aScaleFactor ) bool SnapPoint2( const wxPoint& aPosRef, int SearchMask, SCH_ITEM* DrawList )
{ {
for( ; DrawList != NULL; DrawList = DrawList->Next() ) for( ; DrawList != NULL; DrawList = DrawList->Next() )
{ {
@ -367,40 +366,27 @@ SCH_SHEET_PIN* LocateSheetLabel( SCH_SHEET* Sheet, const wxPoint& pos )
LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, const wxPoint& RefPos, SCH_COMPONENT** libpart ) LIB_PIN* LocateAnyPin( SCH_ITEM* DrawList, const wxPoint& RefPos, SCH_COMPONENT** libpart )
{ {
SCH_ITEM* DrawStruct; SCH_ITEM* item;
LIB_COMPONENT* Entry; SCH_COMPONENT* component = NULL;
SCH_COMPONENT* schItem = NULL; LIB_PIN* pin = NULL;
LIB_PIN* Pin = NULL;
for( DrawStruct = DrawList; DrawStruct != NULL; DrawStruct = DrawStruct->Next() ) for( item = DrawList; item != NULL; item = item->Next() )
{ {
if( DrawStruct->Type() != SCH_COMPONENT_T ) if( item->Type() != SCH_COMPONENT_T )
continue; continue;
schItem = (SCH_COMPONENT*) DrawStruct; component = (SCH_COMPONENT*) item;
Entry = CMP_LIBRARY::FindLibraryComponent( schItem->m_ChipName );
if( Entry == NULL ) pin = (LIB_PIN*) component->GetDrawItem( RefPos, LIB_PIN_T );
continue;
/* we use LocateDrawItem to locate pins. but this function suppose a if( pin )
* component.
* at 0,0 location
* So we must calculate the ref position relative to the component
*/
wxPoint libPos = RefPos - schItem->m_Pos;
Pin = (LIB_PIN*) Entry->LocateDrawItem( schItem->m_Multi,
schItem->m_Convert,
LIB_PIN_T,
libPos, schItem->m_Transform );
if( Pin )
break; break;
} }
if( libpart ) if( libpart )
*libpart = schItem; *libpart = component;
return Pin; return pin;
} }

View File

@ -1361,14 +1361,7 @@ bool SCH_COMPONENT::Load( LINE_READER& aLine, wxString& aErrorMsg )
} }
/** EDA_Rect SCH_COMPONENT::GetBodyBoundingBox() const
* Function GetBoundaryBox
* returns the orthogonal, bounding box of this object for display purposes.
* This box should be an enclosing perimeter for graphic items and pins.
* this include only fields defined in library
* use GetBoundingBox() to include fields in schematic
*/
EDA_Rect SCH_COMPONENT::GetBoundingBox() const
{ {
LIB_COMPONENT* Entry = CMP_LIBRARY::FindLibraryComponent( m_ChipName ); LIB_COMPONENT* Entry = CMP_LIBRARY::FindLibraryComponent( m_ChipName );
EDA_Rect bBox; EDA_Rect bBox;
@ -1406,11 +1399,25 @@ EDA_Rect SCH_COMPONENT::GetBoundingBox() const
bBox.SetHeight( y2 - y1 ); bBox.SetHeight( y2 - y1 );
bBox.Offset( m_Pos ); bBox.Offset( m_Pos );
return bBox;
}
// Include BoundingBoxes of fields
/**
* Function GetBoundaryBox
* returns the orthogonal, bounding box of this object for display purposes.
* This box should be an enclosing perimeter for graphic items and pins.
* this include only fields defined in library
* use GetBoundingBox() to include fields in schematic
*/
EDA_Rect SCH_COMPONENT::GetBoundingBox() const
{
EDA_Rect bBox = GetBodyBoundingBox();
// Include BoundingBoxes of fields if they are visible and not empty.
for( int ii = 0; ii < GetFieldCount(); ii++ ) for( int ii = 0; ii < GetFieldCount(); ii++ )
{ {
if( !GetField( ii )->IsVisible() ) if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() )
continue; continue;
bBox.Merge( GetField( ii )->GetBoundingBox() ); bBox.Merge( GetField( ii )->GetBoundingBox() );
@ -1441,12 +1448,15 @@ void SCH_COMPONENT::DisplayInfo( WinEDA_DrawFrame* frame )
msg = _( "Power symbol" ); msg = _( "Power symbol" );
else else
msg = _( "Name" ); msg = _( "Name" );
frame->AppendMsgPanel( msg, GetField( VALUE )->m_Text, DARKCYAN ); frame->AppendMsgPanel( msg, GetField( VALUE )->m_Text, DARKCYAN );
// Display component reference in library and library // Display component reference in library and library
frame->AppendMsgPanel( _( "Component" ), m_ChipName, BROWN ); frame->AppendMsgPanel( _( "Component" ), m_ChipName, BROWN );
if( alias->GetName() != root_component->GetName() ) if( alias->GetName() != root_component->GetName() )
frame->AppendMsgPanel( _( "Alias of" ), root_component->GetName(), BROWN ); frame->AppendMsgPanel( _( "Alias of" ), root_component->GetName(), BROWN );
frame->AppendMsgPanel( _( "Library" ), alias->GetLibraryName(), BROWN ); frame->AppendMsgPanel( _( "Library" ), alias->GetLibraryName(), BROWN );
// Display description of the component, and keywords found in lib // Display description of the component, and keywords found in lib
@ -1664,13 +1674,50 @@ void SCH_COMPONENT::GetConnectionPoints( vector< wxPoint >& aPoints ) const
} }
bool SCH_COMPONENT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const LIB_DRAW_ITEM* SCH_COMPONENT::GetDrawItem( const wxPoint& aPosition, KICAD_T aType )
{ {
EDA_Rect rect = GetBoundingBox(); LIB_COMPONENT* component = CMP_LIBRARY::FindLibraryComponent( m_ChipName );
rect.Inflate( aAccuracy ); if( component == NULL )
return NULL;
return rect.Inside( aPoint ); // Calculate the position relative to the component.
wxPoint libPosition = aPosition - m_Pos;
return component->LocateDrawItem( m_Multi, m_Convert, aType, libPosition, m_Transform );
}
bool SCH_COMPONENT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
EDA_Rect bBox;
if( aFilter & FIELD_T )
{
// Test the bounding boxes of fields if they are visible and not empty.
for( int ii = 0; ii < GetFieldCount(); ii++ )
{
if( !GetField( ii )->IsVisible() || GetField( ii )->IsVoid() )
continue;
bBox = GetField( ii )->GetBoundingBox();
bBox.Inflate( aAccuracy );
if( bBox.Inside( aPoint ) )
return true;
}
}
if( aFilter & COMPONENT_T )
{
bBox = GetBodyBoundingBox();
bBox.Inflate( aAccuracy );
if( bBox.Inside( aPoint ) )
return true;
}
return false;
} }
@ -1685,3 +1732,19 @@ bool SCH_COMPONENT::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccu
return rect.Intersects( GetBoundingBox() ); return rect.Intersects( GetBoundingBox() );
} }
bool SCH_COMPONENT::DoIsConnected( const wxPoint& aPosition ) const
{
vector< wxPoint > pts;
GetConnectionPoints( pts );
for( size_t i = 0; i < pts.size(); i++ )
{
if( pts[i] == aPosition )
return true;
}
return false;
}

View File

@ -12,6 +12,7 @@
class SCH_SHEET_PATH; class SCH_SHEET_PATH;
class LIB_DRAW_ITEM;
class LIB_PIN; class LIB_PIN;
class LIB_COMPONENT; class LIB_COMPONENT;
@ -86,6 +87,8 @@ private:
void Init( const wxPoint& pos = wxPoint( 0, 0 ) ); void Init( const wxPoint& pos = wxPoint( 0, 0 ) );
EDA_Rect GetBodyBoundingBox() const;
public: public:
SCH_COMPONENT( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = NULL ); SCH_COMPONENT( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = NULL );
@ -367,6 +370,17 @@ public:
virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const;
/**
* Function GetDrawItem().
* Return the component library item at \a aPosition that is part of this component.
*
* @param aPosition - Schematic position of the component library object.
* @param aType - Type of component library object to find or any if set to TYPE_NOT_INIT.
* @return A pointer to the component library object if found, otherwise NULL.
*/
LIB_DRAW_ITEM* GetDrawItem( const wxPoint& aPosition, KICAD_T aType = TYPE_NOT_INIT );
#if defined(DEBUG) #if defined(DEBUG)
/** /**
@ -381,8 +395,9 @@ public:
#endif #endif
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
virtual bool DoIsConnected( const wxPoint& aPosition ) const;
}; };

View File

@ -246,8 +246,11 @@ void SCH_BUS_ENTRY::GetConnectionPoints( vector< wxPoint >& aPoints ) const
} }
bool SCH_BUS_ENTRY::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_BUS_ENTRY::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & BUS_ENTRY_T ) )
return false;
return TestSegmentHit( aPoint, m_Pos, m_End(), aAccuracy ); return TestSegmentHit( aPoint, m_Pos, m_End(), aAccuracy );
} }
@ -421,8 +424,11 @@ void SCH_JUNCTION::Show( int nestLevel, std::ostream& os )
#endif #endif
bool SCH_JUNCTION::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_JUNCTION::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & JUNCTION_T ) )
return false;
EDA_Rect rect = GetBoundingBox(); EDA_Rect rect = GetBoundingBox();
rect.Inflate( aAccuracy ); rect.Inflate( aAccuracy );
@ -444,6 +450,12 @@ bool SCH_JUNCTION::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccur
} }
bool SCH_JUNCTION::DoIsConnected( const wxPoint& aPosition ) const
{
return m_Pos == aPosition;
}
/************************/ /************************/
/* class SCH_NO_CONNECT */ /* class SCH_NO_CONNECT */
/************************/ /************************/
@ -593,8 +605,11 @@ void SCH_NO_CONNECT::GetConnectionPoints( vector< wxPoint >& aPoints ) const
} }
bool SCH_NO_CONNECT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_NO_CONNECT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & NO_CONNECT_T ) )
return false;
int delta = ( ( m_Size.x + g_DrawDefaultLineThickness ) / 2 ) + aAccuracy; int delta = ( ( m_Size.x + g_DrawDefaultLineThickness ) / 2 ) + aAccuracy;
wxPoint dist = aPoint - m_Pos; wxPoint dist = aPoint - m_Pos;
@ -1007,9 +1022,22 @@ void SCH_LINE::GetConnectionPoints( vector< wxPoint >& aPoints ) const
} }
bool SCH_LINE::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_LINE::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
return TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ); if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) )
return false;
if( ( ( aFilter & DRAW_ITEM_T ) && ( m_Layer == LAYER_NOTES ) )
|| ( ( aFilter & WIRE_T ) && ( m_Layer == LAYER_WIRE ) )
|| ( ( aFilter & BUS_T ) && ( m_Layer == LAYER_BUS ) ) )
{
if( aFilter & EXCLUDE_WIRE_BUS_ENDPOINTS && IsEndPoint( aPoint )
|| aFilter & WIRE_BUS_ENDPOINTS_ONLY && !IsEndPoint( aPoint )
|| TestSegmentHit( aPoint, m_Start, m_End, aAccuracy ) )
return true;
}
return false;
} }
@ -1026,6 +1054,15 @@ bool SCH_LINE::DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy
} }
bool SCH_LINE::DoIsConnected( const wxPoint& aPosition ) const
{
if( m_Layer != LAYER_WIRE && m_Layer != LAYER_BUS )
return false;
return IsEndPoint( aPosition );
}
/**********************/ /**********************/
/* Class SCH_POLYLINE */ /* Class SCH_POLYLINE */
/**********************/ /**********************/
@ -1219,8 +1256,11 @@ void SCH_POLYLINE::Rotate( wxPoint rotationPoint )
} }
bool SCH_POLYLINE::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_POLYLINE::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & ( DRAW_ITEM_T | WIRE_T | BUS_T ) ) )
return false;
for( size_t i = 0; i < m_PolyPoints.size() - 1; i++ ) for( size_t i = 0; i < m_PolyPoints.size() - 1; i++ )
{ {
if( TestSegmentHit( aPoint, m_PolyPoints[i], m_PolyPoints[i + 1], aAccuracy ) ) if( TestSegmentHit( aPoint, m_PolyPoints[i], m_PolyPoints[i + 1], aAccuracy ) )

View File

@ -131,8 +131,9 @@ public:
#endif #endif
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
virtual bool DoIsConnected( const wxPoint& aPosition ) const;
}; };
@ -215,7 +216,7 @@ public:
virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const;
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
}; };
@ -311,7 +312,7 @@ public:
virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const; virtual void GetConnectionPoints( vector< wxPoint >& aPoints ) const;
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
}; };
@ -400,7 +401,7 @@ public:
virtual void Rotate( wxPoint rotationPoint ); virtual void Rotate( wxPoint rotationPoint );
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
}; };
@ -486,8 +487,9 @@ public:
#endif #endif
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
virtual bool DoIsConnected( const wxPoint& aPosition ) const;
}; };

View File

@ -192,3 +192,13 @@ bool SCH_MARKER::IsSelectStateChanged( const wxRect& aRect )
return previousState != IsSelected(); return previousState != IsSelected();
} }
bool SCH_MARKER::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
if( !( aFilter & MARKER_T ) )
return false;
return HitTestMarker( aPoint );
}

View File

@ -52,16 +52,6 @@ public:
*/ */
bool Save( FILE* aFile ) const; bool Save( FILE* aFile ) const;
/**
* Function HitTest
* @return true if the point aPosRef is within item area
* @param aPosRef = a wxPoint to test
*/
bool HitTest( const wxPoint& aPosRef )
{
return HitTestMarker( aPosRef );
}
/** /**
* Function GetBoundingBox * Function GetBoundingBox
* returns the orthogonal, bounding box of this object for display purposes. * returns the orthogonal, bounding box of this object for display purposes.
@ -113,6 +103,8 @@ public:
void Show( int nestLevel, std::ostream& os ); void Show( int nestLevel, std::ostream& os );
#endif #endif
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
}; };
#endif /* _TYPE_SCH_MARKER_H_ */ #endif /* _TYPE_SCH_MARKER_H_ */

View File

@ -15,6 +15,7 @@
#include "class_library.h" #include "class_library.h"
#include "sch_items.h" #include "sch_items.h"
#include "sch_sheet.h" #include "sch_sheet.h"
#include "sch_component.h"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
@ -376,6 +377,50 @@ void SCH_SCREEN::ClearDrawingState()
} }
LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent )
{
SCH_ITEM* item;
SCH_COMPONENT* component = NULL;
LIB_PIN* pin = NULL;
for( item = GetDrawItems(); item != NULL; item = item->Next() )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
component = (SCH_COMPONENT*) item;
pin = (LIB_PIN*) component->GetDrawItem( aPosition, LIB_PIN_T );
if( pin )
break;
}
if( aComponent )
*aComponent = component;
return pin;
}
int SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const
{
SCH_ITEM* item;
int count = 0;
for( item = GetDrawItems(); item != NULL; item = item->Next() )
{
if( item->Type() == SCH_JUNCTION_T && !aTestJunctions )
continue;
if( item->IsConnected( aPos ) )
count++;
}
return count;
}
/******************************************************************/ /******************************************************************/
/* Class SCH_SCREENS to handle the list of screens in a hierarchy */ /* Class SCH_SCREENS to handle the list of screens in a hierarchy */
/******************************************************************/ /******************************************************************/

View File

@ -1136,8 +1136,11 @@ void SCH_SHEET::GetConnectionPoints( vector< wxPoint >& aPoints ) const
} }
bool SCH_SHEET::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_SHEET::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & SHEET_T ) )
return false;
EDA_Rect rect = GetBoundingBox(); EDA_Rect rect = GetBoundingBox();
rect.Inflate( aAccuracy ); rect.Inflate( aAccuracy );

View File

@ -524,7 +524,7 @@ protected:
void renumberLabels(); void renumberLabels();
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
}; };

View File

@ -671,8 +671,11 @@ EDA_Rect SCH_TEXT::GetBoundingBox() const
} }
bool SCH_TEXT::DoHitTest( const wxPoint& aPoint, int aAccuracy ) const bool SCH_TEXT::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{ {
if( !( aFilter & TEXT_T ) )
return false;
return TextHitTest( aPoint, aAccuracy ); return TextHitTest( aPoint, aAccuracy );
} }
@ -918,6 +921,15 @@ EDA_Rect SCH_LABEL::GetBoundingBox() const
} }
bool SCH_LABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
if( !( aFilter & LABEL_T ) )
return false;
return TextHitTest( aPoint, aAccuracy );
}
SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) : SCH_GLOBALLABEL::SCH_GLOBALLABEL( const wxPoint& pos, const wxString& text ) :
SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T ) SCH_TEXT( pos, text, SCH_GLOBAL_LABEL_T )
{ {
@ -1358,6 +1370,15 @@ EDA_Rect SCH_GLOBALLABEL::GetBoundingBox() const
} }
bool SCH_GLOBALLABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
if( !( aFilter & LABEL_T ) )
return false;
return TextHitTest( aPoint, aAccuracy );
}
SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) : SCH_HIERLABEL::SCH_HIERLABEL( const wxPoint& pos, const wxString& text, KICAD_T aType ) :
SCH_TEXT( pos, text, aType ) SCH_TEXT( pos, text, aType )
{ {
@ -1719,3 +1740,12 @@ void SCH_HIERLABEL::Rotate( wxPoint rotationPoint )
RotatePoint( &m_Pos, rotationPoint, 900 ); RotatePoint( &m_Pos, rotationPoint, 900 );
SetSchematicTextOrientation( (GetSchematicTextOrientation() + 3) % 4 ); SetSchematicTextOrientation( (GetSchematicTextOrientation() + 3) % 4 );
} }
bool SCH_HIERLABEL::DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
if( !( aFilter & LABEL_T ) )
return false;
return TextHitTest( aPoint, aAccuracy );
}

View File

@ -196,7 +196,7 @@ public:
#endif #endif
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const; virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const; virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const;
}; };
@ -273,6 +273,9 @@ public:
* @return True if the schematic label loaded successfully. * @return True if the schematic label loaded successfully.
*/ */
virtual bool Load( LINE_READER& aLine, wxString& aErrorMsg ); virtual bool Load( LINE_READER& aLine, wxString& aErrorMsg );
private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
}; };
@ -363,6 +366,9 @@ public:
virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_Y( int aYaxis_position );
virtual void Mirror_X( int aXaxis_position ); virtual void Mirror_X( int aXaxis_position );
virtual void Rotate( wxPoint rotationPoint ); virtual void Rotate( wxPoint rotationPoint );
private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
}; };
@ -455,6 +461,9 @@ public:
virtual void Mirror_Y( int aYaxis_position ); virtual void Mirror_Y( int aYaxis_position );
virtual void Mirror_X( int aXaxis_position ); virtual void Mirror_X( int aXaxis_position );
virtual void Rotate( wxPoint rotationPoint ); virtual void Rotate( wxPoint rotationPoint );
private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const;
}; };
#endif /* CLASS_TEXT_LABEL_H */ #endif /* CLASS_TEXT_LABEL_H */

View File

@ -178,7 +178,7 @@ public:
* @param ref_pos A wxPoint to test * @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false * @return bool - true if a hit, else false
*/ */
bool HitTestMarker( const wxPoint& ref_pos ); bool HitTestMarker( const wxPoint& ref_pos ) const;
/** /**
* Function GetBoundingBoxMarker * Function GetBoundingBoxMarker

View File

@ -10,6 +10,10 @@
#include "class_base_screen.h" #include "class_base_screen.h"
class LIB_PIN;
class SCH_COMPONENT;
/* Max number of sheets in a hierarchy project: */ /* Max number of sheets in a hierarchy project: */
#define NB_MAX_SHEET 500 #define NB_MAX_SHEET 500
@ -107,6 +111,10 @@ public:
*/ */
void ClearDrawingState(); void ClearDrawingState();
int CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const;
LIB_PIN* GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent = NULL );
virtual void AddItem( SCH_ITEM* aItem ) { BASE_SCREEN::AddItem( (EDA_ITEM*) aItem ); } virtual void AddItem( SCH_ITEM* aItem ) { BASE_SCREEN::AddItem( (EDA_ITEM*) aItem ); }
virtual void InsertItem( EDA_ITEMS::iterator aIter, SCH_ITEM* aItem ) virtual void InsertItem( EDA_ITEMS::iterator aIter, SCH_ITEM* aItem )
{ {

View File

@ -17,6 +17,27 @@ class SCH_EDIT_FRAME;
class wxFindReplaceData; class wxFindReplaceData;
// Schematic item filter mask for hit test objects in schematic editor.
enum SCH_FILTER_T {
COMPONENT_T = 0x0001,
WIRE_T = 0X0002,
BUS_T = 0x0004,
BUS_ENTRY_T = 0x0008,
JUNCTION_T = 0x0010,
DRAW_ITEM_T = 0x0020,
TEXT_T = 0x0040,
LABEL_T = 0x0080,
SHEET_T = 0x0100,
MARKER_T = 0x0200,
NO_CONNECT_T = 0x0400,
SHEET_LABEL_T = 0x0800,
FIELD_T = 0x1000,
EXCLUDE_ENDPOINTS_T = 0x2000,
ENDPOINTS_ONLY_T = 0x4000,
NO_FILTER_T = 0xFFFF
};
enum DANGLING_END_T { enum DANGLING_END_T {
UNKNOWN = 0, UNKNOWN = 0,
WIRE_START_END, WIRE_START_END,
@ -223,17 +244,28 @@ public:
*/ */
void ClearConnections() { m_connections.release(); } void ClearConnections() { m_connections.release(); }
/**
* Function IsConnected().
* Test \a aPosition to see if it is connected to this schematic object.
*
* @param aPosition - Position to test for connection.
* @return True if connection to \a aPosition exists.
*/
bool IsConnected( const wxPoint& aPoint ) const;
/** /**
* Function HitTest(). * Function HitTest().
* Test if \a aPoint is contained within the bounding box or on an item. * Test if \a aPoint is contained within the bounding box or on an item.
* *
* @param aPoint - Point to test. * @param aPoint - Point to test.
* @param aAccuracy - Increase the item bounding box by this amount. * @param aAccuracy - Increase the item bounding box by this amount.
* @return True if \aPoint is within the item. * @param aFilter - Mask to provide more granular hit testing. See enum SCH_FILTER_T.
* @return True if \aPoint is within the item and meets the filter criteria.
*/ */
bool HitTest( const wxPoint& aPoint, int aAccuracy = 0 ) const bool HitTest( const wxPoint& aPoint, int aAccuracy = 0,
SCH_FILTER_T aFilter = NO_FILTER_T ) const
{ {
return DoHitTest( aPoint, aAccuracy ); return DoHitTest( aPoint, aAccuracy, aFilter );
} }
/** /**
@ -257,11 +289,17 @@ public:
* http://www.gotw.ca/publications/mill18.htm. * http://www.gotw.ca/publications/mill18.htm.
*/ */
private: private:
virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy ) const { return false; } virtual bool DoHitTest( const wxPoint& aPoint, int aAccuracy, SCH_FILTER_T aFilter ) const
{
return false;
}
virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const virtual bool DoHitTest( const EDA_Rect& aRect, bool aContained, int aAccuracy ) const
{ {
return false; return false;
} }
virtual bool DoIsConnected( const wxPoint& aPosition ) const { return false; }
}; };
#endif /* SCH_ITEM_STRUCT_H */ #endif /* SCH_ITEM_STRUCT_H */