Replace EESchema DLIST

This moves EESchema DLIST structures to rtree.  These changes are more
fundamental than the pcbnew changes from 9163ac543 888c01d11 d1877d7c1
and 961b22d60 as eeschema operations were more dependent on passing
drawing list references around with SCH_ITEM* objects.
This commit is contained in:
Seth Hillbrand 2019-06-25 16:39:58 -07:00
parent a8d9fcb4e0
commit 6e5e453d0d
70 changed files with 2347 additions and 2216 deletions

View File

@ -127,7 +127,7 @@ EDA_ITEM* EDA_ITEM::Clone() const
// see base_struct.h
// many classes inherit this method, be careful:
//TODO(snh): Fix this to use std::set instead of C-style vector
//TODO (snh): Fix this to use std::set instead of C-style vector
SEARCH_RESULT EDA_ITEM::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] )
{
#if 0 && defined(DEBUG)

View File

@ -25,6 +25,7 @@
#include <kiway.h>
#include <kiway_holder.h>
#include <project.h>
#if defined(DEBUG)
#include <typeinfo>

View File

@ -266,18 +266,21 @@ protected:
*/
void get_possible_colliders( std::vector<SCH_ITEM*>& aItems )
{
wxASSERT_MSG( m_screen, "get_possible_colliders() with null m_screen" );
for( SCH_ITEM* item = m_screen->GetDrawItems(); item; item = item->Next() )
wxCHECK_RET( m_screen, "get_possible_colliders() with null m_screen" );
for( auto item : m_screen->Items().Overlapping( m_component->GetBoundingBox() ) )
{
if( SCH_COMPONENT* comp = dynamic_cast<SCH_COMPONENT*>( item ) )
{
if( comp == m_component ) continue;
if( comp == m_component )
continue;
std::vector<SCH_FIELD*> fields;
comp->GetFields( fields, /* aVisibleOnly */ true );
for( SCH_FIELD* field : fields )
aItems.push_back( field );
}
aItems.push_back( item );
}
}

View File

@ -23,23 +23,28 @@
*/
#include <fctsys.h>
#include <sch_edit_frame.h>
#include <lib_item.h>
#include <core/kicad_algo.h>
#include <eeschema_id.h>
#include <general.h>
#include <lib_item.h>
#include <sch_bus_entry.h>
#include <sch_component.h>
#include <sch_edit_frame.h>
#include <sch_junction.h>
#include <sch_line.h>
#include <sch_no_connect.h>
#include <sch_component.h>
#include <sch_screen.h>
#include <sch_sheet.h>
#include <sch_view.h>
#include <tool/tool_manager.h>
#include <tools/ee_actions.h>
#include <tools/ee_selection_tool.h>
#include <tool/tool_manager.h>
void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnections )
{
for( SCH_ITEM* item = GetScreen()->GetDrawItems(); item; item = item->Next() )
for( auto item : GetScreen()->Items() )
{
// Avoid items that are changing
if( !( item->GetEditFlags() & ( IS_DRAGGED | IS_MOVED | IS_DELETED ) ) )
@ -50,7 +55,8 @@ void SCH_EDIT_FRAME::GetSchematicConnections( std::vector< wxPoint >& aConnectio
std::sort( aConnections.begin(), aConnections.end(),
[]( const wxPoint& a, const wxPoint& b ) -> bool
{ return a.x < b.x || (a.x == b.x && a.y < b.y); } );
aConnections.erase( unique( aConnections.begin(), aConnections.end() ), aConnections.end() );
aConnections.erase(
std::unique( aConnections.begin(), aConnections.end() ), aConnections.end() );
}
@ -59,16 +65,17 @@ bool SCH_EDIT_FRAME::TestDanglingEnds()
std::vector<DANGLING_END_ITEM> endPoints;
bool hasStateChanged = false;
for( SCH_ITEM* item = GetScreen()->GetDrawList().begin(); item; item = item->Next() )
for( auto item : GetScreen()->Items() )
item->GetEndPoints( endPoints );
for( SCH_ITEM* item = GetScreen()->GetDrawList().begin(); item; item = item->Next() )
for( auto item : GetScreen()->Items() )
{
if( item->UpdateDanglingState( endPoints ) )
{
GetCanvas()->GetView()->Update( item, KIGFX::REPAINT );
hasStateChanged = true;
}
item->GetEndPoints( endPoints );
}
return hasStateChanged;
@ -77,25 +84,22 @@ bool SCH_EDIT_FRAME::TestDanglingEnds()
bool SCH_EDIT_FRAME::TrimWire( const wxPoint& aStart, const wxPoint& aEnd )
{
SCH_LINE* line;
SCH_ITEM* next_item = NULL;
bool retval = false;
if( aStart == aEnd )
return retval;
for( SCH_ITEM* item = GetScreen()->GetDrawItems(); item; item = next_item )
for( auto item : GetScreen()->Items().OfType( SCH_LINE_T ) )
{
next_item = item->Next();
SCH_LINE* line = static_cast<SCH_LINE*>( item );
if( line->GetLayer() != LAYER_WIRE )
continue;
// Don't remove wires that are already deleted or are currently being dragged
if( item->GetEditFlags() & ( STRUCT_DELETED | IS_DRAGGED | IS_MOVED | SKIP_STRUCT ) )
if( line->GetEditFlags() & ( STRUCT_DELETED | IS_DRAGGED | IS_MOVED | SKIP_STRUCT ) )
continue;
if( item->Type() != SCH_LINE_T || item->GetLayer() != LAYER_WIRE )
continue;
line = (SCH_LINE*) item;
if( !IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aStart ) ||
!IsPointOnSegment( line->GetStartPoint(), line->GetEndPoint(), aEnd ) )
{
@ -134,113 +138,131 @@ bool SCH_EDIT_FRAME::TrimWire( const wxPoint& aStart, const wxPoint& aEnd )
bool SCH_EDIT_FRAME::SchematicCleanUp( SCH_SCREEN* aScreen )
{
SCH_ITEM* item = NULL;
SCH_ITEM* secondItem = NULL;
PICKED_ITEMS_LIST itemList;
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
PICKED_ITEMS_LIST itemList;
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
std::vector<SCH_ITEM*> deletedItems;
std::vector<SCH_LINE*> lines;
std::vector<SCH_JUNCTION*> junctions;
std::vector<SCH_NO_CONNECT*> ncs;
if( aScreen == nullptr )
aScreen = GetScreen();
auto remove_item = [ &itemList ]( SCH_ITEM* aItem ) -> void
{
auto remove_item = [&itemList, &deletedItems]( SCH_ITEM* aItem ) -> void {
aItem->SetFlags( STRUCT_DELETED );
itemList.PushItem( ITEM_PICKER( aItem, UR_DELETED ) );
deletedItems.push_back( aItem );
};
BreakSegmentsOnJunctions( aScreen );
for( item = aScreen->GetDrawItems(); item; item = item->Next() )
for( auto item : aScreen->Items().OfType( SCH_LINE_T ) )
{
if( ( item->Type() != SCH_LINE_T )
&& ( item->Type() != SCH_JUNCTION_T )
&& ( item->Type() != SCH_NO_CONNECT_T ) )
continue;
if( item->GetLayer() == LAYER_WIRE )
lines.push_back( static_cast<SCH_LINE*>( item ) );
}
if( item->GetEditFlags() & STRUCT_DELETED )
continue;
// Remove unneeded junctions
if( ( item->Type() == SCH_JUNCTION_T )
&& ( !aScreen->IsJunctionNeeded( item->GetPosition() ) ) )
{
for( auto item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
{
if( !aScreen->IsJunctionNeeded( item->GetPosition() ) )
remove_item( item );
else
junctions.push_back( static_cast<SCH_JUNCTION*>( item ) );
}
for( auto item : aScreen->Items().OfType( SCH_NO_CONNECT_T ) )
{
ncs.push_back( static_cast<SCH_NO_CONNECT*>( item ) );
}
alg::for_all_pairs(
junctions.begin(), junctions.end(), [&]( SCH_JUNCTION* aFirst, SCH_JUNCTION* aSecond ) {
if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
|| ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
return;
if( aFirst->GetPosition() == aSecond->GetPosition() )
remove_item( aSecond );
} );
alg::for_all_pairs(
ncs.begin(), ncs.end(), [&]( SCH_NO_CONNECT* aFirst, SCH_NO_CONNECT* aSecond ) {
if( ( aFirst->GetEditFlags() & STRUCT_DELETED )
|| ( aSecond->GetEditFlags() & STRUCT_DELETED ) )
return;
if( aFirst->GetPosition() == aSecond->GetPosition() )
remove_item( aSecond );
} );
for( auto it1 = lines.begin(); it1 != lines.end(); ++it1 )
{
SCH_LINE* firstLine = *it1;
if( firstLine->GetEditFlags() & STRUCT_DELETED )
continue;
if( firstLine->IsNull() )
{
remove_item( firstLine );
continue;
}
// Remove zero-length lines
if( item->Type() == SCH_LINE_T
&& ( (SCH_LINE*) item )->IsNull() )
{
remove_item( item );
continue;
}
auto it2 = it1;
for( secondItem = item->Next(); secondItem; secondItem = secondItem->Next() )
for( ++it2; it2 != lines.end(); ++it2 )
{
if( item->Type() != secondItem->Type()
|| ( secondItem->GetEditFlags() & STRUCT_DELETED ) )
SCH_LINE* secondLine = *it2;
bool needed = false;
if( secondLine->GetFlags() & STRUCT_DELETED )
continue;
// Merge overlapping lines
if( item->Type() == SCH_LINE_T )
{
SCH_LINE* firstLine = (SCH_LINE*) item;
SCH_LINE* secondLine = (SCH_LINE*) secondItem;
SCH_LINE* line = NULL;
bool needed = false;
if( !secondLine->IsParallel( firstLine )
|| secondLine->GetLineStyle() != firstLine->GetLineStyle()
|| secondLine->GetLineColor() != firstLine->GetLineColor()
|| secondLine->GetLineSize() != firstLine->GetLineSize() )
continue;
if( !secondLine->IsParallel( firstLine )
|| secondLine->GetLineStyle() != firstLine->GetLineStyle()
|| secondLine->GetLineColor() != firstLine->GetLineColor()
|| secondLine->GetLineSize() != firstLine->GetLineSize() )
continue;
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
&& firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
{
remove_item( secondItem );
continue;
}
// If the end points overlap, check if we still need the junction
if( secondLine->IsEndPoint( firstLine->GetStartPoint() ) )
needed = aScreen->IsJunctionNeeded( firstLine->GetStartPoint() );
else if( secondLine->IsEndPoint( firstLine->GetEndPoint() ) )
needed = aScreen->IsJunctionNeeded( firstLine->GetEndPoint() );
if( !needed && ( line = secondLine->MergeOverlap( firstLine ) ) )
{
remove_item( item );
remove_item( secondItem );
itemList.PushItem( ITEM_PICKER( line, UR_NEW ) );
AddToScreen( line, aScreen );
if( line->IsSelected() )
selectionTool->AddItemToSel( line, true /*quiet mode*/ );
break;
}
{
remove_item( secondLine );
continue;
}
// If the end points overlap, check if we still need the junction
if( secondLine->IsEndPoint( firstLine->GetStartPoint() ) )
needed = aScreen->IsJunctionNeeded( firstLine->GetStartPoint() );
else if( secondLine->IsEndPoint( firstLine->GetEndPoint() ) )
needed = aScreen->IsJunctionNeeded( firstLine->GetEndPoint() );
SCH_LINE* mergedLine = nullptr;
if( !needed && ( mergedLine = secondLine->MergeOverlap( firstLine ) ) )
{
remove_item( firstLine );
remove_item( secondLine );
itemList.PushItem( ITEM_PICKER( mergedLine, UR_NEW ) );
AddToScreen( mergedLine, aScreen );
if( firstLine->IsSelected() )
selectionTool->AddItemToSel( mergedLine, true /*quiet mode*/ );
break;
}
// Remove duplicate junctions and no-connects
else if( secondItem->GetPosition() == item->GetPosition() )
remove_item( secondItem );
}
}
for( item = aScreen->GetDrawItems(); item; item = secondItem )
for( auto item : deletedItems )
{
secondItem = item->Next();
if( item->IsSelected() )
selectionTool->RemoveItemFromSel( item, true /*quiet mode*/ );
if( item->GetEditFlags() & STRUCT_DELETED )
{
if( item->IsSelected() )
selectionTool->RemoveItemFromSel( item, true /*quiet mode*/ );
RemoveFromScreen( item, aScreen );
}
RemoveFromScreen( item, aScreen );
}
if( itemList.GetCount() )
@ -280,19 +302,24 @@ bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint,
bool SCH_EDIT_FRAME::BreakSegments( const wxPoint& aPoint, SCH_SCREEN* aScreen )
{
static KICAD_T wiresAndBusses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
static const KICAD_T wiresAndBusses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
if( aScreen == nullptr )
aScreen = GetScreen();
bool brokenSegments = false;
bool brokenSegments = false;
std::vector<SCH_LINE*> wires;
EDA_RECT bbox( aPoint, wxSize( 2, 2 ) );
for( SCH_ITEM* segment = aScreen->GetDrawItems(); segment; segment = segment->Next() )
for( auto item : aScreen->Items().Overlapping( SCH_LINE_T, aPoint ) )
{
if( segment->IsType( wiresAndBusses ) )
brokenSegments |= BreakSegment( (SCH_LINE*) segment, aPoint, NULL, aScreen );
if( item->IsType( wiresAndBusses ) )
wires.push_back( static_cast<SCH_LINE*>( item ) );
}
for( auto wire : wires )
brokenSegments |= BreakSegment( wire, aPoint, NULL, aScreen );
return brokenSegments;
}
@ -304,23 +331,21 @@ bool SCH_EDIT_FRAME::BreakSegmentsOnJunctions( SCH_SCREEN* aScreen )
bool brokenSegments = false;
for( SCH_ITEM* item = aScreen->GetDrawItems(); item; item = item->Next() )
std::set<wxPoint> point_set;
for( auto item : aScreen->Items().OfType( SCH_JUNCTION_T ) )
point_set.insert( item->GetPosition() );
for( auto item : aScreen->Items().OfType( SCH_BUS_WIRE_ENTRY_T ) )
{
if( item->Type() == SCH_JUNCTION_T )
{
SCH_JUNCTION* junction = ( SCH_JUNCTION* ) item;
brokenSegments |= BreakSegments( junction->GetPosition(), aScreen );
}
else if( item->Type() == SCH_BUS_BUS_ENTRY_T || item->Type() == SCH_BUS_WIRE_ENTRY_T )
{
SCH_BUS_ENTRY_BASE* busEntry = (SCH_BUS_ENTRY_BASE*) item;
brokenSegments |= BreakSegments( busEntry->GetPosition(), aScreen );
brokenSegments |= BreakSegments( busEntry->m_End(), aScreen );
}
auto entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
point_set.insert( entry->GetPosition() );
point_set.insert( entry->m_End() );
}
for( auto pt : point_set )
brokenSegments |= BreakSegments( pt, aScreen );
return brokenSegments;
}
@ -330,6 +355,7 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
SCH_SCREEN* screen = GetScreen();
PICKED_ITEMS_LIST undoList;
EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
KICAD_T wiresAndBusses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
auto remove_item = [ & ]( SCH_ITEM* aItem ) -> void
{
@ -338,62 +364,62 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
};
remove_item( aJunction );
RemoveFromScreen( aJunction );
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
/// Note that std::list or similar is required here as we may insert values in the
/// loop below. This will invalidate iterators in a std::vector or std::deque
std::list<SCH_LINE*> lines;
for( auto item : screen->Items().Overlapping( SCH_LINE_T, aJunction->GetPosition() ) )
{
SCH_LINE* firstLine = dynamic_cast<SCH_LINE*>( item );
auto line = static_cast<SCH_LINE*>( item );
if( !firstLine || !firstLine->IsEndPoint( aJunction->GetPosition() )
|| ( firstLine->GetEditFlags() & STRUCT_DELETED ) )
continue;
for( SCH_ITEM* secondItem = item->Next(); secondItem; secondItem = secondItem->Next() )
{
SCH_LINE* secondLine = dynamic_cast<SCH_LINE*>( secondItem );
if( !secondLine || !secondLine->IsEndPoint( aJunction->GetPosition() )
|| ( secondItem->GetEditFlags() & STRUCT_DELETED )
|| !secondLine->IsParallel( firstLine ) )
continue;
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
&& firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
{
remove_item( secondItem );
continue;
}
// Try to merge the remaining lines
if( SCH_LINE* line = secondLine->MergeOverlap( firstLine ) )
{
remove_item( item );
remove_item( secondItem );
undoList.PushItem( ITEM_PICKER( line, UR_NEW ) );
AddToScreen( line );
if( line->IsSelected() )
selectionTool->AddItemToSel( line, true /*quiet mode*/ );
break;
}
}
if( line->IsType( wiresAndBusses ) && line->IsEndPoint( aJunction->GetPosition() )
&& !( line->GetEditFlags() & STRUCT_DELETED ) )
lines.push_back( line );
}
alg::for_all_pairs(
lines.begin(), lines.end(), [&]( SCH_LINE* firstLine, SCH_LINE* secondLine ) {
if( ( firstLine->GetEditFlags() & STRUCT_DELETED )
|| ( secondLine->GetEditFlags() & STRUCT_DELETED )
|| !secondLine->IsParallel( firstLine ) )
return;
// Remove identical lines
if( firstLine->IsEndPoint( secondLine->GetStartPoint() )
&& firstLine->IsEndPoint( secondLine->GetEndPoint() ) )
{
remove_item( firstLine );
return;
}
// Try to merge the remaining lines
if( SCH_LINE* line = secondLine->MergeOverlap( firstLine ) )
{
remove_item( firstLine );
remove_item( secondLine );
undoList.PushItem( ITEM_PICKER( line, UR_NEW ) );
AddToScreen( line );
if( line->IsSelected() )
selectionTool->AddItemToSel( line, true /*quiet mode*/ );
lines.push_back( line );
}
} );
SaveCopyInUndoList( undoList, UR_DELETED, aAppend );
for( unsigned ii = 0; ii < undoList.GetCount(); ii++ )
for( auto line : lines )
{
EDA_ITEM* item = undoList.GetPickedItem( ii );
if( item->GetEditFlags() & STRUCT_DELETED )
if( line->GetEditFlags() & STRUCT_DELETED )
{
if( item->IsSelected() )
selectionTool->RemoveItemFromSel( item, true /*quiet mode*/ );
if( line->IsSelected() )
selectionTool->RemoveItemFromSel( line, true /*quiet mode*/ );
RemoveFromScreen( item );
RemoveFromScreen( line );
}
}
}

View File

@ -29,10 +29,11 @@
#include <advanced_config.h>
#include <common.h>
#include <erc.h>
#include <sch_edit_frame.h>
#include <sch_bus_entry.h>
#include <sch_component.h>
#include <sch_edit_frame.h>
#include <sch_line.h>
#include <sch_marker.h>
#include <sch_pin.h>
#include <sch_screen.h>
#include <sch_sheet.h>
@ -388,14 +389,10 @@ void CONNECTION_GRAPH::Recalculate( SCH_SHEET_LIST aSheetList, bool aUncondition
{
std::vector<SCH_ITEM*> items;
for( auto item = sheet.LastScreen()->GetDrawItems();
item; item = item->Next() )
for( auto item : sheet.LastScreen()->Items() )
{
if( item->IsConnectable() &&
( aUnconditional || item->IsConnectivityDirty() ) )
{
if( item->IsConnectable() && ( aUnconditional || item->IsConnectivityDirty() ) )
items.push_back( item );
}
}
updateItemConnectivity( sheet, items );

View File

@ -48,13 +48,11 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
const wxString& aSearchText )
{
SCH_SHEET_PATH* sheetWithComponentFound = NULL;
SCH_ITEM* item = NULL;
SCH_COMPONENT* Component = NULL;
wxPoint pos;
bool notFound = true;
LIB_PIN* pin = nullptr;
SCH_SHEET_LIST sheetList( g_RootSheet );
EDA_ITEM* foundItem = nullptr;
SCH_ITEM* foundItem = nullptr;
if( !aSearchHierarchy )
sheetList.push_back( *g_CurrentSheet );
@ -63,12 +61,11 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
for( SCH_SHEET_PATH& sheet : sheetList)
{
for( item = sheet.LastDrawList(); item && notFound; item = item->Next() )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_SCREEN* screen = sheet.LastScreen();
SCH_COMPONENT* pSch = (SCH_COMPONENT*) item;
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
SCH_COMPONENT* pSch = static_cast<SCH_COMPONENT*>( item );
if( aReference.CmpNoCase( pSch->GetRef( &sheet ) ) == 0 )
{
@ -82,21 +79,21 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
if( pin )
{
notFound = false;
pos += pin->GetPosition();
foundItem = Component;
break;
}
}
else
{
notFound = false;
pos = pSch->GetPosition();
foundItem = Component;
break;
}
}
}
if( notFound == false )
if( foundItem )
break;
}
@ -129,7 +126,7 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
if( Component )
{
if( !notFound )
if( foundItem )
msg.Printf( _( "%s %s found" ), aReference, msg_item );
else
msg.Printf( _( "%s found but %s not found" ), aReference, msg_item );
@ -152,7 +149,7 @@ SCH_ITEM* SCH_EDITOR_CONTROL::FindComponentAndItem( const wxString& aReference,
m_frame->GetCanvas()->Refresh();
return item;
return foundItem;
}

View File

@ -417,27 +417,6 @@ void DIALOG_EDIT_COMPONENTS_LIBID::initDlg()
m_isModified = false;
// Build the component list:
#if 0
// This option build a component list that works fine to edit LIB_ID fields, but does not display
// all components in a complex hierarchy.
// the list is shorter, but can be look like there are missing components in list
SCH_SCREENS screens;
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() == SCH_COMPONENT_T )
{
CMP_CANDIDATE candidate( static_cast< SCH_COMPONENT* >( item ) );
candidate.m_Screen = screen;
candidate.m_Reference = candidate.m_Component->GetField( REFERENCE )->GetFullyQualifiedText();
m_components.push_back( candidate );
}
}
}
#else
// This option build the full component list
// In complex hierarchies, the same component is in fact duplicated, but
// it is listed with different references (one by sheet instance)
@ -460,7 +439,6 @@ void DIALOG_EDIT_COMPONENTS_LIBID::initDlg()
candidate.m_IsOrphan = ( unitcount == 0 );
m_components.push_back( candidate );
}
#endif
if( m_components.size() == 0 )
return;
@ -734,7 +712,7 @@ bool DIALOG_EDIT_COMPONENTS_LIBID::setLibIdByBrowser( int aRow )
if( !current.IsEmpty() )
aPreselectedLibid.Parse( current, LIB_ID::ID_SCH, true );
SCH_BASE_FRAME::COMPONENT_SELECTION sel =
COMPONENT_SELECTION sel =
m_parent->SelectComponentFromLibBrowser( this, NULL, aPreselectedLibid, 0, 0 );
#endif

View File

@ -195,12 +195,13 @@ bool DIALOG_LABEL_EDITOR::TransferDataToWindow()
SCH_SCREENS allScreens;
for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
if( item->Type() == m_CurrentText->Type() )
{
auto textItem = static_cast<SCH_TEXT*>( item );
existingLabels.insert( UnescapeString( textItem->GetText() ) );
}
{
for( auto item : screen->Items().OfType( m_CurrentText->Type() ) )
{
auto textItem = static_cast<const SCH_TEXT*>( item );
existingLabels.insert( UnescapeString( textItem->GetText() ) );
}
}
wxArrayString existingLabelArray;

View File

@ -256,13 +256,11 @@ void DIALOG_ERC::OnLeftClickMarkersList( wxHtmlLinkEvent& event )
SCH_SHEET_LIST sheetList( g_RootSheet );
bool found = false;
for( i = 0; i < sheetList.size(); i++ )
for( i = 0; i < sheetList.size(); i++ )
{
SCH_ITEM* item = (SCH_ITEM*) sheetList[i].LastDrawList();
for( ; item; item = item->Next() )
for( auto aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
{
if( item == marker )
if( static_cast<const SCH_MARKER*>( aItem ) == marker )
{
found = true;
break;
@ -440,19 +438,12 @@ void DIALOG_ERC::DisplayERC_MarkersList()
for( unsigned i = 0; i < sheetList.size(); i++ )
{
SCH_ITEM* item = sheetList[i].LastDrawList();
for( ; item != NULL; item = item->Next() )
for( auto aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
{
if( item->Type() != SCH_MARKER_T )
continue;
SCH_MARKER* marker = static_cast<SCH_MARKER*>( aItem );
SCH_MARKER* marker = (SCH_MARKER*) item;
if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
continue;
m_MarkersList->AppendToList( marker );
if( marker->GetMarkerType() == MARKER_BASE::MARKER_ERC )
m_MarkersList->AppendToList( marker );
}
}
@ -623,11 +614,8 @@ void DIALOG_ERC::TestErc( REPORTER& aReporter )
// Display new markers from the current screen:
KIGFX::VIEW* view = m_parent->GetCanvas()->GetView();
for( auto item = m_parent->GetScreen()->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() == SCH_MARKER_T )
view->Add( item );
}
for( auto item : m_parent->GetScreen()->Items().OfType( SCH_MARKER_T ) )
view->Add( item );
m_parent->GetCanvas()->Refresh();

View File

@ -346,7 +346,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataFromWindow()
if( screen )
{
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
for( auto item : screen->Items() )
visitItem( sheetPath, item );
}
}

View File

@ -34,6 +34,7 @@
#include <wx/wupdlock.h>
#include <cctype>
#include <cstring>
// Helper function to shorten conditions
static bool empty( const wxTextCtrl* aCtrl )

View File

@ -243,32 +243,25 @@ void DIALOG_SYMBOL_REMAP::remapSymbolsToLibTable( REPORTER& aReporter )
wxString msg;
SCH_SCREENS schematic;
SCH_COMPONENT* symbol;
SCH_ITEM* item;
SCH_ITEM* nextItem;
SCH_SCREEN* screen;
for( screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
{
for( item = screen->GetDrawItems(); item; item = nextItem )
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
nextItem = item->Next();
if( item->Type() != SCH_COMPONENT_T )
continue;
symbol = dynamic_cast< SCH_COMPONENT* >( item );
symbol = dynamic_cast<SCH_COMPONENT*>( item );
if( !remapSymbolToLibTable( symbol ) )
{
msg.Printf( _( "No symbol \"%s\" found in symbol library table." ),
symbol->GetLibId().GetLibItemName().wx_str() );
symbol->GetLibId().GetLibItemName().wx_str() );
aReporter.Report( msg, REPORTER::RPT_WARNING );
}
else
{
msg.Printf( _( "Symbol \"%s\" mapped to symbol library \"%s\"." ),
symbol->GetLibId().GetLibItemName().wx_str(),
symbol->GetLibId().GetLibNickname().wx_str() );
symbol->GetLibId().GetLibItemName().wx_str(),
symbol->GetLibId().GetLibNickname().wx_str() );
aReporter.Report( msg, REPORTER::RPT_ACTION );
screen->SetModify();
}

View File

@ -26,12 +26,13 @@
#include <macros.h>
#include <trace_helpers.h>
#include <sch_sheet_path.h>
#include <transform.h>
#include <ee_collectors.h>
#include <lib_item.h>
#include <sch_bus_entry.h>
#include <sch_component.h>
#include <sch_line.h>
#include <sch_bus_entry.h>
#include <sch_sheet_path.h>
#include <transform.h>
const KICAD_T EE_COLLECTOR::AllItems[] = {
@ -93,8 +94,31 @@ SEARCH_RESULT EE_COLLECTOR::Inspect( EDA_ITEM* aItem, void* aTestData )
}
void EE_COLLECTOR::Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPos,
int aUnit, int aConvert )
void EE_COLLECTOR::Collect( SCH_SCREEN* aScreen, const KICAD_T aFilterList[], const wxPoint& aPos,
int aUnit, int aConvert )
{
Empty(); // empty the collection just in case
SetScanTypes( aFilterList );
m_Unit = aUnit;
m_Convert = aConvert;
// remember where the snapshot was taken from and pass refPos to the Inspect() function.
SetRefPos( aPos );
if( aScreen )
{
for( const KICAD_T* filter = aFilterList; *filter != EOT; ++filter )
{
for( auto item : aScreen->Items().OfType( *filter ) )
item->Visit( m_inspector, nullptr, m_ScanTypes );
}
}
}
void EE_COLLECTOR::Collect( LIB_ITEMS_CONTAINER& aItems, const KICAD_T aFilterList[],
const wxPoint& aPos, int aUnit, int aConvert )
{
Empty(); // empty the collection just in case
@ -105,11 +129,11 @@ void EE_COLLECTOR::Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[], const
// remember where the snapshot was taken from and pass refPos to the Inspect() function.
SetRefPos( aPos );
// aItem can be null for empty schematics
if( aItem && aItem->Type() == LIB_PART_T )
static_cast<LIB_PART*>( aItem )->Visit( m_inspector, nullptr, m_ScanTypes );
else
EDA_ITEM::IterateForward( aItem, m_inspector, nullptr, m_ScanTypes );
for( auto& item : aItems )
{
if( item.Visit( m_inspector, nullptr, m_ScanTypes ) == SEARCH_RESULT::QUIT )
break;
}
}
@ -142,23 +166,3 @@ bool EE_COLLECTOR::IsDraggableJunction() const
return false;
}
SEARCH_RESULT EE_TYPE_COLLECTOR::Inspect( EDA_ITEM* aItem, void* testData )
{
// The Vist() function only visits the testItem if its type was in the
// the scanList, so therefore we can collect anything given to us here.
Append( aItem );
return SEARCH_RESULT::CONTINUE;
}
void EE_TYPE_COLLECTOR::Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[] )
{
Empty(); // empty the collection
SetScanTypes( aFilterList );
EDA_ITEM::IterateForward( aItem, m_inspector, NULL, m_ScanTypes );
}

View File

@ -26,11 +26,11 @@
#ifndef EE_COLLECTORS_H
#define EE_COLLECTORS_H
#include <class_libentry.h>
#include <collector.h>
#include <dialogs/dialog_schematic_find.h>
#include <sch_item.h>
#include <sch_sheet_path.h>
#include <dialogs/dialog_schematic_find.h>
/**
@ -70,7 +70,7 @@ public:
/**
* Function Collect
* scans a EDA_ITEM using this class's Inspector method, which does the collection.
* @param aItem A EDA_ITEM to scan.
* @param aScreen The eeschema screen to use for scanning
* @param aFilterList A list of #KICAD_T types with a terminating #EOT, that determines
* what is to be collected and the priority order of the resulting
* collection.
@ -78,8 +78,22 @@ public:
* @param aUnit A symbol unit filter (for symbol editor)
* @param aConvert A DeMorgan filter (for symbol editor)
*/
void Collect( EDA_ITEM* aItem, const KICAD_T aFilterList[], const wxPoint& aPos,
int aUnit = 0, int aConvert = 0 );
void Collect( SCH_SCREEN* aScreen, const KICAD_T aFilterList[], const wxPoint& aPos,
int aUnit = 0, int aConvert = 0 );
/**
* Function Collect
* scans a EDA_ITEM using this class's Inspector method, which does the collection.
* @param aItems The LIB_PART multivector holding the part components
* @param aFilterList A list of #KICAD_T types with a terminating #EOT, that determines
* what is to be collected and the priority order of the resulting
* collection.
* @param aPos A wxPoint to use in hit-testing.
* @param aUnit A symbol unit filter (for symbol editor)
* @param aConvert A DeMorgan filter (for symbol editor)
*/
void Collect( LIB_ITEMS_CONTAINER& aItems, const KICAD_T aFilterList[], const wxPoint& aPos,
int aUnit = 0, int aConvert = 0 );
/**
* Function IsCorner
@ -109,35 +123,4 @@ public:
};
/**
* Class EE_TYPE_COLLECTOR
* merely gathers up all SCH_ITEMs of a given set of KICAD_T type(s). It does
* no hit-testing.
*
* @see class COLLECTOR
*/
class EE_TYPE_COLLECTOR : public EE_COLLECTOR
{
public:
/**
* Function Inspect
* is the examining function within the INSPECTOR which is passed to the Iterate function.
*
* @param testItem An EDA_ITEM to examine.
* @param testData is not used in this class.
* @return SEARCH_RESULT - SEARCH_QUIT if the Iterator is to stop the scan,
* else SCAN_CONTINUE;
*/
SEARCH_RESULT Inspect( EDA_ITEM* testItem, void* testData ) override;
/**
* Function Collect
* scans a DLIST using this class's Inspector method, which does the collection.
* @param aItem The head of a DLIST to scan.
* @param aScanList The KICAD_Ts to gather up.
*/
void Collect( EDA_ITEM* aItem, const KICAD_T aScanList[] );
};
#endif // EE_COLLECTORS_H

View File

@ -174,23 +174,23 @@ static int MinimalReq[PINTYPE_COUNT][PINTYPE_COUNT] =
int TestDuplicateSheetNames( bool aCreateMarker )
{
SCH_SCREEN* screen;
SCH_ITEM* item;
SCH_ITEM* test_item;
int err_count = 0;
SCH_SCREENS screenList; // Created the list of screen
for( screen = screenList.GetFirst(); screen != NULL; screen = screenList.GetNext() )
{
for( item = screen->GetDrawItems(); item != NULL; item = item->Next() )
{
// search for a sheet;
if( item->Type() != SCH_SHEET_T )
continue;
std::vector<SCH_SHEET*> list;
for( test_item = item->Next(); test_item != NULL; test_item = test_item->Next() )
for( auto item : screen->Items().OfType( SCH_SHEET_T ) )
list.push_back( static_cast<SCH_SHEET*>( item ) );
for( size_t i = 0; i < list.size(); i++ )
{
auto item = list[i];
for( size_t j = i + 1; j < list.size(); j++ )
{
if( test_item->Type() != SCH_SHEET_T )
continue;
auto test_item = list[j];
// We have found a second sheet: compare names
// we are using case insensitive comparison to avoid mistakes between
@ -584,12 +584,9 @@ bool WriteDiagnosticERC( EDA_UNITS aUnits, const wxString& aFullFileName )
msg << wxString::Format( _( "\n***** Sheet %s\n" ),
GetChars( sheetList[i].PathHumanReadable() ) );
for( SCH_ITEM* item = sheetList[i].LastDrawList(); item != NULL; item = item->Next() )
for( auto aItem : sheetList[i].LastScreen()->Items().OfType( SCH_MARKER_T ) )
{
if( item->Type() != SCH_MARKER_T )
continue;
SCH_MARKER* marker = (SCH_MARKER*) item;
auto marker = static_cast<const SCH_MARKER*>( aItem );
if( marker->GetMarkerType() != MARKER_BASE::MARKER_ERC )
continue;

View File

@ -649,18 +649,14 @@ bool SCH_EDIT_FRAME::importFile( const wxString& aFileName, int aFileType )
schematic.UpdateSymbolLinks(); // Update all symbol library links for all sheets.
GetScreen()->m_Initialized = true;
EE_TYPE_COLLECTOR components;
SCH_SCREENS allScreens;
for( SCH_SCREEN* screen = allScreens.GetFirst(); screen; screen = allScreens.GetNext() )
{
components.Collect( screen->GetDrawItems(), EE_COLLECTOR::ComponentsOnly );
for( int cmpIdx = 0; cmpIdx < components.GetCount(); ++cmpIdx )
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
std::vector<wxPoint> pts;
SCH_COMPONENT* cmp = static_cast<SCH_COMPONENT*>( components[cmpIdx] );
SCH_COMPONENT* cmp = static_cast<SCH_COMPONENT*>( item );
// Update footprint LIB_ID to point to the imported Eagle library
auto fpField = cmp->GetField( FOOTPRINT );

View File

@ -24,30 +24,31 @@
*/
#include <algorithm>
#include <fctsys.h>
#include <pgm_base.h>
#include <kiway.h>
#include <gr_basic.h>
#include <sch_draw_panel.h>
#include <confirm.h>
#include <sch_edit_frame.h>
#include <msgpanel.h>
#include <tool/tool_manager.h>
#include <tools/ee_actions.h>
#include <general.h>
#include <class_library.h>
#include <sch_component.h>
#include <confirm.h>
#include <eeschema_id.h>
#include <fctsys.h>
#include <general.h>
#include <gr_basic.h>
#include <kiway.h>
#include <lib_edit_frame.h>
#include <lib_view_frame.h>
#include <msgpanel.h>
#include <pgm_base.h>
#include <project.h>
#include <sch_component.h>
#include <sch_draw_panel.h>
#include <sch_edit_frame.h>
#include <symbol_lib_table.h>
#include <tool/tool_manager.h>
#include <tools/ee_actions.h>
#include <dialog_choose_component.h>
#include <symbol_tree_model_adapter.h>
SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowser(
wxTopLevelWindow* aParent, const SCHLIB_FILTER* aFilter, const LIB_ID& aPreselectedLibId,
int aUnit, int aConvert )
COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowser( wxTopLevelWindow* aParent,
const SCHLIB_FILTER* aFilter, const LIB_ID& aPreselectedLibId, int aUnit, int aConvert )
{
// Close any open non-modal Lib browser, and open a new one, in "modal" mode:
LIB_VIEW_FRAME* viewlibFrame = (LIB_VIEW_FRAME*) Kiway().Player( FRAME_SCH_VIEWER, false );
@ -90,15 +91,9 @@ SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectComponentFromLibBrowse
}
SCH_BASE_FRAME::COMPONENT_SELECTION SCH_BASE_FRAME::SelectCompFromLibTree(
const SCHLIB_FILTER* aFilter,
std::vector<COMPONENT_SELECTION>& aHistoryList,
bool aUseLibBrowser,
int aUnit,
int aConvert,
bool aShowFootprints,
const LIB_ID* aHighlight,
bool aAllowFields )
COMPONENT_SELECTION SCH_BASE_FRAME::SelectCompFromLibTree( const SCHLIB_FILTER* aFilter,
std::vector<COMPONENT_SELECTION>& aHistoryList, bool aUseLibBrowser, int aUnit,
int aConvert, bool aShowFootprints, const LIB_ID* aHighlight, bool aAllowFields )
{
std::unique_lock<std::mutex> dialogLock( DIALOG_CHOOSE_COMPONENT::g_Mutex, std::defer_lock );
wxString dialogTitle;

View File

@ -158,31 +158,26 @@ void HIERARCHY_NAVIG_DLG::buildHierarchyTree( SCH_SHEET_PATH* aList, wxTreeItemI
{
wxCHECK_RET( m_nbsheets < NB_MAX_SHEET, "Maximum number of sheets exceeded." );
SCH_ITEM* schitem = aList->LastDrawList();
while( schitem && m_nbsheets < NB_MAX_SHEET )
for( auto aItem : aList->LastScreen()->Items().OfType( SCH_SHEET_T ) )
{
if( schitem->Type() == SCH_SHEET_T )
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
m_nbsheets++;
wxTreeItemId menu;
menu = m_Tree->AppendItem( *aPreviousmenu, sheet->GetName(), 0, 1 );
aList->push_back( sheet );
m_Tree->SetItemData( menu, new TreeItemData( *aList ) );
if( *aList == m_currSheet )
{
SCH_SHEET* sheet = (SCH_SHEET*) schitem;
m_nbsheets++;
wxTreeItemId menu;
menu = m_Tree->AppendItem( *aPreviousmenu, sheet->GetName(), 0, 1 );
aList->push_back( sheet );
m_Tree->SetItemData( menu, new TreeItemData( *aList ) );
if( *aList == m_currSheet )
{
m_Tree->EnsureVisible( menu );
m_Tree->SelectItem( menu );
}
buildHierarchyTree( aList, &menu );
aList->pop_back();
m_Tree->EnsureVisible( menu );
m_Tree->SelectItem( menu );
}
schitem = schitem->Next();
buildHierarchyTree( aList, &menu );
aList->pop_back();
if( m_nbsheets >= NB_MAX_SHEET )
break;
}
}

View File

@ -81,13 +81,11 @@ bool SCH_EDIT_FRAME::CreateArchiveLibrary( const wxString& aFileName )
*/
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
for( auto aItem : screen->Items().OfType( SCH_COMPONENT_T ) )
{
LIB_PART* part = nullptr;
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
auto component = static_cast<SCH_COMPONENT*>( aItem );
try
{

View File

@ -102,46 +102,40 @@ SCH_COMPONENT* NETLIST_EXPORTER::findNextComponent( EDA_ITEM* aItem, SCH_SHEET_P
{
wxString ref;
// continue searching from the middle of a linked list (the draw list)
for( ; aItem; aItem = aItem->Next() )
if( aItem->Type() != SCH_COMPONENT_T )
return nullptr;
// found next component
SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem;
// Power symbols and other components which have the reference starting
// with "#" are not included in netlist (pseudo or virtual components)
ref = comp->GetRef( aSheetPath );
if( ref[0] == wxChar( '#' ) )
return nullptr;
// if( Component->m_FlagControlMulti == 1 )
// continue; /* yes */
// removed because with multiple instances of one schematic
// (several sheets pointing to 1 screen), this will be erroneously be
// toggled.
if( !comp->GetPartRef() )
return nullptr;
// If component is a "multi parts per package" type
if( comp->GetPartRef()->GetUnitCount() > 1 )
{
if( aItem->Type() != SCH_COMPONENT_T )
continue;
// found next component
SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem;
// Power symbols and other components which have the reference starting
// with "#" are not included in netlist (pseudo or virtual components)
ref = comp->GetRef( aSheetPath );
if( ref[0] == wxChar( '#' ) )
continue;
// if( Component->m_FlagControlMulti == 1 )
// continue; /* yes */
// removed because with multiple instances of one schematic
// (several sheets pointing to 1 screen), this will be erroneously be
// toggled.
if( !comp->GetPartRef() )
continue;
// If component is a "multi parts per package" type
if( comp->GetPartRef()->GetUnitCount() > 1 )
{
// test if this reference has already been processed, and if so skip
if( m_ReferencesAlreadyFound.Lookup( ref ) )
continue;
}
// record the usage of this library component entry.
m_LibParts.insert( comp->GetPartRef().get() ); // rejects non-unique pointers
return comp;
// test if this reference has already been processed, and if so skip
if( m_ReferencesAlreadyFound.Lookup( ref ) )
return nullptr;
}
return NULL;
// record the usage of this library component entry.
m_LibParts.insert( comp->GetPartRef().get() ); // rejects non-unique pointers
return comp;
}
@ -153,82 +147,65 @@ static bool sortPinsByNum( NETLIST_OBJECT* aPin1, NETLIST_OBJECT* aPin2 )
}
SCH_COMPONENT* NETLIST_EXPORTER::findNextComponentAndCreatePinList(
EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath )
void NETLIST_EXPORTER::CreatePinList( SCH_COMPONENT* comp, SCH_SHEET_PATH* aSheetPath )
{
wxString ref;
wxString ref( comp->GetRef( aSheetPath ) );
// Power symbols and other components which have the reference starting
// with "#" are not included in netlist (pseudo or virtual components)
if( ref[0] == wxChar( '#' ) )
return;
// if( Component->m_FlagControlMulti == 1 )
// continue; /* yes */
// removed because with multiple instances of one schematic
// (several sheets pointing to 1 screen), this will be erroneously be
// toggled.
if( !comp->GetPartRef() )
return;
m_SortedComponentPinList.clear();
// continue searching from the middle of a linked list (the draw list)
for( ; aItem; aItem = aItem->Next() )
// If component is a "multi parts per package" type
if( comp->GetPartRef()->GetUnitCount() > 1 )
{
if( aItem->Type() != SCH_COMPONENT_T )
continue;
// test if this reference has already been processed, and if so skip
if( m_ReferencesAlreadyFound.Lookup( ref ) )
return;
// found next component
SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem;
// Power symbols and other components which have the reference starting
// with "#" are not included in netlist (pseudo or virtual components)
ref = comp->GetRef( aSheetPath );
if( ref[0] == wxChar( '#' ) )
continue;
// if( Component->m_FlagControlMulti == 1 )
// continue; /* yes */
// removed because with multiple instances of one schematic
// (several sheets pointing to 1 screen), this will be erroneously be
// toggled.
if( !comp->GetPartRef() )
continue;
// If component is a "multi parts per package" type
if( comp->GetPartRef()->GetUnitCount() > 1 )
{
// test if this reference has already been processed, and if so skip
if( m_ReferencesAlreadyFound.Lookup( ref ) )
continue;
// Collect all pins for this reference designator by searching
// the entire design for other parts with the same reference designator.
// This is only done once, it would be too expensive otherwise.
findAllUnitsOfComponent( comp, comp->GetPartRef().get(), aSheetPath );
}
else // entry->GetUnitCount() <= 1 means one part per package
{
LIB_PINS pins; // constructed once here
comp->GetPartRef()->GetPins( pins, comp->GetUnitSelection( aSheetPath ),
comp->GetConvert() );
for( size_t i = 0; i < pins.size(); i++ )
{
LIB_PIN* pin = pins[i];
wxASSERT( pin->Type() == LIB_PIN_T );
addPinToComponentPinList( comp, aSheetPath, pin );
}
}
// Sort pins in m_SortedComponentPinList by pin number
sort( m_SortedComponentPinList.begin(),
m_SortedComponentPinList.end(), sortPinsByNum );
// Remove duplicate Pins in m_SortedComponentPinList
eraseDuplicatePins();
// record the usage of this library component entry.
m_LibParts.insert( comp->GetPartRef().get() ); // rejects non-unique pointers
return comp;
// Collect all pins for this reference designator by searching
// the entire design for other parts with the same reference designator.
// This is only done once, it would be too expensive otherwise.
findAllUnitsOfComponent( comp, comp->GetPartRef().get(), aSheetPath );
}
return NULL;
else // entry->GetUnitCount() <= 1 means one part per package
{
LIB_PINS pins; // constructed once here
comp->GetPartRef()->GetPins(
pins, comp->GetUnitSelection( aSheetPath ), comp->GetConvert() );
for( size_t i = 0; i < pins.size(); i++ )
{
LIB_PIN* pin = pins[i];
wxASSERT( pin->Type() == LIB_PIN_T );
addPinToComponentPinList( comp, aSheetPath, pin );
}
}
// Sort pins in m_SortedComponentPinList by pin number
sort( m_SortedComponentPinList.begin(), m_SortedComponentPinList.end(), sortPinsByNum );
// Remove duplicate Pins in m_SortedComponentPinList
eraseDuplicatePins();
// record the usage of this library component entry.
m_LibParts.insert( comp->GetPartRef().get() ); // rejects non-unique pointers
}
@ -329,12 +306,9 @@ void NETLIST_EXPORTER::findAllUnitsOfComponent( SCH_COMPONENT* aComponent,
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* item = sheetList[i].LastDrawList(); item; item = item->Next() )
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item;
SCH_COMPONENT* comp2 = static_cast<SCH_COMPONENT*>( item );
ref2 = comp2->GetRef( &sheetList[i] );

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2013 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2018 KiCad Developers
* Copyright (C) 1992-2019 KiCad Developers
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -92,6 +92,7 @@ protected:
/// Used to temporarily store and filter the list of pins of a schematic component
/// when generating schematic component data in netlist (comp section). No ownership
/// of members.
/// TODO(snh): Descope this object
NETLIST_OBJECTS m_SortedComponentPinList;
/// Used for "multi parts per package" components,
@ -123,7 +124,7 @@ protected:
* the component is the next actual component after aItem
* (power symbols and virtual components that have their reference starting by '#'are skipped).
*/
SCH_COMPONENT* findNextComponentAndCreatePinList( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath );
void CreatePinList( SCH_COMPONENT* aItem, SCH_SHEET_PATH* aSheetPath );
SCH_COMPONENT* findNextComponent( EDA_ITEM* aItem, SCH_SHEET_PATH* aSheetPath );

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2018 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -53,7 +53,6 @@ bool NETLIST_EXPORTER_CADSTAR::WriteNetlist( const wxString& aOutFileName, unsig
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
wxString msg;
wxString footprint;
EDA_ITEM* DrawList;
SCH_COMPONENT* component;
wxString title = wxT( "Eeschema " ) + GetBuildVersion();
@ -74,13 +73,16 @@ bool NETLIST_EXPORTER_CADSTAR::WriteNetlist( const wxString& aOutFileName, unsig
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( DrawList = sheetList[i].LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
std::vector<SCH_COMPONENT*> cmps;
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
DrawList = component = findNextComponentAndCreatePinList( DrawList, &sheetList[i] );
component = findNextComponent( item, &sheetList[i] );
if( component == NULL )
break;
if( !component )
continue;
CreatePinList( component, &sheetList[i] );
if( !component->GetField( FOOTPRINT )->IsVoid() )
footprint = component->GetField( FOOTPRINT )->GetText();

View File

@ -111,11 +111,8 @@ void NETLIST_EXPORTER_GENERIC::addComponentFields( XNODE* xcomp, SCH_COMPONENT*
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* item = sheetList[i].LastDrawList(); item; item = item->Next() )
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* comp2 = (SCH_COMPONENT*) item;
wxString ref2 = comp2->GetRef( &sheetList[i] );
@ -215,14 +212,12 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* schItem = sheetList[i].LastDrawList(); schItem; schItem = schItem->Next() )
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
SCH_COMPONENT* comp = findNextComponent( schItem, &sheetList[i] );
SCH_COMPONENT* comp = findNextComponent( item, &sheetList[i] );
if( !comp )
break; // No component left
schItem = comp;
continue;
XNODE* xcomp; // current component being constructed

View File

@ -3,7 +3,7 @@
*
* Copyright (C) 1992-2018 jp.charras at wanadoo.fr
* Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2019 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -72,14 +72,15 @@ bool NETLIST_EXPORTER_ORCADPCB2::WriteNetlist( const wxString& aOutFileName,
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* item = sheetList[i].LastDrawList(); item; item = item->Next() )
// Process component attributes
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
SCH_COMPONENT* comp = findNextComponentAndCreatePinList( item, &sheetList[i] );
SCH_COMPONENT* comp = findNextComponent( item, &sheetList[i] );
if( !comp )
break;
continue;
item = comp;
CreatePinList( comp, &sheetList[i] );
if( comp->GetPartRef() )
{

View File

@ -287,31 +287,30 @@ bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
for( unsigned sheet_idx = 0; sheet_idx < sheetList.size(); sheet_idx++ )
{
// Process component attributes to find Spice directives
for( EDA_ITEM* item = sheetList[sheet_idx].LastDrawList(); item; item = item->Next() )
for( auto item : sheetList[sheet_idx].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
SCH_COMPONENT* comp = findNextComponentAndCreatePinList( item, &sheetList[sheet_idx] );
SCH_COMPONENT* comp = findNextComponent( item, &sheetList[sheet_idx] );
if( !comp )
break;
item = comp;
continue;
CreatePinList( comp, &sheetList[sheet_idx] );
SPICE_ITEM spiceItem;
spiceItem.m_parent = comp;
// Obtain Spice fields
SCH_FIELD* fieldLibFile = comp->FindField( GetSpiceFieldName( SF_LIB_FILE ) );
SCH_FIELD* fieldSeq = comp->FindField( GetSpiceFieldName( SF_NODE_SEQUENCE ) );
SCH_FIELD* fieldSeq = comp->FindField( GetSpiceFieldName( SF_NODE_SEQUENCE ) );
spiceItem.m_primitive = GetSpiceField( SF_PRIMITIVE, comp, aCtl )[0];
spiceItem.m_model = GetSpiceField( SF_MODEL, comp, aCtl );
spiceItem.m_refName = comp->GetRef( &sheetList[sheet_idx] );
spiceItem.m_model = GetSpiceField( SF_MODEL, comp, aCtl );
spiceItem.m_refName = comp->GetRef( &sheetList[sheet_idx] );
// Duplicate references will result in simulation errors
if( refNames.count( spiceItem.m_refName ) )
{
DisplayError( NULL, wxT( "There are duplicate components. "
"You need to annotate schematics first." ) );
"You need to annotate schematics first." ) );
return false;
}
@ -357,8 +356,8 @@ bool NETLIST_EXPORTER_PSPICE::ProcessNetlist( unsigned aCtl )
while( tkz.HasMoreTokens() )
{
wxString pinIndex = tkz.GetNextToken();
int seq;
wxString pinIndex = tkz.GetNextToken();
int seq;
// Find PinName In Standard List assign Standard List Index to Name:
seq = pinNames.Index( pinIndex );
@ -388,11 +387,8 @@ void NETLIST_EXPORTER_PSPICE::UpdateDirectives( unsigned aCtl )
for( unsigned i = 0; i < sheetList.size(); i++ )
{
for( EDA_ITEM* item = sheetList[i].LastDrawList(); item; item = item->Next() )
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_TEXT_T ) )
{
if( item->Type() != SCH_TEXT_T )
continue;
wxString text = static_cast<SCH_TEXT*>( item )->GetText();
if( text.IsEmpty() )

View File

@ -78,10 +78,8 @@ bool NETLIST_OBJECT_LIST::BuildNetListInfo( SCH_SHEET_LIST& aSheets )
{
sheet = &aSheets[i];
for( SCH_ITEM* item = sheet->LastScreen()->GetDrawItems(); item; item = item->Next() )
{
for( auto item : sheet->LastScreen()->Items() )
item->GetNetListItem( *this, sheet );
}
}
if( size() == 0 )

View File

@ -66,14 +66,8 @@ static void get_components( std::vector<SCH_COMPONENT*>& aComponents )
// Get the full list
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
aComponents.push_back( component );
}
for( auto aItem : screen->Items().OfType( SCH_COMPONENT_T ) )
aComponents.push_back( static_cast<SCH_COMPONENT*>( aItem ) );
}
if( aComponents.empty() )

View File

@ -25,12 +25,21 @@
#ifndef SCH_BASE_FRAME_H_
#define SCH_BASE_FRAME_H_
#include <lib_id.h>
#include <eda_draw_frame.h>
#include <sch_screen.h>
#include <frame_type.h>
#include <lib_id.h>
#include <page_info.h>
#include <sch_draw_panel.h>
#include "template_fieldnames.h"
#include <sch_screen.h>
#include <stddef.h>
#include <utility>
#include <vector>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <template_fieldnames.h>
namespace KIGFX
@ -47,7 +56,6 @@ class PART_LIB;
class SCHLIB_FILTER;
class LIB_ID;
class SYMBOL_LIB_TABLE;
class SCH_DRAW_PANEL;
/**
* Load symbol from symbol library table.
@ -205,21 +213,6 @@ public:
void UpdateStatusBar() override;
struct COMPONENT_SELECTION
{
LIB_ID LibId;
int Unit;
int Convert;
std::vector<std::pair<int, wxString>> Fields;
COMPONENT_SELECTION():
Unit( 1 ),
Convert( 1 )
{}
};
typedef std::vector<COMPONENT_SELECTION> HISTORY_LIST;
/**

View File

@ -153,9 +153,9 @@ SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, LIB_ID aLibId, SCH_SHEET_PATH* sh
m_prefix = aPart.GetReferenceField().GetText() + wxT( "?" );
}
SCH_COMPONENT::SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* aSheet,
SCH_BASE_FRAME::COMPONENT_SELECTION& aSel, const wxPoint& pos ) :
SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos )
SCH_COMPONENT::SCH_COMPONENT(
LIB_PART& aPart, SCH_SHEET_PATH* aSheet, COMPONENT_SELECTION& aSel, const wxPoint& pos )
: SCH_COMPONENT( aPart, aSel.LibId, aSheet, aSel.Unit, aSel.Convert, pos )
{
// Set any fields that were modified as part of the component selection
for( auto const& i : aSel.Fields )
@ -421,36 +421,25 @@ static bool sort_by_libid( const SCH_COMPONENT* ref, SCH_COMPONENT* cmp )
}
void SCH_COMPONENT::ResolveAll( const EE_COLLECTOR& aComponents, SYMBOL_LIB_TABLE& aLibTable,
PART_LIB* aCacheLib )
void SCH_COMPONENT::ResolveAll(
std::vector<SCH_COMPONENT*>& aComponents, SYMBOL_LIB_TABLE& aLibTable, PART_LIB* aCacheLib )
{
std::vector<SCH_COMPONENT*> cmp_list;
for( int i = 0; i < aComponents.GetCount(); ++i )
{
SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
wxCHECK2_MSG( cmp, continue, "Invalid SCH_COMPONENT pointer in list." );
cmp_list.push_back( cmp );
}
// sort it by lib part. Cmp will be grouped by same lib part.
std::sort( cmp_list.begin(), cmp_list.end(), sort_by_libid );
std::sort( aComponents.begin(), aComponents.end(), sort_by_libid );
LIB_ID curr_libid;
for( unsigned ii = 0; ii < cmp_list.size (); ++ii )
for( unsigned ii = 0; ii < aComponents.size(); ++ii )
{
SCH_COMPONENT* cmp = cmp_list[ii];
SCH_COMPONENT* cmp = aComponents[ii];
curr_libid = cmp->m_lib_id;
cmp->Resolve( aLibTable, aCacheLib );
cmp->UpdatePins();
// Propagate the m_part pointer to other members using the same lib_id
for( unsigned jj = ii+1; jj < cmp_list.size (); ++jj )
for( unsigned jj = ii + 1; jj < aComponents.size(); ++jj )
{
SCH_COMPONENT* next_cmp = cmp_list[jj];
SCH_COMPONENT* next_cmp = aComponents[jj];
if( curr_libid != next_cmp->m_lib_id )
break;
@ -466,18 +455,6 @@ void SCH_COMPONENT::ResolveAll( const EE_COLLECTOR& aComponents, SYMBOL_LIB_TABL
}
void SCH_COMPONENT::UpdatePins( const EE_COLLECTOR& aComponents )
{
for( int i = 0; i < aComponents.GetCount(); ++i )
{
SCH_COMPONENT* cmp = dynamic_cast<SCH_COMPONENT*>( aComponents[i] );
wxASSERT( cmp );
cmp->UpdatePins();
}
}
void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
{
m_pins.clear();

View File

@ -27,16 +27,32 @@
#ifndef COMPONENT_CLASS_H
#define COMPONENT_CLASS_H
#include <base_struct.h>
#include <common.h>
#include <core/typeinfo.h>
#include <layers_id_colors_and_visibility.h>
#include <lib_id.h>
#include <msgpanel.h>
#include <sch_field.h>
#include <transform.h>
#include <general.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <set>
#include <lib_item.h>
#include <wx/arrstr.h>
#include <wx/chartype.h>
#include <wx/fdrepdlg.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <bitmaps.h>
#include <class_libentry.h>
#include <lib_pin.h>
#include <sch_field.h>
#include <sch_item.h>
#include <sch_pin.h>
#include <sch_base_frame.h>
#include <sch_screen.h>
#include <symbol_lib_table.h>
#include <transform.h>
class SCH_SCREEN;
class SCH_SHEET_PATH;
@ -133,9 +149,8 @@ public:
int unit = 0, int convert = 0,
const wxPoint& pos = wxPoint( 0, 0 ) );
SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* aSheet,
SCH_BASE_FRAME::COMPONENT_SELECTION& aSel,
const wxPoint& pos = wxPoint( 0, 0 ) );
SCH_COMPONENT( LIB_PART& aPart, SCH_SHEET_PATH* aSheet, COMPONENT_SELECTION& aSel,
const wxPoint& pos = wxPoint( 0, 0 ) );
/**
* Clones \a aComponent into a new schematic symbol object.
*
@ -204,18 +219,11 @@ public:
bool Resolve( SYMBOL_LIB_TABLE& aLibTable, PART_LIB* aCacheLib = NULL );
static void ResolveAll( const EE_COLLECTOR& aComponents, SYMBOL_LIB_TABLE& aLibTable,
PART_LIB* aCacheLib = NULL );
static void ResolveAll( std::vector<SCH_COMPONENT*>& aComponents, SYMBOL_LIB_TABLE& aLibTable,
PART_LIB* aCacheLib = NULL );
int GetUnit() const { return m_unit; }
/**
* Update the pin cache for all components in \a aComponents
*
* @param aComponents collector of components in screen
*/
static void UpdatePins( const EE_COLLECTOR& aComponents );
/**
* Updates the local cache of SCH_PIN_CONNECTION objects for each pin
*/

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@
#include <lib_view_frame.h>
#include <pgm_base.h>
#include <profile.h>
#include <project.h>
#include <reporter.h>
#include <sch_edit_frame.h>
#include <sch_painter.h>
@ -584,8 +585,7 @@ void SCH_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
wxString fileName = Prj().AbsolutePath( g_RootSheet->GetScreen()->GetFileName() );
if( !g_RootSheet->GetScreen()->GetFileName().IsEmpty() &&
g_RootSheet->GetScreen()->GetDrawItems() != NULL )
if( !g_RootSheet->GetScreen()->GetFileName().IsEmpty() && !g_RootSheet->GetScreen()->IsEmpty() )
{
UpdateFileHistory( fileName );
}
@ -1165,30 +1165,29 @@ void SCH_EDIT_FRAME::FixupJunctions()
for( const SCH_SHEET_PATH& sheet : sheetList )
{
std::vector<wxPoint> anchors;
std::vector<wxPoint> junctions;
SetCurrentSheet( sheet );
GetCurrentSheet().UpdateAllScreenReferences();
auto screen = GetCurrentSheet().LastScreen();
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
for( auto aItem : screen->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() == SCH_COMPONENT_T )
auto cmp = static_cast<SCH_COMPONENT*>( aItem );
auto xform = cmp->GetTransform();
for( const SCH_PIN& pin : cmp->GetPins() )
{
auto cmp = static_cast<SCH_COMPONENT*>( item );
auto xform = cmp->GetTransform();
auto pos = cmp->GetPosition() + xform.TransformCoordinate( pin.GetPosition() );
for( const SCH_PIN& pin : cmp->GetPins() )
{
auto pos = cmp->GetPosition() + xform.TransformCoordinate( pin.GetPosition() );
// Test if a _new_ junction is needed, and add it if missing
if ( screen->IsJunctionNeeded( pos, true ) )
AddJunction( pos );
}
// Test if a _new_ junction is needed, and add it if missing
if( screen->IsJunctionNeeded( pos, true ) )
junctions.push_back( pos );
}
}
for( auto& pos : junctions )
AddJunction( pos );
}
// Reselect the initial sheet:

View File

@ -26,20 +26,29 @@
#ifndef SCH_EDIT_FRAME_H
#define SCH_EDIT_FRAME_H
#include <sch_base_frame.h>
#include <stddef.h>
#include <vector>
#include <wx/cmndata.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <wx/utils.h>
#include <config_params.h>
#include <undo_redo_container.h>
#include <template_fieldnames.h>
#include <ee_collectors.h>
#include <tool/selection.h>
#include <core/typeinfo.h>
#include <eda_base_frame.h>
#include <erc_settings.h>
#include <sch_draw_panel.h>
#include <sch_text.h> // enum PINSHEETLABEL_SHAPE
#include <tool/selection.h>
#include <status_popup.h>
#include <math/box2.h>
#include <sch_base_frame.h>
#include <sch_text.h> // enum PINSHEETLABEL_SHAPE
#include <template_fieldnames.h>
#include <undo_redo_container.h>
class STATUS_TEXT_POPUP;
class SCH_ITEM;
class EDA_ITEM;
class SCH_LINE;
class SCH_TEXT;
class SCH_BITMAP;
class SCH_SHEET;
@ -916,9 +925,7 @@ public:
* UR_MOVED
*
* If it is a delete command, items are put on list with the .Flags member
* set to UR_DELETED. When it will be really deleted, the GetDrawItems() and the
* sub-hierarchy will be deleted. If it is only a copy, the GetDrawItems() and the
* sub-hierarchy must NOT be deleted.
* set to UR_DELETED.
*
* @note
* Edit wires and buses is a bit complex.

View File

@ -73,7 +73,7 @@ public:
return wxT( "SCH_FIELD" );
}
bool IsType( const KICAD_T aScanTypes[] ) override
bool IsType( const KICAD_T aScanTypes[] ) const override
{
if( SCH_ITEM::IsType( aScanTypes ) )
return true;

View File

@ -29,12 +29,12 @@
#include <unordered_set>
#include <vector>
#include <base_screen.h>
#include <base_struct.h>
#include <general.h>
#include <sch_sheet_path.h>
class SCH_ITEM;
class SCH_CONNECTION;
class SCH_SHEET_PATH;
class LINE_READER;
class SCH_EDIT_FRAME;
class wxFindReplaceData;
@ -172,9 +172,6 @@ public:
*/
virtual void SwapData( SCH_ITEM* aItem );
SCH_ITEM* Next() const { return static_cast<SCH_ITEM*>( Pnext ); }
SCH_ITEM* Back() const { return static_cast<SCH_ITEM*>( Pback ); }
/**
* Routine to create a new copy of given item.
* The new object is not put in draw list (not linked).

View File

@ -690,27 +690,20 @@ void SCH_LEGACY_PLUGIN::loadHierarchy( SCH_SHEET* aSheet )
try
{
loadFile( fileName.GetFullPath(), aSheet->GetScreen() );
EDA_ITEM* item = aSheet->GetScreen()->GetDrawItems();
while( item )
for( auto aItem : aSheet->GetScreen()->Items().OfType( SCH_SHEET_T ) )
{
if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
assert( aItem->Type() == SCH_SHEET_T );
auto sheet = static_cast<SCH_SHEET*>( aItem );
// Set the parent to aSheet. This effectively creates a method to find
// the root sheet from any sheet so a pointer to the root sheet does not
// need to be stored globally. Note: this is not the same as a hierarchy.
// Complex hierarchies can have multiple copies of a sheet. This only
// provides a simple tree to find the root sheet.
sheet->SetParent( aSheet );
// Set the parent to aSheet. This effectively creates a method to find
// the root sheet from any sheet so a pointer to the root sheet does not
// need to be stored globally. Note: this is not the same as a hierarchy.
// Complex hierarchies can have multiple copies of a sheet. This only
// provides a simple tree to find the root sheet.
sheet->SetParent( aSheet );
// Recursion starts here.
loadHierarchy( sheet );
}
item = item->Next();
// Recursion starts here.
loadHierarchy( sheet );
}
}
catch( const IO_ERROR& ioe )
@ -1883,37 +1876,37 @@ void SCH_LEGACY_PLUGIN::Format( SCH_SCREEN* aScreen )
saveBusAlias( alias );
}
for( SCH_ITEM* item = aScreen->GetDrawItems(); item; item = item->Next() )
for( auto item : aScreen->Items() )
{
switch( item->Type() )
{
case SCH_COMPONENT_T:
saveComponent( static_cast< SCH_COMPONENT* >( item ) );
saveComponent( static_cast<SCH_COMPONENT*>( item ) );
break;
case SCH_BITMAP_T:
saveBitmap( static_cast< SCH_BITMAP* >( item ) );
saveBitmap( static_cast<SCH_BITMAP*>( item ) );
break;
case SCH_SHEET_T:
saveSheet( static_cast< SCH_SHEET* >( item ) );
saveSheet( static_cast<SCH_SHEET*>( item ) );
break;
case SCH_JUNCTION_T:
saveJunction( static_cast< SCH_JUNCTION* >( item ) );
saveJunction( static_cast<SCH_JUNCTION*>( item ) );
break;
case SCH_NO_CONNECT_T:
saveNoConnect( static_cast< SCH_NO_CONNECT* >( item ) );
saveNoConnect( static_cast<SCH_NO_CONNECT*>( item ) );
break;
case SCH_BUS_WIRE_ENTRY_T:
case SCH_BUS_BUS_ENTRY_T:
saveBusEntry( static_cast< SCH_BUS_ENTRY_BASE* >( item ) );
saveBusEntry( static_cast<SCH_BUS_ENTRY_BASE*>( item ) );
break;
case SCH_LINE_T:
saveLine( static_cast< SCH_LINE* >( item ) );
saveLine( static_cast<SCH_LINE*>( item ) );
break;
case SCH_TEXT_T:
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
saveText( static_cast< SCH_TEXT* >( item ) );
saveText( static_cast<SCH_TEXT*>( item ) );
break;
default:
wxASSERT( "Unexpected schematic object type in SCH_LEGACY_PLUGIN::Format()" );

View File

@ -72,7 +72,7 @@ public:
return wxT( "SCH_LINE" );
}
bool IsType( const KICAD_T aScanTypes[] ) override
bool IsType( const KICAD_T aScanTypes[] ) const override
{
if( SCH_ITEM::IsType( aScanTypes ) )
return true;

View File

@ -27,39 +27,40 @@
#include <sch_item.h>
#include <lib_item.h>
#include <lib_rectangle.h>
#include <lib_pin.h>
#include <lib_circle.h>
#include <lib_polyline.h>
#include <lib_arc.h>
#include <lib_field.h>
#include <lib_text.h>
#include <lib_bezier.h>
#include <sch_line.h>
#include <sch_component.h>
#include <sch_field.h>
#include <sch_junction.h>
#include <sch_text.h>
#include <sch_no_connect.h>
#include <sch_bus_entry.h>
#include <sch_bitmap.h>
#include <sch_sheet.h>
#include <gr_text.h>
#include <geometry/geometry_utils.h>
#include <lib_edit_frame.h>
#include <plotter.h>
#include <template_fieldnames.h>
#include <bezier_curves.h>
#include <class_libentry.h>
#include <class_library.h>
#include <sch_edit_frame.h>
#include <view/view.h>
#include <gal/graphics_abstraction_layer.h>
#include <colors_design_settings.h>
#include <connection_graph.h>
#include <gal/graphics_abstraction_layer.h>
#include <geometry/geometry_utils.h>
#include <geometry/shape_line_chain.h>
#include <bezier_curves.h>
#include <gr_text.h>
#include <lib_arc.h>
#include <lib_bezier.h>
#include <lib_circle.h>
#include <lib_edit_frame.h>
#include <lib_field.h>
#include <lib_item.h>
#include <lib_pin.h>
#include <lib_polyline.h>
#include <lib_rectangle.h>
#include <lib_text.h>
#include <math/util.h> // for KiROUND
#include <plotter.h>
#include <sch_bitmap.h>
#include <sch_bus_entry.h>
#include <sch_component.h>
#include <sch_edit_frame.h>
#include <sch_field.h>
#include <sch_junction.h>
#include <sch_line.h>
#include <sch_marker.h>
#include <sch_no_connect.h>
#include <sch_sheet.h>
#include <sch_text.h>
#include <template_fieldnames.h>
#include <view/view.h>
#include "sch_painter.h"

View File

@ -22,9 +22,10 @@
#ifndef _SCH_PIN_CONNECTION_H
#define _SCH_PIN_CONNECTION_H
#include <lib_pin.h>
#include <msgpanel.h>
#include <sch_item.h>
#include <sch_sheet_path.h>
#include <lib_pin.h>
#include <mutex>
#include <map>

View File

@ -99,6 +99,11 @@ public:
const SCH_SHEET_PATH& GetSheetPath() const { return m_SheetPath; }
SCH_SHEET_PATH& GetSheetPath()
{
return m_SheetPath;
}
int GetUnit() const { return m_Unit; }
void SetSheetNumber( int aSheetNumber ) { m_SheetNum = aSheetNumber; }

276
eeschema/sch_rtree.h Normal file
View File

@ -0,0 +1,276 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2020 CERN
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef EESCHEMA_SCH_RTREE_H_
#define EESCHEMA_SCH_RTREE_H_
#include <core/typeinfo.h>
#include <eda_rect.h>
#include <sch_item.h>
#include <set>
#include <vector>
#include <geometry/rtree.h>
/**
* EE_RTREE -
* Implements an R-tree for fast spatial and type indexing of schematic items.
* Non-owning.
*/
class EE_RTREE
{
private:
using ee_rtree = RTree<SCH_ITEM*, int, 3, double>;
public:
EE_RTREE()
{
this->m_tree = new ee_rtree();
m_count = 0;
}
~EE_RTREE()
{
delete this->m_tree;
}
/**
* Function Insert()
* Inserts an item into the tree. Item's bounding box is taken via its BBox() method.
*/
void insert( SCH_ITEM* aItem )
{
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
m_tree->Insert( mmin, mmax, aItem );
m_count++;
}
/**
* Function Remove()
* Removes an item from the tree. Removal is done by comparing pointers, attempting
* to remove a copy of the item will fail.
*/
bool remove( SCH_ITEM* aItem )
{
// First, attempt to remove the item using its given BBox
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
// If we are not successful ( true == not found ), then we expand
// the search to the full tree
if( m_tree->Remove( mmin, mmax, aItem ) )
{
// N.B. We must search the whole tree for the pointer to remove
// because the item may have been moved before we have the chance to
// delete it from the tree
const int mmin2[3] = { INT_MIN, INT_MIN, INT_MIN };
const int mmax2[3] = { INT_MAX, INT_MAX, INT_MAX };
if( m_tree->Remove( mmin2, mmax2, aItem ) )
return false;
}
m_count--;
return true;
}
/**
* Function RemoveAll()
* Removes all items from the RTree
*/
void clear()
{
m_tree->RemoveAll();
m_count = 0;
}
/**
* Determine if a given item exists in the tree. Note that this does not search the full tree
* so if the item has been moved, this will return false when it should be true.
*
* @param aItem Item that may potentially exist in the tree
* @param aRobust If true, search the whole tree, not just the bounding box
* @return true if the item definitely exists, false if it does not exist within bbox
*/
bool contains( SCH_ITEM* aItem, bool aRobust = false )
{
const EDA_RECT& bbox = aItem->GetBoundingBox();
const int type = int( aItem->Type() );
const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
bool found = false;
auto search = [&found, &aItem]( const SCH_ITEM* aSearchItem ) {
if( aSearchItem == aItem )
{
found = true;
return false;
}
return true;
};
m_tree->Search( mmin, mmax, search );
if( !found && aRobust )
{
// N.B. We must search the whole tree for the pointer to remove
// because the item may have been moved. We do not expand the item
// type search as this should not change.
const int mmin2[3] = { type, INT_MIN, INT_MIN };
const int mmax2[3] = { type, INT_MAX, INT_MAX };
m_tree->Search( mmin2, mmax2, search );
}
return found;
}
/**
* Returns the number of items in the tree
* @return number of elements in the tree;
*/
size_t size()
{
return m_count;
}
bool empty()
{
return m_count == 0;
}
using iterator = typename ee_rtree::Iterator;
/**
* The EE_TYPE struct provides a type-specific auto-range iterator to the RTree. Using
* this struct, one can write lines like:
*
* for( auto item : rtree.OfType( SCH_COMPONENT_T ) )
*
* and iterate over the RTree items that are components only
*/
struct EE_TYPE
{
EE_TYPE( ee_rtree* aTree, KICAD_T aType ) : type_tree( aTree )
{
KICAD_T type = BaseType( aType );
if( type == SCH_LOCATE_ANY_T )
m_rect = { { INT_MIN, INT_MIN, INT_MIN }, { INT_MAX, INT_MAX, INT_MAX } };
else
m_rect = { { type, INT_MIN, INT_MIN }, { type, INT_MAX, INT_MAX } };
};
EE_TYPE( ee_rtree* aTree, KICAD_T aType, const EDA_RECT aRect ) : type_tree( aTree )
{
KICAD_T type = BaseType( aType );
if( type == SCH_LOCATE_ANY_T )
m_rect = { { INT_MIN, aRect.GetX(), aRect.GetY() },
{ INT_MAX, aRect.GetRight(), aRect.GetBottom() } };
else
m_rect = { { type, aRect.GetX(), aRect.GetY() },
{ type, aRect.GetRight(), aRect.GetBottom() } };
};
ee_rtree::Rect m_rect;
ee_rtree* type_tree;
iterator begin()
{
return type_tree->begin( m_rect );
}
iterator end()
{
return type_tree->end( m_rect );
}
};
EE_TYPE OfType( KICAD_T aType )
{
return EE_TYPE( m_tree, aType );
}
EE_TYPE Overlapping( const EDA_RECT& aRect )
{
return EE_TYPE( m_tree, SCH_LOCATE_ANY_T, aRect );
}
EE_TYPE Overlapping( const wxPoint& aPoint, int aAccuracy = 0 )
{
EDA_RECT rect( aPoint, wxSize( 0, 0 ) );
rect.Inflate( aAccuracy );
return EE_TYPE( m_tree, SCH_LOCATE_ANY_T, rect );
}
EE_TYPE Overlapping( KICAD_T aType, const wxPoint& aPoint, int aAccuracy = 0 )
{
EDA_RECT rect( aPoint, wxSize( 0, 0 ) );
rect.Inflate( aAccuracy );
return EE_TYPE( m_tree, aType, rect );
}
EE_TYPE Overlapping( KICAD_T aType, const EDA_RECT& aRect )
{
return EE_TYPE( m_tree, aType, aRect );
}
iterator begin()
{
return m_tree->begin();
}
iterator end()
{
return m_tree->end();
}
const iterator begin() const
{
return m_tree->begin();
}
const iterator end() const
{
return m_tree->end();
}
private:
ee_rtree* m_tree;
size_t m_count;
};
#endif /* EESCHEMA_SCH_RTREE_H_ */

View File

@ -29,32 +29,36 @@
* @brief Implementation of SCH_SCREEN and SCH_SCREENS classes.
*/
#include <common.h>
#include <eda_rect.h>
#include <eeschema_id.h>
#include <fctsys.h>
#include <gr_basic.h>
#include <common.h>
#include <kicad_string.h>
#include <id.h>
#include <pgm_base.h>
#include <kiway.h>
#include <sch_draw_panel.h>
#include <sch_item.h>
#include <gr_text.h>
#include <sch_edit_frame.h>
#include <id.h>
#include <kicad_string.h>
#include <kiway.h>
#include <pgm_base.h>
#include <plotter.h>
#include <project.h>
#include <sch_draw_panel.h>
#include <sch_edit_frame.h>
#include <sch_item.h>
#include <netlist.h>
#include <netlist_object.h>
#include <class_library.h>
#include <connection_graph.h>
#include <sch_junction.h>
#include <lib_pin.h>
#include <netlist.h>
#include <netlist_object.h>
#include <sch_bus_entry.h>
#include <sch_component.h>
#include <sch_junction.h>
#include <sch_line.h>
#include <sch_marker.h>
#include <sch_no_connect.h>
#include <sch_rtree.h>
#include <sch_sheet.h>
#include <sch_component.h>
#include <sch_text.h>
#include <lib_pin.h>
#include <symbol_lib_table.h>
#include <tool/common_tools.h>
@ -66,8 +70,6 @@
// TODO(JE) Debugging only
#include <profile.h>
#include <boost/foreach.hpp>
#define EESCHEMA_FILE_STAMP "EESchema"
#define ZOOM_FACTOR( x ) ( x * IU_PER_MILS )
@ -152,13 +154,7 @@ SCH_SCREEN::SCH_SCREEN( KIWAY* aKiway ) :
SCH_SCREEN::~SCH_SCREEN()
{
ClearUndoRedoList();
// Now delete items in draw list. We do that only if the list is not empty, because if the
// list was appended to another list (see SCH_SCREEN::Append( SCH_SCREEN* aScreen ) it is
// empty but as no longer the ownership (m_drawList.meOwner == false) of items, and calling
// FreeDrawList() with m_drawList.meOwner == false will generate a debug alert in debug mode
if( GetDrawItems() )
FreeDrawList();
FreeDrawList();
}
@ -176,23 +172,33 @@ void SCH_SCREEN::DecRefCount()
}
void SCH_SCREEN::Append( SCH_ITEM* aItem )
{
m_rtree.insert( aItem );
--m_modification_sync;
}
void SCH_SCREEN::Append( SCH_SCREEN* aScreen )
{
wxCHECK_RET( aScreen, "Invalid screen object." );
// No need to decend the hierarchy. Once the top level screen is copied, all of it's
// No need to descend the hierarchy. Once the top level screen is copied, all of it's
// children are copied as well.
m_drawList.Append( aScreen->m_drawList );
for( auto aItem : aScreen->m_rtree )
m_rtree.insert( aItem );
// This screen owns the objects now. This prevents the object from being delete when
// aSheet is deleted.
aScreen->m_drawList.SetOwnership( false );
--m_modification_sync;
aScreen->Clear( false );
}
void SCH_SCREEN::Clear()
void SCH_SCREEN::Clear( bool aFree )
{
FreeDrawList();
if( aFree )
FreeDrawList();
else
m_rtree.clear();
// Clear the project settings
m_ScreenNumber = m_NumberOfScreens = 1;
@ -203,13 +209,32 @@ void SCH_SCREEN::Clear()
void SCH_SCREEN::FreeDrawList()
{
m_drawList.DeleteAll();
// We don't know which order we will encounter dependent items (e.g. pins or fields), so
// we store the items to be deleted until we've fully cleared the tree before deleting
std::vector<SCH_ITEM*> delete_list;
std::copy_if( m_rtree.begin(), m_rtree.end(), std::back_inserter( delete_list ),
[]( SCH_ITEM* aItem ) {
return ( aItem->Type() != SCH_SHEET_PIN_T && aItem->Type() != SCH_FIELD_T );
} );
m_rtree.clear();
for( auto item : delete_list )
delete item;
}
void SCH_SCREEN::Update( SCH_ITEM* aItem )
{
Remove( aItem );
Append( aItem );
}
void SCH_SCREEN::Remove( SCH_ITEM* aItem )
{
m_drawList.Remove( aItem );
m_rtree.remove( aItem );
}
@ -218,6 +243,7 @@ void SCH_SCREEN::DeleteItem( SCH_ITEM* aItem )
wxCHECK_RET( aItem, wxT( "Cannot delete invalid item from screen." ) );
SetModify();
Remove( aItem );
if( aItem->Type() == SCH_SHEET_PIN_T )
{
@ -230,7 +256,6 @@ void SCH_SCREEN::DeleteItem( SCH_ITEM* aItem )
}
else
{
m_drawList.Remove( aItem );
delete aItem;
}
}
@ -238,130 +263,69 @@ void SCH_SCREEN::DeleteItem( SCH_ITEM* aItem )
bool SCH_SCREEN::CheckIfOnDrawList( SCH_ITEM* aItem )
{
SCH_ITEM* itemList = m_drawList.begin();
while( itemList )
{
if( itemList == aItem )
return true;
itemList = itemList->Next();
}
return false;
return m_rtree.contains( aItem, true );
}
SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType ) const
SCH_ITEM* SCH_SCREEN::GetItem( const wxPoint& aPosition, int aAccuracy, KICAD_T aType )
{
KICAD_T types[] = { aType, EOT };
EDA_RECT bbox;
bbox.SetOrigin( aPosition );
bbox.Inflate( aAccuracy );
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().Overlapping( aType, bbox ) )
{
switch( item->Type() )
{
case SCH_COMPONENT_T:
{
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
for( int i = REFERENCE; i < component->GetFieldCount(); i++ )
{
SCH_FIELD* field = component->GetField( i );
if( field->IsType( types ) && field->HitTest( aPosition, aAccuracy ) )
return field;
}
break;
}
case SCH_SHEET_T:
{
SCH_SHEET* sheet = (SCH_SHEET*)item;
SCH_SHEET_PIN* pin = sheet->GetPin( aPosition );
if( pin && pin->IsType( types ) )
return pin;
break;
}
default:
break;
}
if( item->IsType( types ) && item->HitTest( aPosition, aAccuracy ) )
if( item->HitTest( aPosition, aAccuracy ) )
return item;
}
return NULL;
return nullptr;
}
void SCH_SCREEN::ReplaceWires( DLIST< SCH_ITEM >& aWireList )
std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
{
SCH_ITEM* item;
SCH_ITEM* next_item;
std::set<SCH_ITEM*> retval;
std::stack<SCH_LINE*> to_search;
for( item = m_drawList.begin(); item; item = next_item )
wxCHECK_MSG( ( aSegment ) && ( aSegment->Type() == SCH_LINE_T ), retval,
wxT( "Invalid object pointer." ) );
to_search.push( aSegment );
while( !to_search.empty() )
{
next_item = item->Next();
auto test_item = to_search.top();
to_search.pop();
switch( item->Type() )
for( auto item : Items().Overlapping( SCH_JUNCTION_T, test_item->GetBoundingBox() ) )
{
case SCH_JUNCTION_T:
case SCH_LINE_T:
Remove( item );
delete item;
break;
if( test_item->IsEndPoint( item->GetPosition() ) )
retval.insert( item );
}
default:
break;
for( auto item : Items().Overlapping( SCH_LINE_T, test_item->GetBoundingBox() ) )
{
// Skip connecting lines on different layers (e.g. busses)
if( test_item->GetLayer() != item->GetLayer() )
continue;
auto line = static_cast<SCH_LINE*>( item );
if( ( test_item->IsEndPoint( line->GetStartPoint() )
&& !GetPin( line->GetStartPoint(), NULL, true ) )
|| ( test_item->IsEndPoint( line->GetEndPoint() )
&& !GetPin( line->GetEndPoint(), nullptr, true ) ) )
{
auto result = retval.insert( line );
if( result.second )
to_search.push( line );
}
}
}
m_drawList.Append( aWireList );
}
void SCH_SCREEN::MarkConnections( SCH_LINE* aSegment )
{
wxCHECK_RET( (aSegment) && (aSegment->Type() == SCH_LINE_T),
wxT( "Invalid object pointer." ) );
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
{
if( item->HasFlag( CANDIDATE ) )
continue;
if( item->Type() == SCH_JUNCTION_T )
{
SCH_JUNCTION* junction = (SCH_JUNCTION*) item;
if( aSegment->IsEndPoint( junction->GetPosition() ) )
item->SetFlags( CANDIDATE );
continue;
}
if( item->Type() != SCH_LINE_T )
continue;
SCH_LINE* segment = (SCH_LINE*) item;
if( aSegment->IsEndPoint( segment->GetStartPoint() )
&& !GetPin( segment->GetStartPoint(), NULL, true ) )
{
item->SetFlags( CANDIDATE );
MarkConnections( segment );
}
if( aSegment->IsEndPoint( segment->GetEndPoint() )
&& !GetPin( segment->GetEndPoint(), NULL, true ) )
{
item->SetFlags( CANDIDATE );
MarkConnections( segment );
}
}
return retval;
}
@ -375,7 +339,7 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
std::vector<SCH_LINE*> lines[ sizeof( layers ) ];
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().Overlapping( aPosition ) )
{
if( item->GetEditFlags() & STRUCT_DELETED )
continue;
@ -386,9 +350,9 @@ bool SCH_SCREEN::IsJunctionNeeded( const wxPoint& aPosition, bool aNew )
if( ( item->Type() == SCH_LINE_T ) && ( item->HitTest( aPosition, 0 ) ) )
{
if( item->GetLayer() == LAYER_WIRE )
lines[ WIRES ].push_back( (SCH_LINE*) item );
lines[WIRES].push_back( (SCH_LINE*) item );
else if( item->GetLayer() == LAYER_BUS )
lines[ BUSSES ].push_back( (SCH_LINE*) item );
lines[BUSSES].push_back( (SCH_LINE*) item );
}
if( ( item->Type() == SCH_COMPONENT_T ) && ( item->IsConnected( aPosition ) ) )
@ -525,25 +489,30 @@ void SCH_SCREEN::UpdateSymbolLinks( bool aForce )
// Initialize or reinitialize the pointer to the LIB_PART for each component
// found in m_drawList, but only if needed (change in lib or schematic)
// therefore the calculation time is usually very low.
if( m_drawList.GetCount() )
if( !IsEmpty() )
{
std::vector<SCH_COMPONENT*> cmps;
SYMBOL_LIB_TABLE* libs = Prj().SchSymbolLibTable();
int mod_hash = libs->GetModifyHash();
EE_TYPE_COLLECTOR c;
c.Collect( GetDrawItems(), EE_COLLECTOR::ComponentsOnly );
for( auto aItem : Items().OfType( SCH_COMPONENT_T ) )
cmps.push_back( static_cast<SCH_COMPONENT*>( aItem ) );
// Must we resolve?
if( (m_modification_sync != mod_hash) || aForce )
{
SCH_COMPONENT::ResolveAll( c, *libs, Prj().SchLibs()->GetCacheLibrary() );
SCH_COMPONENT::ResolveAll( cmps, *libs, Prj().SchLibs()->GetCacheLibrary() );
m_modification_sync = mod_hash; // note the last mod_hash
}
// Resolving will update the pin caches but we must ensure that this happens
// even if the libraries don't change.
else
SCH_COMPONENT::UpdatePins( c );
{
for( auto cmp : cmps )
cmp->UpdatePins();
}
}
}
@ -555,7 +524,7 @@ void SCH_SCREEN::Print( wxDC* aDC )
// Ensure links are up to date, even if a library was reloaded for some reason:
UpdateSymbolLinks();
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
{
if( item->IsMoving() || item->IsResized() )
continue;
@ -581,7 +550,7 @@ void SCH_SCREEN::Plot( PLOTTER* aPlotter )
// Ensure links are up to date, even if a library was reloaded for some reason:
UpdateSymbolLinks();
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
{
if( item->IsMoving() || item->IsResized() )
continue;
@ -636,24 +605,20 @@ void SCH_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
void SCH_SCREEN::ClearDrawingState()
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
item->ClearTempFlags();
}
LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent,
bool aEndPointOnly ) const
LIB_PIN* SCH_SCREEN::GetPin(
const wxPoint& aPosition, SCH_COMPONENT** aComponent, bool aEndPointOnly )
{
SCH_ITEM* item;
SCH_COMPONENT* component = NULL;
LIB_PIN* pin = NULL;
for( item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().Overlapping( SCH_COMPONENT_T, aPosition ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
component = (SCH_COMPONENT*) item;
component = static_cast<SCH_COMPONENT*>( item );
if( aEndPointOnly )
{
@ -698,12 +663,9 @@ LIB_PIN* SCH_SCREEN::GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponen
SCH_SHEET* SCH_SCREEN::GetSheet( const wxString& aName )
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().OfType( SCH_SHEET_T ) )
{
if( item->Type() != SCH_SHEET_T )
continue;
SCH_SHEET* sheet = (SCH_SHEET*) item;
auto sheet = static_cast<SCH_SHEET*>( item );
if( aName.CmpNoCase( sheet->GetName() ) == 0 )
return sheet;
@ -715,14 +677,12 @@ SCH_SHEET* SCH_SCREEN::GetSheet( const wxString& aName )
SCH_SHEET_PIN* SCH_SCREEN::GetSheetLabel( const wxPoint& aPosition )
{
SCH_SHEET_PIN* sheetPin = NULL;
SCH_SHEET_PIN* sheetPin = nullptr;
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().OfType( SCH_SHEET_T ) )
{
if( item->Type() != SCH_SHEET_T )
continue;
auto sheet = static_cast<SCH_SHEET*>( item );
SCH_SHEET* sheet = (SCH_SHEET*) item;
sheetPin = sheet->GetPin( aPosition );
if( sheetPin )
@ -733,17 +693,13 @@ SCH_SHEET_PIN* SCH_SCREEN::GetSheetLabel( const wxPoint& aPosition )
}
int SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const
size_t SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions )
{
SCH_ITEM* item;
int count = 0;
size_t count = 0;
for( item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
{
if( item->Type() == SCH_JUNCTION_T && !aTestJunctions )
continue;
if( item->IsConnected( aPos ) )
if( ( item->Type() != SCH_JUNCTION_T || aTestJunctions ) && item->IsConnected( aPos ) )
count++;
}
@ -753,19 +709,17 @@ int SCH_SCREEN::CountConnectedItems( const wxPoint& aPos, bool aTestJunctions )
void SCH_SCREEN::ClearAnnotation( SCH_SHEET_PATH* aSheetPath )
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
auto component = static_cast<SCH_COMPONENT*>( item );
component->ClearAnnotation( aSheetPath );
component->ClearAnnotation( aSheetPath );
// Clear the modified component flag set by component->ClearAnnotation
// because we do not use it here and we should not leave this flag set,
// when an editing is finished:
component->ClearFlags();
}
// Clear the modified component flag set by component->ClearAnnotation
// because we do not use it here and we should not leave this flag set,
// when an editing is finished:
component->ClearFlags();
}
}
@ -775,42 +729,36 @@ void SCH_SCREEN::EnsureAlternateReferencesExist()
if( GetClientSheetPathsCount() <= 1 ) // No need for alternate reference
return;
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
auto component = static_cast<SCH_COMPONENT*>( item );
// Add (when not existing) all sheet path entries
for( unsigned int ii = 0; ii < m_clientSheetPathList.GetCount(); ii++ )
((SCH_COMPONENT*)item)->AddSheetPathReferenceEntryIfMissing( m_clientSheetPathList[ii] );
component->AddSheetPathReferenceEntryIfMissing( m_clientSheetPathList[ii] );
}
}
void SCH_SCREEN::GetHierarchicalItems( EDA_ITEMS& aItems )
{
SCH_ITEM* item = m_drawList.begin();
while( item )
for( auto item : Items() )
{
if( ( item->Type() == SCH_SHEET_T ) || ( item->Type() == SCH_COMPONENT_T ) )
aItems.push_back( item );
item = item->Next();
}
}
bool SCH_SCREEN::TestDanglingEnds()
{
SCH_ITEM* item;
std::vector< DANGLING_END_ITEM > endPoints;
bool hasStateChanged = false;
for( item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
item->GetEndPoints( endPoints );
for( item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
{
if( item->UpdateDanglingState( endPoints ) )
hasStateChanged = true;
@ -820,24 +768,10 @@ bool SCH_SCREEN::TestDanglingEnds()
}
SCH_LINE* SCH_SCREEN::GetWireOrBus( const wxPoint& aPosition )
{
static KICAD_T types[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
{
if( item->IsType( types ) && item->HitTest( aPosition ) )
return (SCH_LINE*) item;
}
return nullptr;
}
SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLayer,
SCH_LINE_TEST_T aSearchType )
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items() )
{
if( item->Type() != SCH_LINE_T )
continue;
@ -870,7 +804,7 @@ SCH_LINE* SCH_SCREEN::GetLine( const wxPoint& aPosition, int aAccuracy, int aLay
SCH_TEXT* SCH_SCREEN::GetLabel( const wxPoint& aPosition, int aAccuracy )
{
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().Overlapping( aPosition, aAccuracy ) )
{
switch( item->Type() )
{
@ -895,12 +829,9 @@ bool SCH_SCREEN::SetComponentFootprint( SCH_SHEET_PATH* aSheetPath, const wxStri
SCH_COMPONENT* component;
bool found = false;
for( SCH_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( auto item : Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
component = (SCH_COMPONENT*) item;
component = static_cast<SCH_COMPONENT*>( item );
if( aReference.CmpNoCase( component->GetRef( aSheetPath ) ) == 0 )
{
@ -982,10 +913,9 @@ void SCH_SCREEN::Show( int nestLevel, std::ostream& os ) const
{
// for now, make it look like XML, expand on this later.
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() << ">\n";
for( EDA_ITEM* item = m_drawList.begin(); item; item = item->Next() )
for( const auto item : Items() )
{
item->Show( nestLevel+1, os );
item->Show( nestLevel + 1, os );
}
NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
@ -1057,17 +987,8 @@ void SCH_SCREENS::buildScreenList( SCH_SHEET* aSheet )
addScreenToList( screen );
EDA_ITEM* strct = screen->GetDrawItems();
while( strct )
{
if( strct->Type() == SCH_SHEET_T )
{
buildScreenList( ( SCH_SHEET* )strct );
}
strct = strct->Next();
}
for( auto item : screen->Items().OfType( SCH_SHEET_T ) )
buildScreenList( static_cast<SCH_SHEET*>( item ) );
}
}
@ -1167,26 +1088,20 @@ int SCH_SCREENS::ReplaceDuplicateTimeStamps()
void SCH_SCREENS::DeleteAllMarkers( enum MARKER_BASE::TYPEMARKER aMarkerType )
{
SCH_ITEM* item;
SCH_ITEM* nextItem;
SCH_MARKER* marker;
SCH_SCREEN* screen;
for( screen = GetFirst(); screen; screen = GetNext() )
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
{
for( item = screen->GetDrawItems(); item; item = nextItem )
std::vector<SCH_ITEM*> markers;
for( auto item : screen->Items().OfType( SCH_MARKER_T ) )
{
nextItem = item->Next();
if( static_cast<SCH_MARKER*>( item )->GetMarkerType() == aMarkerType )
markers.push_back( item );
}
if( item->Type() != SCH_MARKER_T )
continue;
marker = (SCH_MARKER*) item;
if( marker->GetMarkerType() != aMarkerType )
continue;
screen->DeleteItem( marker );
for( auto marker : markers )
{
screen->Remove( marker );
delete marker;
}
}
}
@ -1199,12 +1114,9 @@ int SCH_SCREENS::GetMarkerCount( enum MARKER_BASE::TYPEMARKER aMarkerType,
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
{
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
for( auto item : screen->Items().OfType( SCH_MARKER_T ) )
{
if( item->Type() != SCH_MARKER_T )
continue;
SCH_MARKER* marker = (SCH_MARKER*) item;
auto marker = static_cast<SCH_MARKER*>( item );
if( ( aMarkerType != MARKER_BASE::MARKER_UNSPEC ) &&
( marker->GetMarkerType() != aMarkerType ) )
@ -1270,64 +1182,36 @@ void SCH_SCREENS::TestDanglingEnds()
bool SCH_SCREENS::HasNoFullyDefinedLibIds()
{
SCH_COMPONENT* symbol;
SCH_ITEM* item;
SCH_ITEM* nextItem;
SCH_SCREEN* screen;
unsigned cnt = 0;
for( screen = GetFirst(); screen; screen = GetNext() )
{
for( item = screen->GetDrawItems(); item; item = nextItem )
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
nextItem = item->Next();
if( item->Type() != SCH_COMPONENT_T )
continue;
cnt += 1;
symbol = dynamic_cast< SCH_COMPONENT* >( item );
wxASSERT( symbol );
cnt++;
auto symbol = static_cast<SCH_COMPONENT*>( item );
if( !symbol->GetLibId().GetLibNickname().empty() )
return false;
}
}
if( cnt == 0 )
return false;
return true;
return cnt != 0;
}
size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
{
SCH_COMPONENT* symbol;
SCH_ITEM* item;
SCH_ITEM* nextItem;
SCH_SCREEN* screen;
wxString nickname;
for( screen = GetFirst(); screen; screen = GetNext() )
for( SCH_SCREEN* screen = GetFirst(); screen; screen = GetNext() )
{
for( item = screen->GetDrawItems(); item; item = nextItem )
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
nextItem = item->Next();
if( item->Type() != SCH_COMPONENT_T )
continue;
symbol = dynamic_cast< SCH_COMPONENT* >( item );
wxASSERT( symbol );
if( !symbol )
continue;
nickname = symbol->GetLibId().GetLibNickname();
auto symbol = static_cast<SCH_COMPONENT*>( item );
auto& nickname = symbol->GetLibId().GetLibNickname();
if( !nickname.empty() && ( aLibNicknames.Index( nickname ) == wxNOT_FOUND ) )
aLibNicknames.Add( nickname );;
aLibNicknames.Add( nickname );
}
}
@ -1337,23 +1221,14 @@ size_t SCH_SCREENS::GetLibNicknames( wxArrayString& aLibNicknames )
int SCH_SCREENS::ChangeSymbolLibNickname( const wxString& aFrom, const wxString& aTo )
{
SCH_COMPONENT* symbol;
SCH_ITEM* item;
SCH_ITEM* nextItem;
SCH_SCREEN* screen;
int cnt = 0;
for( screen = GetFirst(); screen; screen = GetNext() )
{
for( item = screen->GetDrawItems(); item; item = nextItem )
for( auto item : screen->Items().OfType( SCH_COMPONENT_T ) )
{
nextItem = item->Next();
if( item->Type() != SCH_COMPONENT_T )
continue;
symbol = dynamic_cast< SCH_COMPONENT* >( item );
wxASSERT( symbol );
auto symbol = static_cast<SCH_COMPONENT*>( item );
if( symbol->GetLibId().GetLibNickname() != aFrom )
continue;

View File

@ -25,30 +25,39 @@
#ifndef SCREEN_H
#define SCREEN_H
#include <memory>
#include <stddef.h>
#include <unordered_set>
#include <macros.h>
#include <dlist.h>
#include <sch_item.h>
#include <lib_item.h>
#include <base_screen.h>
#include <title_block.h>
#include <page_info.h>
#include <kiway_holder.h>
#include <sch_marker.h>
#include <bus_alias.h>
#include <vector>
#include <wx/arrstr.h>
#include <wx/chartype.h>
#include <wx/gdicmn.h>
#include <wx/string.h>
#include <base_screen.h>
#include <base_struct.h>
#include <core/typeinfo.h>
#include <kiway_holder.h>
#include <layers_id_colors_and_visibility.h>
#include <marker_base.h>
#include <page_info.h>
#include <template_fieldnames.h>
#include <title_block.h>
#include <lib_id.h>
#include <sch_rtree.h>
#include <sch_sheet.h>
#include <sch_sheet_path.h>
class BUS_ALIAS;
class LIB_PIN;
class SCH_COMPONENT;
class SCH_SHEET_LIST;
class SCH_SHEET_PATH;
class SCH_SHEET_PIN;
class SCH_LINE;
class SCH_TEXT;
class PLOTTER;
class SCH_SHEET_LIST;
enum SCH_LINE_TEST_T
{
ENTIRE_LENGTH_T,
@ -60,6 +69,18 @@ enum SCH_LINE_TEST_T
/// Max number of sheets in a hierarchy project
#define NB_MAX_SHEET 500
struct COMPONENT_SELECTION
{
LIB_ID LibId;
int Unit;
int Convert;
std::vector<std::pair<int, wxString>> Fields;
COMPONENT_SELECTION() : Unit( 1 ), Convert( 1 )
{
}
};
class SCH_SCREEN : public BASE_SCREEN, public KIWAY_HOLDER
{
@ -86,10 +107,10 @@ private:
/// Origin of the auxiliary axis, which is used in exports mostly, but not yet in EESCHEMA
wxPoint m_aux_origin;
DLIST< SCH_ITEM > m_drawList; ///< Object list for the screen.
EE_RTREE m_rtree;
int m_modification_sync; ///< inequality with PART_LIBS::GetModificationHash()
///< will trigger ResolveAll().
int m_modification_sync; ///< inequality with PART_LIBS::GetModificationHash()
///< will trigger ResolveAll().
/// List of bus aliases stored in this screen
std::unordered_set< std::shared_ptr< BUS_ALIAS > > m_aliases;
@ -103,7 +124,20 @@ public:
~SCH_SCREEN();
DLIST< SCH_ITEM > & GetDrawList() { return m_drawList; }
EE_RTREE& Items()
{
return m_rtree;
}
const EE_RTREE& Items() const
{
return m_rtree;
}
bool IsEmpty()
{
return m_rtree.empty();
}
static inline bool ClassOf( const EDA_ITEM* aItem )
{
@ -126,7 +160,7 @@ public:
void SetAuxOrigin( const wxPoint& aPosition ) { m_aux_origin = aPosition; }
const TITLE_BLOCK& GetTitleBlock() const { return m_titles; }
//TITLE_BLOCK& GetTitleBlock() const { return (TITLE_BLOCK&) m_titles; }
void SetTitleBlock( const TITLE_BLOCK& aTitleBlock ) { m_titles = aTitleBlock; }
void DecRefCount();
@ -146,16 +180,8 @@ public:
wxArrayString& GetClientSheetPaths() { return m_clientSheetPathList; }
/**
* @return A pointer to the first item in the linked list of draw items.
*/
SCH_ITEM* GetDrawItems() const { return m_drawList.begin(); }
void Append( SCH_ITEM* aItem )
{
m_drawList.Append( aItem );
--m_modification_sync;
}
void Append( SCH_ITEM* aItem );
/**
* Copy the contents of \a aScreen into this #SCH_SCREEN object.
@ -169,21 +195,10 @@ public:
*/
void Append( SCH_SCREEN* aScreen );
/**
* Add \a aList of SCH_ITEM objects to the list for draw items for the sheet.
*
* @param aList A reference to a #DLIST containing the #SCH_ITEM to add to the sheet.
*/
void Append( DLIST< SCH_ITEM >& aList )
{
m_drawList.Append( aList );
--m_modification_sync;
}
/**
* Delete all draw items and clears the project settings.
*/
void Clear();
void Clear( bool aFree = true );
/**
* Free all the items from the schematic associated with the screen.
@ -200,8 +215,8 @@ public:
* @param aType The type of item to find.
* @return The item found that meets the search criteria or NULL if none found.
*/
SCH_ITEM* GetItem( const wxPoint& aPosition, int aAccuracy = 0,
KICAD_T aType = SCH_LOCATE_ANY_T ) const;
SCH_ITEM* GetItem(
const wxPoint& aPosition, int aAccuracy = 0, KICAD_T aType = SCH_LOCATE_ANY_T );
void Place( SCH_EDIT_FRAME* frame, wxDC* DC ) { };
@ -248,6 +263,13 @@ public:
*/
void Remove( SCH_ITEM* aItem );
/**
* Updates \a aItem's bounding box in the tree
*
* @param aItem Item that needs to be updated.
*/
void Update( SCH_ITEM* aItem );
/**
* Removes \a aItem from the linked list and deletes the object.
*
@ -267,19 +289,12 @@ public:
bool TestDanglingEnds();
/**
* Replace all of the wires, buses, and junctions in the screen with \a aWireList.
*
* @param aWireList List of wires to replace the existing wires with.
*/
void ReplaceWires( DLIST< SCH_ITEM >& aWireList );
/**
* Add all wires and junctions connected to \a aSegment which are not connected any
* component pin to \a aItemList.
* Return all wires and junctions connected to \a aSegment which are not connected any
* component pin
*
* @param aSegment The segment to test for connections.
*/
void MarkConnections( SCH_LINE* aSegment );
std::set<SCH_ITEM*> MarkConnections( SCH_LINE* aSegment );
/* full undo redo management : */
// use BASE_SCREEN::PushCommandToUndoList( PICKED_ITEMS_LIST* aItem )
@ -304,7 +319,7 @@ public:
*/
void ClearDrawingState();
int CountConnectedItems( const wxPoint& aPos, bool aTestJunctions ) const;
size_t CountConnectedItems( const wxPoint& aPos, bool aTestJunctions );
/**
* Test if a junction is required for the items at \a aPosition on the screen.
@ -343,7 +358,7 @@ public:
* @return The pin item if found, otherwise NULL.
*/
LIB_PIN* GetPin( const wxPoint& aPosition, SCH_COMPONENT** aComponent = NULL,
bool aEndPointOnly = false ) const;
bool aEndPointOnly = false );
/**
* Returns a sheet object pointer that is named \a aName.
@ -388,14 +403,6 @@ public:
*/
void GetHierarchicalItems( EDA_ITEMS& aItems );
/**
* Return a wire or bus item located at \a aPosition.
*
* @param aPosition The wxPoint to test for node items.
* @return The SCH_LINE* of the wire or bus item found at \a aPosition or NULL if item not
* found.
*/
SCH_LINE* GetWireOrBus( const wxPoint& aPosition );
/**
* Return a line item located at \a aPosition.

View File

@ -245,23 +245,17 @@ bool SCH_SHEET::HasUndefinedPins()
for( const SCH_SHEET_PIN& pin : m_pins )
{
/* Search the schematic for a hierarchical label corresponding to this sheet label. */
EDA_ITEM* DrawStruct = m_screen->GetDrawItems();
const SCH_HIERLABEL* HLabel = NULL;
for( ; DrawStruct != NULL; DrawStruct = DrawStruct->Next() )
const SCH_HIERLABEL* HLabel = nullptr;
for( auto aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
{
if( DrawStruct->Type() != SCH_HIER_LABEL_T )
continue;
HLabel = static_cast<SCH_HIERLABEL*>( DrawStruct );
if( pin.GetText().CmpNoCase( HLabel->GetText() ) == 0 )
break; // Found!
HLabel = NULL;
if( !pin.GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
{
HLabel = static_cast<SCH_HIERLABEL*>( aItem );
break;
}
}
if( HLabel == NULL ) // Corresponding hierarchical label not found.
if( HLabel == nullptr ) // Corresponding hierarchical label not found.
return true;
}
@ -355,20 +349,15 @@ void SCH_SHEET::CleanupSheet()
while( i != m_pins.end() )
{
/* Search the schematic for a hierarchical label corresponding to this sheet label. */
EDA_ITEM* DrawStruct = m_screen->GetDrawItems();
const SCH_HIERLABEL* HLabel = NULL;
for( ; DrawStruct != NULL; DrawStruct = DrawStruct->Next() )
for( auto aItem : m_screen->Items().OfType( SCH_HIER_LABEL_T ) )
{
if( DrawStruct->Type() != SCH_HIER_LABEL_T )
continue;
HLabel = static_cast<SCH_HIERLABEL*>( DrawStruct );
if( i->GetText().CmpNoCase( HLabel->GetText() ) == 0 )
break; // Found!
HLabel = NULL;
if( !i->GetText().CmpNoCase( static_cast<SCH_HIERLABEL*>( aItem )->GetText() ) )
{
HLabel = static_cast<SCH_HIERLABEL*>( aItem );
break;
}
}
if( HLabel == NULL ) // Hlabel not found: delete sheet label.
@ -527,30 +516,22 @@ wxPoint SCH_SHEET::GetRotationCenter() const
}
int SCH_SHEET::ComponentCount()
int SCH_SHEET::ComponentCount() const
{
int n = 0;
if( m_screen )
{
EDA_ITEM* bs;
for( bs = m_screen->GetDrawItems(); bs != NULL; bs = bs->Next() )
for( auto aItem : m_screen->Items().OfType( SCH_COMPONENT_T ) )
{
if( bs->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* Cmp = (SCH_COMPONENT*) bs;
SCH_COMPONENT* Cmp = (SCH_COMPONENT*) aItem;
if( Cmp->GetField( VALUE )->GetText().GetChar( 0 ) != '#' )
n++;
}
if( bs->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) bs;
n += sheet->ComponentCount();
}
if( Cmp->GetField( VALUE )->GetText().GetChar( 0 ) != '#' )
n++;
}
for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
n += static_cast<const SCH_SHEET*>( aItem )->ComponentCount();
}
return n;
@ -559,47 +540,33 @@ int SCH_SHEET::ComponentCount()
bool SCH_SHEET::SearchHierarchy( const wxString& aFilename, SCH_SCREEN** aScreen )
{
SCH_SHEET* sheet = nullptr;
SCH_SCREEN* screen = nullptr;
if( m_screen )
{
// Only check the root sheet once and don't recurse.
if( !GetParent() )
{
sheet = this;
screen = m_screen;
if( m_screen && m_screen->GetFileName().Cmp( aFilename ) == 0 )
{
*aScreen = m_screen;
return true;
}
}
for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
{
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( aItem );
SCH_SCREEN* screen = sheet->m_screen;
// Must use the screen's path (which is always absolute) rather than the
// sheet's (which could be relative).
if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
{
*aScreen = screen;
return true;
}
}
EDA_ITEM* item = m_screen->GetDrawItems();
while( item )
{
if( item->Type() == SCH_SHEET_T )
{
// Must use the screen's path (which is always absolute) rather than the
// sheet's (which could be relative).
sheet = static_cast< SCH_SHEET* >( item );
screen = sheet->m_screen;
if( screen && screen->GetFileName().Cmp( aFilename ) == 0 )
{
*aScreen = screen;
return true;
}
else if( sheet->SearchHierarchy( aFilename, aScreen ) )
{
return true;
}
}
item = item->Next();
if( sheet->SearchHierarchy( aFilename, aScreen ) )
return true;
}
}
@ -616,19 +583,14 @@ bool SCH_SHEET::LocatePathOfScreen( SCH_SCREEN* aScreen, SCH_SHEET_PATH* aList )
if( m_screen == aScreen )
return true;
EDA_ITEM* strct = m_screen->GetDrawItems();
while( strct )
for( auto item : m_screen->Items().OfType( SCH_SHEET_T ) )
{
if( strct->Type() == SCH_SHEET_T )
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
if( sheet->LocatePathOfScreen( aScreen, aList ) )
{
SCH_SHEET* ss = (SCH_SHEET*) strct;
if( ss->LocatePathOfScreen( aScreen, aList ) )
return true;
return true;
}
strct = strct->Next();
}
aList->pop_back();
@ -644,17 +606,10 @@ int SCH_SHEET::CountSheets()
if( m_screen )
{
EDA_ITEM* strct = m_screen->GetDrawItems();
for( ; strct; strct = strct->Next() )
{
if( strct->Type() == SCH_SHEET_T )
{
SCH_SHEET* subsheet = (SCH_SHEET*) strct;
count += subsheet->CountSheets();
}
}
for( auto aItem : m_screen->Items().OfType( SCH_SHEET_T ) )
count += static_cast<SCH_SHEET*>( aItem )->CountSheets();
}
return count;
}

View File

@ -426,7 +426,7 @@ public:
*
* @return the component count.
*/
int ComponentCount();
int ComponentCount() const;
/**
* Search the existing hierarchy for an instance of screen loaded from \a aFileName.

View File

@ -30,7 +30,6 @@
#include <fctsys.h>
#include <dlist.h>
#include <sch_screen.h>
#include <sch_item.h>
@ -97,9 +96,20 @@ int SCH_SHEET_PATH::Cmp( const SCH_SHEET_PATH& aSheetPathToTest ) const
SCH_SHEET* SCH_SHEET_PATH::Last() const
{
if( !empty() )
return at( size() - 1 );
return m_sheets.back();
return NULL;
return nullptr;
}
SCH_SCREEN* SCH_SHEET_PATH::LastScreen()
{
SCH_SHEET* lastSheet = Last();
if( lastSheet )
return lastSheet->GetScreen();
return nullptr;
}
@ -110,41 +120,7 @@ SCH_SCREEN* SCH_SHEET_PATH::LastScreen() const
if( lastSheet )
return lastSheet->GetScreen();
return NULL;
}
SCH_ITEM* SCH_SHEET_PATH::LastDrawList() const
{
SCH_SHEET* lastSheet = Last();
if( lastSheet && lastSheet->GetScreen() )
return lastSheet->GetScreen()->GetDrawItems();
return NULL;
}
SCH_ITEM* SCH_SHEET_PATH::FirstDrawList() const
{
SCH_ITEM* item = NULL;
if( !empty() && at( 0 )->GetScreen() )
item = at( 0 )->GetScreen()->GetDrawItems();
/* @fixme - These lists really should be one of the boost pointer containers. This
* is a brain dead hack to allow reverse iteration of EDA_ITEM linked
* list.
*/
SCH_ITEM* lastItem = NULL;
while( item )
{
lastItem = item;
item = item->Next();
}
return lastItem;
return nullptr;
}
@ -195,18 +171,11 @@ wxString SCH_SHEET_PATH::PathHumanReadable() const
void SCH_SHEET_PATH::UpdateAllScreenReferences()
{
EDA_ITEM* t = LastDrawList();
while( t )
for( auto item : LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( t->Type() == SCH_COMPONENT_T )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) t;
component->GetField( REFERENCE )->SetText( component->GetRef( this ) );
component->UpdateUnit( component->GetUnitSelection( this ) );
}
t = t->Next();
auto component = static_cast<SCH_COMPONENT*>( item );
component->GetField( REFERENCE )->SetText( component->GetRef( this ) );
component->UpdateUnit( component->GetUnitSelection( this ) );
}
}
@ -215,17 +184,14 @@ void SCH_SHEET_PATH::UpdateAllScreenReferences()
void SCH_SHEET_PATH::GetComponents( SCH_REFERENCE_LIST& aReferences, bool aIncludePowerSymbols,
bool aForceIncludeOrphanComponents )
{
for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() )
for( auto item : LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() == SCH_COMPONENT_T )
auto component = static_cast<SCH_COMPONENT*>( item );
// Skip pseudo components, which have a reference starting with #. This mainly
// affects power symbols.
if( aIncludePowerSymbols || component->GetRef( this )[0] != wxT( '#' ) )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
// Skip pseudo components, which have a reference starting with #. This mainly
// affects power symbols.
if( !aIncludePowerSymbols && component->GetRef( this )[0] == wxT( '#' ) )
continue;
LIB_PART* part = component->GetPartRef().get();
if( part || aForceIncludeOrphanComponents )
@ -243,13 +209,9 @@ void SCH_SHEET_PATH::GetComponents( SCH_REFERENCE_LIST& aReferences, bool aInclu
void SCH_SHEET_PATH::GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP& aRefList,
bool aIncludePowerSymbols )
{
for( SCH_ITEM* item = LastDrawList(); item; item = item->Next() )
for( auto item : LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
auto component = static_cast<SCH_COMPONENT*>( item );
// Skip pseudo components, which have a reference starting with #. This mainly
// affects power symbols.
@ -274,72 +236,6 @@ void SCH_SHEET_PATH::GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP& aRefL
}
SCH_ITEM* SCH_SHEET_PATH::FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem, bool aWrap ) const
{
bool hasWrapped = false;
bool firstItemFound = false;
SCH_ITEM* drawItem = LastDrawList();
while( drawItem )
{
if( drawItem->Type() == aType )
{
if( !aLastItem || firstItemFound )
{
return drawItem;
}
else if( !firstItemFound && drawItem == aLastItem )
{
firstItemFound = true;
}
}
drawItem = drawItem->Next();
if( !drawItem && aLastItem && aWrap && !hasWrapped )
{
hasWrapped = true;
drawItem = LastDrawList();
}
}
return NULL;
}
SCH_ITEM* SCH_SHEET_PATH::FindPreviousItem( KICAD_T aType, SCH_ITEM* aLastItem, bool aWrap ) const
{
bool hasWrapped = false;
bool firstItemFound = false;
SCH_ITEM* drawItem = FirstDrawList();
while( drawItem )
{
if( drawItem->Type() == aType )
{
if( aLastItem == NULL || firstItemFound )
{
return drawItem;
}
else if( !firstItemFound && drawItem == aLastItem )
{
firstItemFound = true;
}
}
drawItem = drawItem->Back();
if( drawItem == NULL && aLastItem && aWrap && !hasWrapped )
{
hasWrapped = true;
drawItem = FirstDrawList();
}
}
return NULL;
}
bool SCH_SHEET_PATH::SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
bool aSetVisible )
{
@ -490,20 +386,10 @@ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet )
m_currentSheetPath.SetPageNumber( size() + 1 );
push_back( m_currentSheetPath );
if( aSheet->GetScreen() )
if( m_currentSheetPath.LastScreen() )
{
EDA_ITEM* item = m_currentSheetPath.LastDrawList();
while( item )
{
if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
BuildSheetList( sheet );
}
item = item->Next();
}
for( auto item : m_currentSheetPath.LastScreen()->Items().OfType( SCH_SHEET_T ) )
BuildSheetList( static_cast<SCH_SHEET*>( item ) );
}
m_currentSheetPath.pop_back();
@ -545,12 +431,9 @@ void SCH_SHEET_LIST::AnnotatePowerSymbols()
{
SCH_SHEET_PATH& spath = *it;
for( EDA_ITEM* item = spath.LastDrawList(); item; item = item->Next() )
for( auto item : spath.LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
SCH_COMPONENT* component = (SCH_COMPONENT*) item;
auto component = static_cast<SCH_COMPONENT*>( item );
LIB_PART* part = component->GetPartRef().get();
if( !part || !part->IsPower() )
@ -639,97 +522,6 @@ void SCH_SHEET_LIST::GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP &aRefL
}
SCH_ITEM* SCH_SHEET_LIST::FindNextItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFoundIn,
SCH_ITEM* aLastItem, bool aWrap )
{
bool hasWrapped = false;
bool firstItemFound = false;
SCH_ITEM* drawItem = NULL;
SCH_SHEET_PATHS_ITER it = begin();
while( it != end() )
{
drawItem = (*it).LastDrawList();
while( drawItem )
{
if( drawItem->Type() == aType )
{
if( aLastItem == NULL || firstItemFound )
{
if( aSheetFoundIn )
*aSheetFoundIn = &(*it);
return drawItem;
}
else if( !firstItemFound && drawItem == aLastItem )
{
firstItemFound = true;
}
}
drawItem = drawItem->Next();
}
++it;
if( it == end() && aLastItem && aWrap && !hasWrapped )
{
hasWrapped = true;
it = begin();
}
}
return NULL;
}
SCH_ITEM* SCH_SHEET_LIST::FindPreviousItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFoundIn,
SCH_ITEM* aLastItem, bool aWrap )
{
bool hasWrapped = false;
bool firstItemFound = false;
SCH_ITEM* drawItem = NULL;
SCH_SHEET_PATHS_RITER it = rbegin();
while( it != rend() )
{
drawItem = (*it).FirstDrawList();
while( drawItem )
{
if( drawItem->Type() == aType )
{
if( aLastItem == NULL || firstItemFound )
{
if( aSheetFoundIn )
*aSheetFoundIn = &(*it);
return drawItem;
}
else if( !firstItemFound && drawItem == aLastItem )
{
firstItemFound = true;
}
}
drawItem = drawItem->Back();
}
++it;
if( it == rend() && aLastItem && aWrap && !hasWrapped )
{
hasWrapped = true;
it = rbegin();
}
}
return NULL;
}
bool SCH_SHEET_LIST::SetComponentFootprint( const wxString& aReference,
const wxString& aFootPrint, bool aSetVisible )
{

View File

@ -195,23 +195,12 @@ public:
* Function LastScreen
* @return the SCH_SCREEN relative to the last sheet in list
*/
SCH_SCREEN* LastScreen();
///> @copydoc SCH_SHEET_PATH::LastScreen()
SCH_SCREEN* LastScreen() const;
/**
* Function LastDrawList
* @return a pointer to the first schematic item handled by the
* SCH_SCREEN relative to the last sheet in list
*/
SCH_ITEM* LastDrawList() const;
/**
* Get the last schematic item relative to the first sheet in the list.
*
* @return Last schematic item relative to the first sheet in the list if list
* is not empty. Otherwise NULL.
*/
SCH_ITEM* FirstDrawList() const;
/**
* Function Path
* the path uses the time stamps which do not changes even when editing
@ -284,30 +273,6 @@ public:
bool SetComponentFootprint( const wxString& aReference, const wxString& aFootPrint,
bool aSetVisible );
/**
* Find the next schematic item in this sheet object.
*
* @param aType - The type of schematic item object to search for.
* @param aLastItem - Start search from aLastItem. If no aLastItem, search from
* the beginning of the list.
* @param aWrap - Wrap around the end of the list to find the next item if aLastItem
* is defined.
* @return - The next schematic item if found. Otherwise, NULL is returned.
*/
SCH_ITEM* FindNextItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
/**
* Find the previous schematic item in this sheet path object.
*
* @param aType - The type of schematic item object to search for.
* @param aLastItem - Start search from aLastItem. If no aLastItem, search from
* the end of the list.
* @param aWrap - Wrap around the beginning of the list to find the next item if aLastItem
* is defined.
* @return - The previous schematic item if found. Otherwise, NULL is returned.
*/
SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_ITEM* aLastItem = NULL, bool aWrap = false ) const;
/**
* Function TestForRecursion
*
@ -453,34 +418,6 @@ public:
void GetMultiUnitComponents( SCH_MULTI_UNIT_REFERENCE_MAP &aRefList,
bool aIncludePowerSymbols = true );
/**
* Function FindNextItem
* searches the entire schematic for the next schematic object.
*
* @param aType - The type of schematic item to find.
* @param aSheetFound - The sheet the item was found in. NULL if the next item
* is not found.
* @param aLastItem - Find next item after aLastItem if not NULL.
* @param aWrap - Wrap past around the end of the list of sheets.
* @return If found, Returns the next schematic item. Otherwise, returns NULL.
*/
SCH_ITEM* FindNextItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFound = NULL,
SCH_ITEM* aLastItem = NULL, bool aWrap = true );
/**
* Function FindPreviousItem
* searches the entire schematic for the previous schematic item.
*
* @param aType - The type of schematic item to find.
* @param aSheetFound - The sheet the item was found in. NULL if the previous item
* is not found.
* @param aLastItem - Find the previous item before aLastItem if not NULL.
* @param aWrap - Wrap past around the beginning of the list of sheets.
* @return If found, the previous schematic item. Otherwise, NULL.
*/
SCH_ITEM* FindPreviousItem( KICAD_T aType, SCH_SHEET_PATH** aSheetFound = NULL,
SCH_ITEM* aLastItem = NULL, bool aWrap = true );
/**
* Function SetFootprintField
* searches all the sheets for a component with \a aReference and set the footprint

View File

@ -659,7 +659,7 @@ EDA_ITEM* SCH_LABEL::Clone() const
}
bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] )
bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
{
static KICAD_T wireTypes[] = { SCH_LINE_LOCATE_WIRE_T, EOT };
static KICAD_T busTypes[] = { SCH_LINE_LOCATE_BUS_T, EOT };

View File

@ -383,7 +383,7 @@ public:
return wxT( "SCH_LABEL" );
}
bool IsType( const KICAD_T aScanTypes[] ) override ;
bool IsType( const KICAD_T aScanTypes[] ) const override;
const EDA_RECT GetBoundingBox() const override;

View File

@ -92,7 +92,7 @@ void SCH_VIEW::ResizeSheetWorkingArea( SCH_SCREEN* aScreen )
void SCH_VIEW::DisplaySheet( SCH_SCREEN *aScreen )
{
for( auto item = aScreen->GetDrawItems(); item; item = item->Next() )
for( auto item : aScreen->Items() )
Add( item );
m_worksheet.reset( new KIGFX::WS_PROXY_VIEW_ITEM( static_cast< int >( IU_PER_MILS ),

View File

@ -24,13 +24,13 @@
#ifndef SCH_VIEW_H_
#define SCH_VIEW_H_
#include <memory>
#include <view/view.h>
#include <math/box2.h>
#include <view/wx_view_controls.h>
#include <ws_proxy_view_item.h>
#include <base_struct.h>
#include <layers_id_colors_and_visibility.h>
#include <math/vector2d.h>
#include <view/view.h>
#include <memory>
#include <vector>
class SCH_SHEET;
class SCH_SCREEN;

View File

@ -76,7 +76,7 @@
*
* Redo command
* - delete item(s) old command:
* => deleted items are moved in GetDrawItems() list, and in
* => deleted items are moved into m_tree
*
* - change item(s) command
* => the copy of item(s) is moved in Undo list

View File

@ -104,7 +104,6 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
{
wxASSERT( aSheet && aHierarchy );
int i;
wxString msg;
wxString topLevelSheetPath;
wxFileName tmp;
@ -448,14 +447,13 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
// Check for duplicate sheet names in the current page.
wxArrayString duplicateSheetNames;
EE_TYPE_COLLECTOR sheets;
sheets.Collect( currentScreen->GetDrawItems(), EE_COLLECTOR::SheetsOnly );
for( i = 0; i < sheets.GetCount(); ++i )
for( auto item : currentScreen->Items().OfType( SCH_SHEET_T ) )
{
if( newSheet->GetScreen()->GetSheet( ( ( SCH_SHEET* ) sheets[i] )->GetName() ) )
duplicateSheetNames.Add( ( ( SCH_SHEET* ) sheets[i] )->GetName() );
auto sheet = static_cast<SCH_SHEET*>( item );
if( newSheet->GetScreen()->GetSheet( sheet->GetName() ) )
duplicateSheetNames.Add( sheet->GetName() );
}
if( !duplicateSheetNames.IsEmpty() )
@ -484,15 +482,11 @@ bool SCH_EDIT_FRAME::LoadSheetFromFile( SCH_SHEET* aSheet, SCH_SHEET_PATH* aHier
}
// Set all sheets loaded into the correct sheet file paths.
EE_TYPE_COLLECTOR newTopLevelSheets;
newTopLevelSheets.Collect( newSheet->GetScreen()->GetDrawItems(), EE_COLLECTOR::SheetsOnly );
for( i = 0; i < newTopLevelSheets.GetCount(); ++i )
for( auto aItem : currentScreen->Items().OfType( SCH_SHEET_T ) )
{
SCH_SHEET* tmpSheet = dynamic_cast< SCH_SHEET* >( newTopLevelSheets[i] );
wxCHECK2( tmpSheet != nullptr, continue );
tmpSheet->SetFileName( topLevelSheetPath + tmpSheet->GetFileName() );
auto sheet = static_cast<SCH_SHEET*>( aItem );
sheet->SetFileName( topLevelSheetPath + sheet->GetFileName() );
}
if( libTableChanged )
@ -821,14 +815,11 @@ SCH_SHEET_PIN* SCH_EDIT_FRAME::CreateSheetPin( SCH_SHEET* aSheet, SCH_HIERLABEL*
SCH_HIERLABEL* SCH_EDIT_FRAME::ImportHierLabel( SCH_SHEET* aSheet )
{
if( !aSheet->GetScreen() )
return NULL;
return nullptr;
for( EDA_ITEM* item = aSheet->GetScreen()->GetDrawItems(); item != NULL; item = item->Next() )
for( auto item : aSheet->GetScreen()->Items().OfType( SCH_HIER_LABEL_T ) )
{
if( item->Type() != SCH_HIER_LABEL_T )
continue;
SCH_HIERLABEL* label = (SCH_HIERLABEL*) item;
auto label = static_cast<SCH_HIERLABEL*>( item );
/* A global label has been found: check if there a corresponding sheet label. */
if( !aSheet->HasPin( label->GetText() ) )

View File

@ -153,15 +153,15 @@ public:
SCH_LINE* connectedStart = nullptr;
SCH_LINE* connectedEnd = nullptr;
for( SCH_ITEM* test = frame->GetScreen()->GetDrawItems(); test; test = test->Next() )
for( auto test : frame->GetScreen()->Items().OfType( SCH_LINE_T ) )
{
if( test->Type() != SCH_LINE_T || test->GetLayer() != LAYER_NOTES )
if( test->GetLayer() != LAYER_NOTES )
continue;
if( test == aItem )
continue;
SCH_LINE* testLine = (SCH_LINE*) test;
auto testLine = static_cast<SCH_LINE*>( test );
testLine->ClearFlags( STARTPOINT | ENDPOINT );
if( testLine->GetStartPoint() == line->GetStartPoint() )
@ -186,6 +186,7 @@ public:
}
}
points->AddPoint( line->GetStartPoint(), connectedStart );
points->AddPoint( line->GetEndPoint(), connectedEnd );
break;

View File

@ -419,20 +419,21 @@ EDA_ITEM* EE_SELECTION_TOOL::SelectPoint( const VECTOR2I& aWhere, const KICAD_T*
bool* aSelectionCancelledFlag, bool aCheckLocked,
bool aAdd, bool aSubtract, bool aExclusiveOr )
{
EDA_ITEM* start;
EE_COLLECTOR collector;
if( m_isLibEdit )
start = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
else
start = m_frame->GetScreen()->GetDrawItems();
// Empty schematics have no draw items
if( !start )
return nullptr;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
collector.Collect( start, aFilterList, (wxPoint) aWhere, m_unit, m_convert );
if( m_isLibEdit )
{
auto part = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
if( !part )
return nullptr;
collector.Collect( part->GetDrawItems(), aFilterList, (wxPoint) aWhere, m_unit, m_convert );
}
else
collector.Collect( m_frame->GetScreen(), aFilterList, (wxPoint) aWhere, m_unit, m_convert );
// Post-process collected items
for( int i = collector.GetCount() - 1; i >= 0; --i )
@ -804,17 +805,15 @@ static KICAD_T nodeTypes[] =
EDA_ITEM* EE_SELECTION_TOOL::GetNode( VECTOR2I aPosition )
{
if( m_frame->GetScreen()->GetDrawItems() == nullptr ) // Empty schematics
return nullptr;
EE_COLLECTOR collector;
//TODO(snh): Reimplement after exposing KNN interface
int thresholdMax = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
for( int threshold : { 0, thresholdMax/2, thresholdMax } )
{
collector.m_Threshold = threshold;
collector.Collect( m_frame->GetScreen()->GetDrawItems(), nodeTypes, (wxPoint) aPosition );
collector.Collect( m_frame->GetScreen(), nodeTypes, (wxPoint) aPosition );
if( collector.GetCount() > 0 )
break;
@ -847,13 +846,10 @@ int EE_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent )
EDA_ITEMS items;
m_frame->GetScreen()->ClearDrawingState();
m_frame->GetScreen()->MarkConnections( line );
auto conns = m_frame->GetScreen()->MarkConnections( line );
for( EDA_ITEM* item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
{
if( item->HasFlag( CANDIDATE ) )
select( item );
}
for( auto item : conns )
select( item );
if( m_selection.GetSize() > 1 )
m_toolMgr->ProcessEvent( EVENTS::SelectedEvent );
@ -972,26 +968,38 @@ void EE_SELECTION_TOOL::RebuildSelection()
{
m_selection.Clear();
EDA_ITEM* start = nullptr;
if( m_isLibEdit )
start = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
else
start = m_frame->GetScreen()->GetDrawItems();
INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
{
// If the field and component are selected, only use the component
if( item->IsSelected() && !( item->Type() == SCH_FIELD_T && item->GetParent()
&& item->GetParent()->IsSelected() ) )
EDA_ITEM* start = nullptr;
start = static_cast<LIB_EDIT_FRAME*>( m_frame )->GetCurPart();
INSPECTOR_FUNC inspector = [&]( EDA_ITEM* item, void* testData ) {
// If the field and component are selected, only use the component
if( item->IsSelected()
&& !( item->Type() == SCH_FIELD_T && item->GetParent()
&& item->GetParent()->IsSelected() ) )
{
select( item );
}
return SEARCH_RESULT::CONTINUE;
};
EDA_ITEM::IterateForward( start, inspector, nullptr, EE_COLLECTOR::AllItems );
}
else
{
for( auto item : m_frame->GetScreen()->Items() )
{
select( item );
// If the field and component are selected, only use the component
if( item->IsSelected()
&& !( item->Type() == SCH_FIELD_T && item->GetParent()
&& item->GetParent()->IsSelected() ) )
{
select( item );
}
}
return SEARCH_RESULT::CONTINUE;
};
EDA_ITEM::IterateForward( start, inspector, nullptr, EE_COLLECTOR::AllItems );
}
updateReferencePoint();

View File

@ -317,8 +317,8 @@ int LIB_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
EE_COLLECTOR collector;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
collector.Collect( m_frame->GetCurPart(), nonFields, (wxPoint) aPos,
m_frame->GetUnit(), m_frame->GetConvert() );
collector.Collect( m_frame->GetScreen(), nonFields, (wxPoint) aPos, m_frame->GetUnit(),
m_frame->GetConvert() );
// Remove unselectable items
for( int i = collector.GetCount() - 1; i >= 0; --i )

View File

@ -1042,7 +1042,7 @@ int SCH_EDIT_TOOL::DeleteItemCursor( const TOOL_EVENT& aEvent )
{
EE_COLLECTOR collector;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
collector.Collect( m_frame->GetScreen()->GetDrawItems(), deletableItems, (wxPoint) aPos );
collector.Collect( m_frame->GetScreen(), deletableItems, (wxPoint) aPos );
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selectionTool->GuessSelectionCandidates( collector, aPos );
@ -1158,6 +1158,7 @@ int SCH_EDIT_TOOL::AutoplaceFields( const TOOL_EVENT& aEvent )
component->AutoplaceFields( m_frame->GetScreen(), /* aManual */ true );
m_frame->GetScreen()->Update( component );
updateView( component );
m_frame->OnModify();
@ -1169,11 +1170,9 @@ int SCH_EDIT_TOOL::UpdateFields( const TOOL_EVENT& aEvent )
{
std::list<SCH_COMPONENT*> components;
for( SCH_ITEM* item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() == SCH_COMPONENT_T )
components.push_back( static_cast<SCH_COMPONENT*>( item ) );
}
for( auto item : m_frame->GetScreen()->Items().OfType( SCH_COMPONENT_T ) )
components.push_back( static_cast<SCH_COMPONENT*>( item ) );
if( InvokeDialogUpdateFields( m_frame, components, true ) == wxID_OK )
m_frame->GetCanvas()->Refresh();
@ -1360,6 +1359,7 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
wxFAIL_MSG( wxString( "Cannot edit schematic item type " ) + item->GetClass() );
}
m_frame->GetScreen()->Update( item );
updateView( item );
if( selection.IsHover() )
@ -1388,6 +1388,7 @@ int SCH_EDIT_TOOL::ChangeShape( const TOOL_EVENT& aEvent )
entry->SetBusEntryShape( shape );
m_frame->TestDanglingEnds();
m_frame->GetScreen()->Update( entry );
updateView( entry );
m_frame->OnModify( );
}
@ -1457,6 +1458,7 @@ int SCH_EDIT_TOOL::CleanupSheetPins( const TOOL_EVENT& aEvent )
sheet->CleanupSheet();
m_frame->GetScreen()->Update( sheet );
updateView( sheet );
m_frame->OnModify();

View File

@ -147,18 +147,13 @@ int SCH_EDITOR_CONTROL::UpdateFind( const TOOL_EVENT& aEvent )
{
m_selectionTool->ClearSelection();
INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* )
for( auto item : m_frame->GetScreen()->Items() )
{
if( data && item->Matches( *data, nullptr ) )
m_selectionTool->BrightenItem( item );
else if( item->IsBrightened() )
m_selectionTool->UnbrightenItem( item );
return SEARCH_RESULT::CONTINUE;
};
EDA_ITEM* start = m_frame->GetScreen()->GetDrawItems();
EDA_ITEM::IterateForward( start, inspector, nullptr, EE_COLLECTOR::AllItems );
}
}
else if( aEvent.Matches( EVENTS::SelectedItemsModified ) )
{
@ -179,33 +174,23 @@ int SCH_EDITOR_CONTROL::UpdateFind( const TOOL_EVENT& aEvent )
}
EDA_ITEM* nextMatch( SCH_SCREEN* aScreen, EDA_ITEM* after, wxFindReplaceData* data )
SCH_ITEM* SCH_EDITOR_CONTROL::nextMatch(
SCH_SCREEN* aScreen, SCH_ITEM* aAfter, wxFindReplaceData* aData )
{
EDA_ITEM* found = nullptr;
bool past_item = ( aAfter == nullptr );
INSPECTOR_FUNC inspector = [&] ( EDA_ITEM* item, void* testData )
for( auto item : aScreen->Items() )
{
if( after )
{
if( after == item )
after = nullptr;
if( item == aAfter )
past_item = true;
return SEARCH_RESULT::CONTINUE;
}
if( past_item
&& ( ( aData == &g_markersOnly && item->Type() == SCH_MARKER_T )
|| item->Matches( *aData, nullptr ) ) )
return item;
}
if( ( data == &g_markersOnly && item->Type() == SCH_MARKER_T )
|| item->Matches( *data, nullptr ) )
{
found = item;
return SEARCH_RESULT::QUIT;
}
return SEARCH_RESULT::CONTINUE;
};
EDA_ITEM::IterateForward( aScreen->GetDrawItems(), inspector, nullptr, EE_COLLECTOR::AllItems );
return found;
return nullptr;
}
@ -231,8 +216,8 @@ int SCH_EDITOR_CONTROL::FindNext( const TOOL_EVENT& aEvent )
bool searchAllSheets = !( data->GetFlags() & FR_CURRENT_SHEET_ONLY );
EE_SELECTION& selection = m_selectionTool->GetSelection();
SCH_SCREEN* afterScreen = m_frame->GetScreen();
EDA_ITEM* afterItem = selection.Front();
EDA_ITEM* item = nullptr;
SCH_ITEM* afterItem = dynamic_cast<SCH_ITEM*>( selection.Front() );
SCH_ITEM* item = nullptr;
if( wrapAroundTimer.IsRunning() )
{
@ -341,11 +326,12 @@ int SCH_EDITOR_CONTROL::ReplaceAll( const TOOL_EVENT& aEvent )
for( SCH_SCREEN* screen = screens.GetFirst(); screen; screen = screens.GetNext() )
{
for( EDA_ITEM* item = nextMatch( screen, nullptr, data ); item;
item = nextMatch( screen, item, data ) )
{
item->Replace( *data, schematic.FindSheetForScreen( screen ) );
}
//TODO(snh): Fix ReplaceAll
// screen->ForEachItem() for( EDA_ITEM* item = nextMatch( screen, nullptr, data ); item;
// item = nextMatch( screen, item, data ) )
// {
// item->Replace( *data, schematic.FindSheetForScreen( screen ) );
// }
}
return 0;
@ -501,7 +487,7 @@ int SCH_EDITOR_CONTROL::SimProbe( const TOOL_EVENT& aEvent )
{
EE_COLLECTOR collector;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
collector.Collect( m_frame->GetScreen()->GetDrawItems(), wiresAndPins, (wxPoint) aPos );
collector.Collect( m_frame->GetScreen(), wiresAndPins, (wxPoint) aPos );
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selectionTool->GuessSelectionCandidates( collector, aPos );
@ -606,7 +592,7 @@ int SCH_EDITOR_CONTROL::SimTune( const TOOL_EVENT& aEvent )
{
EE_COLLECTOR collector;
collector.m_Threshold = KiROUND( getView()->ToWorld( HITTEST_THRESHOLD_PIXELS ) );
collector.Collect( m_frame->GetScreen()->GetDrawItems(), fieldsAndComponents, (wxPoint) aPos );
collector.Collect( m_frame->GetScreen(), fieldsAndComponents, (wxPoint) aPos );
EE_SELECTION_TOOL* selectionTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
selectionTool->GuessSelectionCandidates( collector, aPos );
@ -717,10 +703,10 @@ int SCH_EDITOR_CONTROL::UpdateNetHighlighting( const TOOL_EVENT& aEvent )
if( !screen )
return 0;
for( SCH_ITEM* item = screen->GetDrawItems(); item; item = item->Next() )
for( auto item : screen->Items() )
{
SCH_CONNECTION* conn = item->Connection( *g_CurrentSheet );
bool redraw = item->IsBrightened();
SCH_CONNECTION* conn = item->Connection( *g_CurrentSheet );
bool redraw = item->IsBrightened();
if( conn && conn->Name() == selectedNetName )
item->SetBrightened();
@ -960,10 +946,6 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
}
EE_SELECTION_TOOL* selTool = m_toolMgr->GetTool<EE_SELECTION_TOOL>();
DLIST<SCH_ITEM>& dlist = m_frame->GetScreen()->GetDrawList();
SCH_ITEM* lastExisting = dlist.GetLast();
std::string text = m_toolMgr->GetClipboard();
if( text.empty() )
@ -972,14 +954,16 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
STRING_LINE_READER reader( text, "Clipboard" );
SCH_LEGACY_PLUGIN plugin;
SCH_SCREEN paste_screen( &m_frame->GetScreen()->Kiway() );
try
{
plugin.LoadContent( reader, m_frame->GetScreen() );
plugin.LoadContent( reader, &paste_screen );
}
catch( IO_ERROR& e )
{
// If it wasn't content, then paste as text
dlist.Append( new SCH_TEXT( wxPoint( 0, 0 ), text ) );
paste_screen.Append( new SCH_TEXT( wxPoint( 0, 0 ), text ) );
}
bool forceKeepAnnotations = false;
@ -997,13 +981,10 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( forceDropAnnotations )
dropAnnotations = true;
// SCH_LEGACY_PLUGIN added the items to the DLIST, but not to the view or anything
// SCH_LEGACY_PLUGIN added the items to the paste screen, but not to the view or anything
// else. Pull them back out to start with.
//
SCH_ITEM* firstNew = lastExisting ? lastExisting->Next() : dlist.GetFirst();
EDA_ITEMS loadedItems;
SCH_ITEM* next = nullptr;
bool sheetsPasted = false;
SCH_SHEET_LIST hierarchy( g_RootSheet );
wxFileName destFn = g_CurrentSheet->Last()->GetFileName();
@ -1011,27 +992,27 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
if( destFn.IsRelative() )
destFn.MakeAbsolute( m_frame->Prj().GetProjectPath() );
for( SCH_ITEM* item = firstNew; item; item = next )
for( auto item : paste_screen.Items() )
{
next = item->Next();
dlist.Remove( item );
loadedItems.push_back( item );
if( item->Type() == SCH_COMPONENT_T )
{
if( !dropAnnotations && !forceKeepAnnotations )
{
for( SCH_ITEM* temp = dlist.GetFirst(); temp != lastExisting; temp = temp->Next() )
for( auto existingItem : m_frame->GetScreen()->Items() )
{
if( item->GetTimeStamp() == temp->GetTimeStamp() )
if( item->GetTimeStamp() == existingItem->GetTimeStamp() )
{
dropAnnotations = true;
break;
}
}
}
}
else if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
SCH_SHEET* sheet = static_cast<SCH_SHEET*>( item );
wxFileName srcFn = sheet->GetFileName();
if( srcFn.IsRelative() )
@ -1051,6 +1032,9 @@ int SCH_EDITOR_CONTROL::Paste( const TOOL_EVENT& aEvent )
}
}
// Remove the references from our temporary screen to prevent freeing on the DTOR
paste_screen.Clear( false );
// Now we can resolve the components and add everything to the screen, view, etc.
//
SYMBOL_LIB_TABLE* symLibTable = m_frame->Prj().SchSymbolLibTable();

View File

@ -178,9 +178,18 @@ private:
///> Sets up handlers for various events.
void setTransitions() override;
/**
* Advances the search and returns the next matching item after aAfter
* @param aScreen Pointer to the screen used for searching
* @param aAfter Starting match to compare
* @param aData Search data to compare against or NULL to match the first item found
* @return pointer to the next search item found or NULL if nothing found
*/
SCH_ITEM* nextMatch( SCH_SCREEN* aScreen, SCH_ITEM* aAfter, wxFindReplaceData* aData );
private:
bool m_probingPcbToSch; // Recursion guard when cross-probing to PCBNew
EDA_ITEM* m_pickerItem; // Current item for picker highlighting.
bool m_probingPcbToSch; // Recursion guard when cross-probing to PCBNew
EDA_ITEM* m_pickerItem; // Current item for picker highlighting.
// A map of sheet paths --> screens for the clipboard contents. We use these to hook up
// cut/paste operations for unsaved sheet content.

View File

@ -381,16 +381,17 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet )
const SCH_SHEET_PIN* SCH_LINE_WIRE_BUS_TOOL::getSheetPin( const wxPoint& aPosition )
{
for( SCH_ITEM* item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
{
if( item->Type() == SCH_SHEET_T )
{
SCH_SHEET* sheet = (SCH_SHEET*) item;
SCH_SCREEN* screen = m_frame->GetScreen();
for( const SCH_SHEET_PIN& pin : sheet->GetPins() )
for( auto item : screen->Items().Overlapping( SCH_SHEET_T, aPosition ) )
{
auto sheet = static_cast<SCH_SHEET*>( item );
for( const SCH_SHEET_PIN& pin : sheet->GetPins() )
{
if( pin.GetPosition() == aPosition )
{
if( pin.GetPosition() == aPosition )
return &pin;
return &pin;
}
}
}
@ -845,11 +846,8 @@ void SCH_LINE_WIRE_BUS_TOOL::finishSegments()
// Correct and remove segments that need to be merged.
m_frame->SchematicCleanUp();
for( auto item = m_frame->GetScreen()->GetDrawItems(); item; item = item->Next() )
for( auto item : m_frame->GetScreen()->Items().OfType( SCH_COMPONENT_T ) )
{
if( item->Type() != SCH_COMPONENT_T )
continue;
std::vector< wxPoint > pts;
item->GetConnectionPoints( pts );

View File

@ -105,7 +105,6 @@ private:
/**
* Searches for a sheet pin at a location
* TODO(snh): Move this to generalized search on RTree
* @param aPosition grid point to search for existing sheet pin
* @return Pointer to sheet pin or nullptr on failure
*/

View File

@ -187,9 +187,10 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
m_dragAdditions.clear();
internalPoints.clear();
for( SCH_ITEM* it = m_frame->GetScreen()->GetDrawItems(); it; it = it->Next() )
for( auto it : m_frame->GetScreen()->Items() )
{
it->ClearFlags(TEMP_SELECTED );
it->ClearFlags( TEMP_SELECTED );
if( !it->IsSelected() )
it->ClearFlags( STARTPOINT | ENDPOINT );
@ -432,14 +433,17 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
for( EDA_ITEM* item : selection )
item->ClearEditFlags();
m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE );
if( restore_state )
{
m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE );
m_frame->RollbackSchematicFromUndo();
}
else
{
// Moving items changes the RTree box bounds.
for( auto item : selection )
m_frame->GetScreen()->Update( static_cast<SCH_ITEM*>( item ) );
// If we move items away from a junction, we _may_ want to add a junction there
// to denote the state.
for( auto it : internalPoints )
@ -449,6 +453,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
}
m_toolMgr->RunAction( EE_ACTIONS::addNeededJunctions, true, &selection );
m_selectionTool->RemoveItemsFromSel( &m_dragAdditions, QUIET_MODE );
m_frame->SchematicCleanUp();
m_frame->TestDanglingEnds();
@ -471,7 +476,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoint,
EDA_ITEMS& aList )
{
for( SCH_ITEM* test = m_frame->GetScreen()->GetDrawItems(); test; test = test->Next() )
for( auto test : m_frame->GetScreen()->Items() )
{
if( test->IsSelected() || !test->IsConnectable() || !test->CanConnect( aOriginalItem ) )
continue;
@ -483,7 +488,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
case SCH_LINE_T:
{
// Select the connected end of wires/bus connections.
SCH_LINE* testLine = (SCH_LINE*) test;
SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
if( testLine->GetStartPoint() == aPoint )
{

View File

@ -292,7 +292,7 @@ public:
* @param aScanTypes List of item types
* @return true if the item type is contained in the list aScanTypes
*/
virtual bool IsType( const KICAD_T aScanTypes[] )
virtual bool IsType( const KICAD_T aScanTypes[] ) const
{
if( aScanTypes[0] == SCH_LOCATE_ANY_T )
return true;

76
include/core/kicad_algo.h Normal file
View File

@ -0,0 +1,76 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2019 CERN
* Copyright (C) 2019 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef INCLUDE_CORE_KICAD_ALGO_H_
#define INCLUDE_CORE_KICAD_ALGO_H_
namespace alg
{
/**
* @brief Apply a function to every sequential pair of elements of a sequence.
* @param __first An input iterator.
* @param __last An input iterator.
* @param __f A unary function object.
*
* Applies the function object @p __f to each sequential pair of elements in the range
* @p [first,last). @p __f must not modify the order of the sequence.
* If @p __f has a return value it is ignored.
*/
template <typename _InputIterator, typename _Function>
void adjacent_pairs( _InputIterator __first, _InputIterator __last, _Function __f )
{
if( __first != __last )
{
_InputIterator __follow = __first;
++__first;
for( ; __first != __last; ++__first, ++__follow )
__f( *__follow, *__first );
}
}
/**
* @brief Apply a function to every possible pair of elements of a sequence.
* @param __first An input iterator.
* @param __last An input iterator.
* @param __f A unary function object.
*
* Applies the function object @p __f to every possible pair of elements in the range
* @p [first,last). @p __f must not modify the order of the sequence.
* If @p __f has a return value it is ignored.
*/
template <typename _InputIterator, typename _Function>
void for_all_pairs( _InputIterator __first, _InputIterator __last, _Function __f )
{
if( __first != __last )
{
_InputIterator __follow = __first;
++__first;
for( ; __first != __last; ++__first, ++__follow )
for( _InputIterator __it = __first; __it != __last; ++__it )
__f( *__follow, *__it );
}
}
} // namespace alg
#endif /* INCLUDE_CORE_KICAD_ALGO_H_ */

View File

@ -77,13 +77,13 @@ class EDA_ITEM;
*/
enum KICAD_T
{
NOT_USED = -1, ///< the 3d code uses this value
NOT_USED = -1, ///< the 3d code uses this value
EOT = 0, ///< search types array terminator (End Of Types)
EOT = 0, ///< search types array terminator (End Of Types)
TYPE_NOT_INIT = 0,
PCB_T,
SCREEN_T, ///< not really an item, used to identify a screen
SCREEN_T, ///< not really an item, used to identify a screen
// Items in pcb
PCB_MODULE_T, ///< class MODULE, a footprint
@ -122,9 +122,10 @@ enum KICAD_T
SCH_SHEET_T,
SCH_PIN_T,
// Be prudent with these 3 types:
// Be prudent with these types:
// they should be used only to locate a specific field type
// among SCH_FIELD_T items types
// N.B. If you add a type here, be sure to add it below to the BaseType()
SCH_FIELD_LOCATE_REFERENCE_T,
SCH_FIELD_LOCATE_VALUE_T,
SCH_FIELD_LOCATE_FOOTPRINT_T,
@ -135,7 +136,7 @@ enum KICAD_T
SCH_LINE_LOCATE_BUS_T,
SCH_LINE_LOCATE_GRAPHIC_LINE_T,
// Same for picking labes attached to wires and/or busses
// Same for picking labels attached to wires and/or busses
SCH_LABEL_LOCATE_WIRE_T,
SCH_LABEL_LOCATE_BUS_T,
@ -187,8 +188,8 @@ enum KICAD_T
WSG_PAGE_T,
// serialized layout used in undo/redo commands
WS_PROXY_UNDO_ITEM_T, // serialized layout used in undo/redo commands
WS_PROXY_UNDO_ITEM_PLUS_T, // serialized layout plus page and title block settings
WS_PROXY_UNDO_ITEM_T, // serialized layout used in undo/redo commands
WS_PROXY_UNDO_ITEM_PLUS_T, // serialized layout plus page and title block settings
/*
* FOR PROJECT::_ELEMs
@ -203,4 +204,34 @@ enum KICAD_T
MAX_STRUCT_TYPE_ID
};
/**
* Returns the underlying type of the given type. This is useful for finding the
* element type given one of the "non-type" types such as SCH_LINE_LOCATE_WIRE_T
* @param aType Given type to resolve
* @return Base type
*/
constexpr KICAD_T BaseType( const KICAD_T aType )
{
switch( aType )
{
case SCH_FIELD_LOCATE_REFERENCE_T:
case SCH_FIELD_LOCATE_VALUE_T:
case SCH_FIELD_LOCATE_FOOTPRINT_T:
case SCH_FIELD_LOCATE_DATASHEET_T:
return SCH_FIELD_T;
case SCH_LINE_LOCATE_WIRE_T:
case SCH_LINE_LOCATE_BUS_T:
case SCH_LINE_LOCATE_GRAPHIC_LINE_T:
return SCH_LINE_T;
case SCH_LABEL_LOCATE_WIRE_T:
case SCH_LABEL_LOCATE_BUS_T:
return SCH_LABEL_T;
default:
return aType;
}
}
#endif // __KICAD_TYPEINFO_H

View File

@ -47,6 +47,7 @@ add_executable( qa_eeschema
test_eagle_plugin.cpp
test_lib_part.cpp
test_sch_pin.cpp
test_sch_rtree.cpp
test_sch_sheet.cpp
test_sch_sheet_path.cpp

View File

@ -23,6 +23,7 @@
#include <kiface_i.h>
#include <pgm_base.h>
#include <transform.h>
#include <sch_edit_frame.h>
@ -138,4 +139,4 @@ void SetLayerColor( COLOR4D aColor, SCH_LAYER_ID aLayer )
unsigned layer = aLayer;
wxASSERT( layer < arrayDim( s_layerColor ) );
s_layerColor[layer] = aColor;
}
}

View File

@ -0,0 +1,244 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2020 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
* or you may search the http://www.gnu.org website for the version 3 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file
* Test suite for SCH_SHEET
*/
#include <convert_to_biu.h>
#include <sch_junction.h>
#include <sch_no_connect.h>
#include <unit_test_utils/unit_test_utils.h>
// Code under test
#include <sch_rtree.h>
#include "timestamp_test_utils.h"
#include <unit_test_utils/wx_assert.h>
class TEST_SCH_RTREE_FIXTURE
{
public:
TEST_SCH_RTREE_FIXTURE() : m_tree()
{
}
EE_RTREE m_tree;
};
/**
* Declare the test suite
*/
BOOST_FIXTURE_TEST_SUITE( SchRtree, TEST_SCH_RTREE_FIXTURE )
/**
* Check default iterators
*/
BOOST_AUTO_TEST_CASE( Default )
{
BOOST_CHECK_EQUAL( m_tree.empty(), true );
int count = 0;
for( auto item : m_tree )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 0 );
for( int type = 0; type <= MAX_STRUCT_TYPE_ID; type++ )
{
count = 0;
for( auto item : m_tree.OfType( KICAD_T( type ) ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 0 );
}
EDA_RECT bbox;
for( int type = 0; type <= MAX_STRUCT_TYPE_ID; type++ )
{
count = 0;
for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, bbox ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 0 );
}
}
BOOST_AUTO_TEST_CASE( Junctions )
{
for( int i = 0; i < 100; i++ )
{
SCH_JUNCTION* junction =
new SCH_JUNCTION( wxPoint( Mils2iu( 100 ) * i, Mils2iu( 100 ) * i ) );
m_tree.insert( junction );
}
int count = 0;
for( auto item : m_tree.OfType( SCH_JUNCTION_T ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 100 );
count = 0;
for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 0 );
EDA_RECT small_bbox( wxPoint( -1, -1 ), wxSize( Mils2iu( 2 ), Mils2iu( 2 ) ) );
EDA_RECT med_bbox( wxPoint( 0, 0 ), wxSize( Mils2iu( 100 ), Mils2iu( 100 ) ) );
EDA_RECT big_bbox( wxPoint( 0, 0 ), wxSize( Mils2iu( 5000 ), Mils2iu( 5000 ) ) );
count = 0;
for( auto item : m_tree.Overlapping( small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 1 );
count = 0;
for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 1 );
count = 0;
for( auto item : m_tree.Overlapping( SCH_NO_CONNECT_T, small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 0 );
count = 0;
for( auto item : m_tree.Overlapping( med_bbox ) )
{
BOOST_CHECK( med_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 2 );
count = 0;
for( auto item : m_tree.Overlapping( big_bbox ) )
{
BOOST_CHECK( big_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 51 );
}
BOOST_AUTO_TEST_CASE( MixedElements )
{
for( int i = 0; i < 100; i++ )
{
int x_sign = ( i % 2 == 0 ) ? -1 : 1;
int y_sign = ( i % 3 == 0 ) ? -1 : 1;
SCH_JUNCTION* junction = new SCH_JUNCTION(
wxPoint( Mils2iu( 100 ) * i * x_sign, Mils2iu( 100 ) * i * y_sign ) );
m_tree.insert( junction );
SCH_NO_CONNECT* nc = new SCH_NO_CONNECT(
wxPoint( Mils2iu( 150 ) * i * y_sign, Mils2iu( 150 ) * i * x_sign ) );
m_tree.insert( nc );
}
int count = 0;
for( auto item : m_tree.OfType( SCH_JUNCTION_T ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 100 );
count = 0;
for( auto item : m_tree.OfType( SCH_NO_CONNECT_T ) )
{
static_cast<void>( item );
count++;
}
BOOST_CHECK_EQUAL( count, 100 );
EDA_RECT small_bbox( wxPoint( -1, -1 ), wxSize( Mils2iu( 2 ), Mils2iu( 2 ) ) );
count = 0;
for( auto item : m_tree.Overlapping( small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 2 );
count = 0;
for( auto item : m_tree.Overlapping( SCH_JUNCTION_T, small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 1 );
count = 0;
for( auto item : m_tree.Overlapping( SCH_NO_CONNECT_T, small_bbox ) )
{
BOOST_CHECK( small_bbox.Intersects( item->GetBoundingBox() ) );
count++;
}
BOOST_CHECK_EQUAL( count, 1 );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -90,8 +90,6 @@ BOOST_AUTO_TEST_CASE( Empty )
// These accessors return nullptr when empty (i.e. they don't crash)
BOOST_CHECK_EQUAL( m_empty_path.Last(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.LastScreen(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.LastDrawList(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.FirstDrawList(), nullptr );
BOOST_CHECK_EQUAL( m_empty_path.Path(), "/" );
BOOST_CHECK_EQUAL( m_empty_path.PathHumanReadable(), "/" );
@ -113,8 +111,6 @@ BOOST_AUTO_TEST_CASE( NonEmpty )
BOOST_CHECK_EQUAL( m_linear.Last(), &m_sheets[2] );
BOOST_CHECK_EQUAL( m_linear.LastScreen(), nullptr );
BOOST_CHECK_EQUAL( m_linear.LastDrawList(), nullptr );
BOOST_CHECK_EQUAL( m_linear.FirstDrawList(), nullptr );
// don't know what the timestamps will be, but we know the format: /<8 chars>/<8 chars>/
BOOST_CHECK_PREDICATE(
@ -134,4 +130,4 @@ BOOST_AUTO_TEST_CASE( Compare )
BOOST_CHECK( m_empty_path != m_linear );
}
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()

View File

@ -14,6 +14,7 @@
// * 1995 Sphere volume fix for degeneracy problem submitted by Paul Brook
// * 2004 Templated C++ port by Greg Douglas
// * 2013 CERN (www.cern.ch)
// * 2020 KiCad Developers - Add std::iterator support for searching
//
//LICENSE:
//
@ -31,9 +32,15 @@
#include <cstdlib>
#include <algorithm>
#include <array>
#include <functional>
#include <iterator>
#ifdef DEBUG
#define ASSERT assert // RTree uses ASSERT( condition )
#else
#define ASSERT( _x )
#endif
//
// RTree.h
@ -78,7 +85,14 @@ class RTree
protected:
struct Node; // Fwd decl. Used by other internal structs and iterator
public:
/// Minimal bounding rectangle (n-dimensional)
struct Rect
{
ELEMTYPE m_min[NUMDIMS]; ///< Min dimensions of bounding box
ELEMTYPE m_max[NUMDIMS]; ///< Max dimensions of bounding box
};
// These constant must be declared after Branch and before Node struct
// Stuck up here for MSVC 6 compiler. NSVC .NET 2003 is much happier.
@ -127,6 +141,15 @@ public:
const ELEMTYPE a_max[NUMDIMS],
std::function<bool (const DATATYPE&)> a_callback ) const;
/// Find all within search rectangle
/// \param a_min Min of search bounding rect
/// \param a_max Max of search bounding rect
/// \param a_callback Callback function to return result. Callback should return 'true' to continue searching
/// \param aFinished This is set to true if the search completed and false if it was interupted
/// \return Returns the number of entries found
int Search( const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS],
std::function<bool( const DATATYPE& )> a_callback, bool& aFinished ) const;
template <class VISITOR>
int Search( const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS], VISITOR& a_visitor )
{
@ -197,29 +220,52 @@ public:
ELEMTYPE a_squareDistanceCallback( const ELEMTYPE a_point[NUMDIMS], DATATYPE a_data ),
ELEMTYPE* a_squareDistance );
public:
/// Iterator is not remove safe.
class Iterator
{
private:
enum { MAX_STACK = 32 }; // Max stack size. Allows almost n^32 where n is number of branches in node
enum
{
MAX_STACK = 32
}; // Max stack size. Allows almost n^32 where n is number of branches in node
struct StackElement
{
Node* m_node;
int m_branchIndex;
Node* m_node;
int m_branchIndex;
};
public:
typedef std::forward_iterator_tag iterator_category;
typedef DATATYPE value_type;
typedef ptrdiff_t difference_type;
typedef DATATYPE* pointer;
typedef DATATYPE& reference;
Iterator() { Init(); }
public:
Iterator() : m_stack( {} ), m_tos( 0 )
{
for( int i = 0; i < NUMDIMS; ++i )
{
m_rect.m_min[i] = std::numeric_limits<ELEMTYPE>::min();
m_rect.m_max[i] = std::numeric_limits<ELEMTYPE>::max();
}
}
~Iterator() { }
Iterator( Rect& aRect ) : m_stack( {} ), m_tos( 0 ), m_rect( aRect )
{
}
/// Is iterator invalid
bool IsNull() { return m_tos <= 0; }
~Iterator()
{
}
/// Is iterator pointing to valid data
bool IsNotNull() { return m_tos > 0; }
bool IsNotNull()
{
return m_tos > 0;
}
/// Access the current data element. Caller must be sure iterator is not NULL first.
DATATYPE& operator*()
@ -237,70 +283,91 @@ public:
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
}
/// Find the next data element
bool operator++() { return FindNextData(); }
/// Get the bounds for this node
void GetBounds( ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS] )
DATATYPE* operator->()
{
ASSERT( IsNotNull() );
StackElement& curTos = m_stack[m_tos - 1];
Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
StackElement& curTos = m_stack[m_tos - 1];
return &( curTos.m_node->m_branch[curTos.m_branchIndex].m_data );
}
for( int index = 0; index < NUMDIMS; ++index )
{
a_min[index] = curBranch.m_rect.m_min[index];
a_max[index] = curBranch.m_rect.m_max[index];
}
/// Prefix ++ operator
Iterator& operator++()
{
FindNextData();
return *this;
}
/// Postfix ++ operator
Iterator operator++( int )
{
Iterator retval = *this;
FindNextData();
return retval;
}
bool operator==( const Iterator& rhs ) const
{
return ( ( m_tos <= 0 && rhs.m_tos <= 0 )
|| ( m_tos == rhs.m_tos && m_stack[m_tos].m_node == rhs.m_stack[m_tos].m_node
&& m_stack[m_tos].m_branchIndex
== rhs.m_stack[m_tos].m_branchIndex ) );
}
bool operator!=( const Iterator& rhs ) const
{
return ( ( m_tos > 0 || rhs.m_tos > 0 )
&& ( m_tos != rhs.m_tos || m_stack[m_tos].m_node != rhs.m_stack[m_tos].m_node
|| m_stack[m_tos].m_branchIndex
!= rhs.m_stack[m_tos].m_branchIndex ) );
}
private:
/// Reset iterator
void Init() { m_tos = 0; }
/// Find the next data element in the tree (For internal use only)
bool FindNextData()
void FindNextData()
{
for( ; ; )
while( m_tos > 0 )
{
if( m_tos <= 0 )
{
return false;
}
StackElement curTos = Pop(); // Copy stack top cause it may change as we use it
StackElement curTos = Pop();
int nextBranch = curTos.m_branchIndex + 1;
if( curTos.m_node->IsLeaf() )
{
// Keep walking through data while we can
if( curTos.m_branchIndex + 1 < curTos.m_node->m_count )
// Keep walking through siblings until we find an overlapping leaf
for( int i = nextBranch; i < curTos.m_node->m_count; i++ )
{
// There is more data, just point to the next one
Push( curTos.m_node, curTos.m_branchIndex + 1 );
return true;
if( RTree::Overlap( &m_rect, &curTos.m_node->m_branch[i].m_rect ) )
{
Push( curTos.m_node, i );
return;
}
}
// No more data, so it will fall back to previous level
}
else
{
if( curTos.m_branchIndex + 1 < curTos.m_node->m_count )
// Look for an overlapping sibling that we can use as the fall-back node
// when we've iterated down the current branch
for( int i = nextBranch; i < curTos.m_node->m_count; i++ )
{
// Push sibling on for future tree walk
// This is the 'fall back' node when we finish with the current level
Push( curTos.m_node, curTos.m_branchIndex + 1 );
if( RTree::Overlap( &m_rect, &curTos.m_node->m_branch[i].m_rect ) )
{
Push( curTos.m_node, i );
break;
}
}
// Since cur node is not a leaf, push first of next level to get deeper into the tree
Node* nextLevelnode = curTos.m_node->m_branch[curTos.m_branchIndex].m_child;
// Since cur node is not a leaf, push first of next level,
// zero-th branch to get deeper into the tree
Push( nextLevelnode, 0 );
// If we pushed on a new leaf, exit as the data is ready at TOS
if( nextLevelnode->IsLeaf() )
{
return true;
}
// If the branch is a leaf, and it overlaps, then break with the current data
// Otherwise, we allow it to seed our next iteration as it may have siblings that
// do overlap
if( nextLevelnode->IsLeaf()
&& RTree::Overlap( &m_rect, &nextLevelnode->m_branch[0].m_rect ) )
return;
}
}
}
@ -322,56 +389,55 @@ public:
return m_stack[m_tos];
}
StackElement m_stack[MAX_STACK]; ///< Stack as we are doing iteration instead of recursion
int m_tos; ///< Top Of Stack index
std::array<StackElement, MAX_STACK> m_stack; ///< Stack for iteration
int m_tos; ///< Top Of Stack index
Rect m_rect; ///< Search rectangle
friend class RTree; // Allow hiding of non-public functions while allowing manipulation by logical owner
friend class RTree;
// Allow hiding of non-public functions while allowing manipulation by logical owner
};
using iterator = Iterator;
using const_iterator = const Iterator;
/// Get 'first' for iteration
void GetFirst( Iterator& a_it )
iterator begin( Rect& aRect )
{
a_it.Init();
Node* first = m_root;
iterator retval( aRect );
while( first )
// Only a single element in the tree
if( m_root->IsLeaf() )
{
if( first->IsInternalNode() && first->m_count > 1 )
{
a_it.Push( first, 1 ); // Descend sibling branch later
}
else if( first->IsLeaf() )
{
if( first->m_count )
{
a_it.Push( first, 0 );
}
if( m_root->m_count && Overlap( &aRect, &m_root->m_branch[0].m_rect ) )
retval.Push( m_root, 0 );
break;
}
first = first->m_branch[0].m_child;
return retval;
}
retval.Push( m_root, 0 );
++retval;
return retval;
}
/// Get Next for iteration
void GetNext( Iterator& a_it ) { ++a_it; }
/// Is iterator NULL, or at end?
bool IsNull( Iterator& a_it ) { return a_it.IsNull(); }
/// Get object at iterator position
DATATYPE& GetAt( Iterator& a_it ) { return *a_it; }
protected:
/// Minimal bounding rectangle (n-dimensional)
struct Rect
iterator begin()
{
ELEMTYPE m_min[NUMDIMS]; ///< Min dimensions of bounding box
ELEMTYPE m_max[NUMDIMS]; ///< Max dimensions of bounding box
};
Rect full_rect( { { INT_MIN, INT_MIN, INT_MIN }, { INT_MAX, INT_MAX, INT_MAX } } );
return begin( full_rect );
}
iterator end()
{
iterator retval;
return retval;
}
iterator end( Rect& aRect )
{
return end();
}
protected:
/// May be data or may be another subtree
/// The parents level determines this.
/// If the parents level is 0, then this is data
@ -460,7 +526,7 @@ protected:
ListNode** a_listNode );
ListNode* AllocListNode();
void FreeListNode( ListNode* a_listNode );
bool Overlap( Rect* a_rectA, Rect* a_rectB ) const;
static bool Overlap( Rect* a_rectA, Rect* a_rectB );
void ReInsert( Node* a_node, ListNode** a_listNode );
ELEMTYPE MinDist( const ELEMTYPE a_point[NUMDIMS], Rect* a_rect );
void InsertNNListSorted( std::vector<NNNode*>* nodeList, NNNode* newNode );
@ -716,6 +782,35 @@ int RTREE_QUAL::Search( const ELEMTYPE a_min[NUMDIMS],
}
RTREE_TEMPLATE
int RTREE_QUAL::Search( const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDIMS],
std::function<bool( const DATATYPE& )> a_callback, bool& aFinished ) const
{
#ifdef _DEBUG
for( int index = 0; index < NUMDIMS; ++index )
{
ASSERT( a_min[index] <= a_max[index] );
}
#endif // _DEBUG
Rect rect;
for( int axis = 0; axis < NUMDIMS; ++axis )
{
rect.m_min[axis] = a_min[axis];
rect.m_max[axis] = a_max[axis];
}
// NOTE: May want to return search result another way, perhaps returning the number of found elements here.
int foundCount = 0;
aFinished = Search( m_root, &rect, foundCount, a_callback );
return foundCount;
}
RTREE_TEMPLATE
DATATYPE RTREE_QUAL::NearestNeighbor( const ELEMTYPE a_point[NUMDIMS] )
{
@ -728,7 +823,6 @@ DATATYPE RTREE_QUAL::NearestNeighbor( const ELEMTYPE a_point[NUMDIMS],
ELEMTYPE a_squareDistanceCallback( const ELEMTYPE a_point[NUMDIMS], DATATYPE a_data ),
ELEMTYPE* a_squareDistance )
{
typedef typename std::vector<NNNode*>::iterator iterator;
std::vector<NNNode*> nodeList;
Node* node = m_root;
NNNode* closestNode = 0;
@ -759,9 +853,9 @@ DATATYPE RTREE_QUAL::NearestNeighbor( const ELEMTYPE a_point[NUMDIMS],
}
// free memory used for remaining NNNodes in nodeList
for( iterator iter = nodeList.begin(); iter != nodeList.end(); ++iter )
for( auto node_it : nodeList )
{
NNNode* nnode = *iter;
NNNode* nnode = node_it;
free(nnode);
}
@ -1767,7 +1861,7 @@ bool RTREE_QUAL::RemoveRectRec( Rect* a_rect,
// Decide whether two rectangles overlap.
RTREE_TEMPLATE
bool RTREE_QUAL::Overlap( Rect* a_rectA, Rect* a_rectB ) const
bool RTREE_QUAL::Overlap( Rect* a_rectA, Rect* a_rectB )
{
ASSERT( a_rectA && a_rectB );
@ -1873,12 +1967,12 @@ ELEMTYPE RTREE_QUAL::MinDist( const ELEMTYPE a_point[NUMDIMS], Rect* a_rect )
RTREE_TEMPLATE
void RTREE_QUAL::InsertNNListSorted( std::vector<NNNode*>* nodeList, NNNode* newNode )
{
typedef typename std::vector<NNNode*>::iterator iterator;
iterator iter = nodeList->begin();
auto iter = nodeList->begin();
while( iter != nodeList->end() && (*iter)->minDist > newNode->minDist )
{
++iter;
}
nodeList->insert(iter, newNode);
}