Improve robustness of SCH_PIN storage architecture.

In particular, allow short-term storage of pointers to SCH_PINs.
This commit is contained in:
Jeff Young 2019-04-22 11:14:47 +01:00
parent a461eae8b9
commit 5e2cf51309
6 changed files with 163 additions and 146 deletions

View File

@ -432,27 +432,26 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
}
else if( item->Type() == SCH_COMPONENT_T )
{
auto component = static_cast<SCH_COMPONENT*>( item );
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
TRANSFORM t = component->GetTransform();
component->UpdatePins( &aSheet );
for( auto& it : component->GetPinMap() )
for( SCH_PIN& pin : component->GetPins() )
{
SCH_PIN* pin = &it.second;
wxPoint pos = pin->GetTransformedPosition();
wxPoint pos = t.TransformCoordinate( pin.GetPosition() ) + component->GetPosition();
// because calling the first time is not thread-safe
pin->GetDefaultNetName( aSheet );
pin->ConnectedItems().clear();
pin.GetDefaultNetName( aSheet );
pin.ConnectedItems().clear();
// Invisible power pins need to be post-processed later
if( pin->IsPowerConnection() && !pin->IsVisible() )
m_invisible_power_pins.push_back( std::make_pair( aSheet, pin ) );
if( pin.IsPowerConnection() && !pin.IsVisible() )
m_invisible_power_pins.push_back( std::make_pair( aSheet, &pin ) );
connection_map[ pos ].push_back( pin );
m_items.insert( pin );
connection_map[ pos ].push_back( &pin );
m_items.insert( &pin );
}
}
else
@ -464,8 +463,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
switch( item->Type() )
{
case SCH_LINE_T:
conn->SetType( ( item->GetLayer() == LAYER_BUS ) ?
CONNECTION_BUS : CONNECTION_NET );
conn->SetType( item->GetLayer() == LAYER_BUS ? CONNECTION_BUS : CONNECTION_NET );
break;
case SCH_BUS_BUS_ENTRY_T:

View File

@ -22,11 +22,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file sch_component.cpp
* @brief Implementation of the class SCH_COMPONENT.
*/
#include <fctsys.h>
#include <pgm_base.h>
#include <sch_draw_panel.h>
@ -175,16 +170,17 @@ SCH_COMPONENT::SCH_COMPONENT( const SCH_COMPONENT& aComponent ) :
m_Fields = aComponent.m_Fields;
// Re-parent the fields, which before this had aComponent as parent
for( int i = 0; i < GetFieldCount(); ++i )
{
GetField( i )->SetParent( this );
}
for( SCH_FIELD field : m_Fields )
field.SetParent( this );
// Copy the pins, and re-parent them
for( const auto& it : aComponent.m_pins )
m_pins = aComponent.m_pins;
m_pinMap.clear();
// Re-parent the pins and build the pinMap
for( SCH_PIN pin : m_pins )
{
m_pins.emplace( std::make_pair( it.first, it.second ) );
m_pins.at( it.first ).SetParentComponent( this );
pin.SetParent( this );
m_pinMap[ pin.GetLibPin() ] = &pin;
}
m_fieldsAutoplaced = aComponent.m_fieldsAutoplaced;
@ -428,10 +424,8 @@ void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
{
if( PART_SPTR part = m_part.lock() )
{
std::set<LIB_PIN*> stalePins;
for( auto& it : m_pins )
stalePins.insert( it.first );
m_pinMap.clear();
int i = 0;
for( LIB_PIN* libPin = part->GetNextPin(); libPin; libPin = part->GetNextPin( libPin ) )
{
@ -443,25 +437,29 @@ void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
continue;
if( !m_pins.count( libPin ) )
m_pins.emplace( std::make_pair( libPin, SCH_PIN( libPin, this ) ) );
if( m_pins.size() <= i || m_pins[ i ].GetLibPin() != libPin )
{
if( m_pins.size() > i )
m_pins.erase( m_pins.begin() + i, m_pins.end() );
m_pins.emplace_back( SCH_PIN( libPin, this ) );
}
m_pinMap[ libPin ] = &m_pins[ i ];
if( aSheet )
m_pins.at( libPin ).InitializeConnection( *aSheet );
m_pins[ i ].InitializeConnection( *aSheet );
stalePins.erase( libPin );
++i;
}
for( auto& stalePin : stalePins )
m_pins.erase( stalePin );
}
}
SCH_CONNECTION* SCH_COMPONENT::GetConnectionForPin( LIB_PIN* aPin, const SCH_SHEET_PATH& aSheet )
{
if( m_pins.count( aPin ) )
return m_pins.at( aPin ).Connection( aSheet );
if( m_pinMap.count( aPin ) )
return m_pinMap.at( aPin )->Connection( aSheet );
return nullptr;
}
@ -929,12 +927,6 @@ void SCH_COMPONENT::GetPins( std::vector<LIB_PIN*>& aPinsList )
}
SCH_PINS& SCH_COMPONENT::GetPinMap()
{
return m_pins;
}
void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
{
wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
@ -1474,12 +1466,12 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
{
bool changed = false;
for( auto& it : m_pins )
for( SCH_PIN& pin : m_pins )
{
bool previousState = it.second.IsDangling();
it.second.SetIsDangling( true );
bool previousState = pin.IsDangling();
pin.SetIsDangling( true );
wxPoint pos = m_transform.TransformCoordinate( it.second.GetPosition() ) + m_Pos;
wxPoint pos = m_transform.TransformCoordinate( pin.GetPosition() ) + m_Pos;
for( DANGLING_END_ITEM& each_item : aItemList )
{
@ -1501,7 +1493,7 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
case JUNCTION_END:
if( pos == each_item.GetPosition() )
it.second.SetIsDangling( false );
pin.SetIsDangling( false );
break;
@ -1509,11 +1501,11 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
break;
}
if( !it.second.IsDangling() )
if( !pin.IsDangling() )
break;
}
changed = ( changed || ( previousState != it.second.IsDangling() ) );
changed = ( changed || ( previousState != pin.IsDangling() ) );
}
return changed;
@ -1546,8 +1538,8 @@ bool SCH_COMPONENT::IsSelectStateChanged( const wxRect& aRect )
void SCH_COMPONENT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
{
for( auto& it : m_pins )
aPoints.push_back( m_transform.TransformCoordinate( it.second.GetPosition() ) + m_Pos );
for( const SCH_PIN& pin : m_pins )
aPoints.push_back( m_transform.TransformCoordinate( pin.GetPosition() ) + m_Pos );
}
@ -1757,19 +1749,20 @@ SCH_ITEM& SCH_COMPONENT::operator=( const SCH_ITEM& aItem )
m_PathsAndReferences = c->m_PathsAndReferences;
m_Fields = c->m_Fields; // std::vector's assignment operator.
m_Fields = c->m_Fields; // std::vector's assignment operator
// Reparent fields after assignment to new component.
for( int ii = 0; ii < GetFieldCount(); ++ii )
{
GetField( ii )->SetParent( this );
}
for( SCH_FIELD field : m_Fields )
field.SetParent( this );
// Copy the pins, and re-parent them
for( const auto& it : c->m_pins )
m_pins = c->m_pins; // std::vector's assignment operator
m_pinMap.clear();
// Re-parent the pins and build the pinMap
for( SCH_PIN pin : m_pins )
{
m_pins.emplace( std::make_pair( it.first, it.second ) );
m_pins.at( it.first ).SetParentComponent( this );
pin.SetParent( this );
m_pinMap[ pin.GetLibPin() ] = &pin;
}
}
@ -1809,9 +1802,9 @@ bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
{
wxPoint new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_Pos );
for( const auto& it : m_pins )
for( const SCH_PIN& pin : m_pins )
{
if( it.second.GetPosition() == new_pos )
if( pin.GetPosition() == new_pos )
return true;
}
@ -1836,8 +1829,8 @@ void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
part->Plot( aPlotter, GetUnit(), GetConvert(), m_Pos, temp );
for( size_t i = 0; i < m_Fields.size(); i++ )
m_Fields[i].Plot( aPlotter );
for( SCH_FIELD field : m_Fields )
field.Plot( aPlotter );
aPlotter->EndBlock( nullptr );
}
@ -1846,9 +1839,9 @@ void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
bool SCH_COMPONENT::HasBrightenedPins()
{
for( auto& it : m_pins )
for( const SCH_PIN& pin : m_pins )
{
if( it.second.IsBrightened() )
if( pin.IsBrightened() )
return true;
}
@ -1858,29 +1851,29 @@ bool SCH_COMPONENT::HasBrightenedPins()
void SCH_COMPONENT::ClearBrightenedPins()
{
for( auto& it : m_pins )
it.second.ClearBrightened();
for( SCH_PIN& pin : m_pins )
pin.ClearBrightened();
}
void SCH_COMPONENT::BrightenPin( LIB_PIN* aPin )
{
if( m_pins.count( aPin ) )
m_pins.at( aPin ).SetBrightened();
if( m_pinMap.count( aPin ) )
m_pinMap.at( aPin )->SetBrightened();
}
void SCH_COMPONENT::ClearHighlightedPins()
{
for( auto& it : m_pins )
it.second.ClearHighlighted();
for( SCH_PIN& pin : m_pins )
pin.ClearHighlighted();
}
void SCH_COMPONENT::HighlightPin( LIB_PIN* aPin )
{
if( m_pins.count( aPin ) )
m_pins.at( aPin ).SetHighlighted();
if( m_pinMap.count( aPin ) )
m_pinMap.at( aPin )->SetHighlighted();
}

View File

@ -4,7 +4,7 @@
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2014 Dick Hollenbeck, dick@softplc.com
* Copyright (C) 2015 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2017 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
@ -24,11 +24,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file sch_component.h
* @brief Definition the SCH_COMPONENT class for Eeschema.
*/
#ifndef COMPONENT_CLASS_H
#define COMPONENT_CLASS_H
@ -56,7 +51,10 @@ class SYMBOL_LIB_TABLE;
/// Pins, mapped by their corresponding LIB_PINs.
typedef std::unordered_map<LIB_PIN*, SCH_PIN> SCH_PINS;
typedef std::unordered_map<LIB_PIN*, SCH_PIN*> SCH_PIN_MAP;
/// A container for several SCH_PIN items
typedef std::vector<SCH_PIN> SCH_PINS;
/// A container for several SCH_FIELD items
typedef std::vector<SCH_FIELD> SCH_FIELDS;
@ -96,7 +94,8 @@ private:
PART_REF m_part; ///< points into the PROJECT's libraries to the LIB_PART for this component
SCH_PINS m_pins;
SCH_PINS m_pins; ///< the component's pins
SCH_PIN_MAP m_pinMap; ///< the component's pins mapped by LIB_PIN*.
AUTOPLACED m_fieldsAutoplaced; ///< indicates status of field autoplacement
@ -461,11 +460,7 @@ public:
*/
void GetPins( std::vector<LIB_PIN*>& aPinsList );
/**
* Return a map of library pins to their SCH_PIN equivalents.
* @return
*/
SCH_PINS& GetPinMap();
SCH_PINS& GetPins() { return m_pins; }
/**
* Draw a component

View File

@ -943,7 +943,7 @@ void SCH_PAINTER::draw( SCH_LINE *aLine, int aLayer )
VECTOR2D start = aLine->GetStartPoint();
VECTOR2D end = aLine->GetEndPoint();
EDA_RECT clip( wxPoint( start.x, start.y ), wxSize( end.x - start.x, end.y - start.y ) );
EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) );
clip.Normalize();
double theta = atan2( end.y - start.y, end.x - start.x );
@ -1093,13 +1093,9 @@ void SCH_PAINTER::draw( SCH_COMPONENT *aComp, int aLayer )
// Use dummy part if the actual couldn't be found (or couldn't be locked).
LIB_PART* originalPart = originalPartSptr ? originalPartSptr.get() : dummy();
LIB_PINS originalPins;
originalPart->GetPins( originalPins, aComp->GetUnit(), aComp->GetConvert() );
// Copy the source so we can re-orient and translate it.
LIB_PART tempPart( *originalPart );
LIB_PINS tempPins;
tempPart.GetPins( tempPins, aComp->GetUnit(), aComp->GetConvert() );
tempPart.SetFlags( aComp->GetFlags() );
@ -1108,24 +1104,21 @@ void SCH_PAINTER::draw( SCH_COMPONENT *aComp, int aLayer )
for( auto& tempItem : tempPart.GetDrawItems() )
tempItem.Move( tempItem.GetPosition() + (wxPoint) mapCoords( aComp->GetPosition() ) );
// Copy pin info from the component
SCH_PINS pinMap = aComp->GetPinMap();
// Copy the pin info from the component to the temp pins
LIB_PINS tempPins;
tempPart.GetPins( tempPins, aComp->GetUnit(), aComp->GetConvert() );
const SCH_PINS& compPins = aComp->GetPins();
for( unsigned i = 0; i < originalPins.size() && i < tempPins.size(); ++i )
for( int i = 0; i < tempPins.size() && i < compPins.size(); ++ i )
{
LIB_PIN* originalPin = originalPins[ i ];
LIB_PIN* tempPin = tempPins[ i ];
const SCH_PIN& compPin = compPins[ i ];
if( pinMap.count( originalPin ) )
{
const SCH_PIN& schPin = pinMap.at( originalPin );
tempPin->ClearFlags();
tempPin->SetFlags( compPin.GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
tempPin->ClearFlags();
tempPin->SetFlags( schPin.GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
if( schPin.IsDangling() )
tempPin->SetFlags( IS_DANGLING );
}
if( compPin.IsDangling() )
tempPin->SetFlags( IS_DANGLING );
}
draw( &tempPart, aLayer, false, aComp->GetUnit(), aComp->GetConvert() );

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 CERN
* Copyright (C) 2019 KiCad Developers, see change_log.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program is free software; you can redistribute it and/or
@ -25,9 +26,8 @@
SCH_PIN::SCH_PIN( LIB_PIN* aLibPin, SCH_COMPONENT* aParentComponent ) :
SCH_ITEM( nullptr, SCH_PIN_T ),
m_pin( aLibPin ),
m_comp( aParentComponent )
SCH_ITEM( aParentComponent, SCH_PIN_T ),
m_libPin( aLibPin )
{
SetPosition( aLibPin->GetPosition() );
m_isDangling = true;
@ -35,37 +35,48 @@ SCH_PIN::SCH_PIN( LIB_PIN* aLibPin, SCH_COMPONENT* aParentComponent ) :
SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
SCH_ITEM( aPin )
SCH_ITEM( aPin )
{
m_pin = aPin.m_pin;
m_comp = aPin.m_comp;
m_libPin = aPin.m_libPin;
m_position = aPin.m_position;
m_isDangling = aPin.m_isDangling;
}
SCH_PIN& SCH_PIN::operator=( const SCH_PIN& aPin )
{
SCH_ITEM::operator=( aPin );
m_libPin = aPin.m_libPin;
m_position = aPin.m_position;
m_isDangling = aPin.m_isDangling;
}
SCH_COMPONENT* SCH_PIN::GetParentComponent() const
{
return static_cast<SCH_COMPONENT*>( GetParent() );
}
wxString SCH_PIN::GetSelectMenuText( EDA_UNITS_T aUnits ) const
{
wxString tmp;
return wxString::Format( "%s %s",
GetParentComponent()->GetSelectMenuText( aUnits ),
m_libPin->GetSelectMenuText( aUnits ) );
}
#ifdef DEBUG
tmp.Printf( "SCH_PIN for %s %s",
m_comp->GetSelectMenuText( aUnits ),
m_pin->GetSelectMenuText( aUnits ) );
#else
tmp.Printf( "%s %s",
m_comp->GetSelectMenuText( aUnits ),
m_pin->GetSelectMenuText( aUnits ) );
#endif
return tmp;
void SCH_PIN::GetMsgPanelInfo( EDA_UNITS_T aUnits, MSG_PANEL_ITEMS& aList )
{
m_libPin->GetMsgPanelInfo( aUnits, aList, GetParentComponent() );
}
wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH aPath )
{
if( m_pin->IsPowerConnection() )
return m_pin->GetName();
if( m_libPin->IsPowerConnection() )
return m_libPin->GetName();
std::lock_guard<std::mutex> lock( m_netmap_mutex );
@ -74,13 +85,13 @@ wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH aPath )
wxString name = "Net-(";
name << m_comp->GetRef( &aPath );
name << GetParentComponent()->GetRef( &aPath );
// TODO(JE) do we need adoptTimestamp?
if( /* adoptTimestamp && */ name.Last() == '?' )
name << m_comp->GetTimeStamp();
name << GetParentComponent()->GetTimeStamp();
name << "-Pad" << m_pin->GetNumber() << ")";
name << "-Pad" << m_libPin->GetNumber() << ")";
m_net_name_map[ aPath ] = name;
@ -90,7 +101,32 @@ wxString SCH_PIN::GetDefaultNetName( const SCH_SHEET_PATH aPath )
wxPoint SCH_PIN::GetTransformedPosition() const
{
auto t = m_comp->GetTransform();
return ( t.TransformCoordinate( GetPosition() ) +
m_comp->GetPosition() );
TRANSFORM t = GetParentComponent()->GetTransform();
return ( t.TransformCoordinate( GetPosition() ) + GetParentComponent()->GetPosition() );
}
const EDA_RECT SCH_PIN::GetBoundingBox() const
{
// Due to pins being relative to their component parent's position, this is unlikely
// to do what a caller wants. Use HitTest() directly instead.
wxFAIL_MSG( "SCH_PINs bounding box is relative to parent component" );
return m_libPin->GetBoundingBox();
}
bool SCH_PIN::HitTest( const wxPoint& aPosition ) const
{
// Pin hit testing is relative to the components position and orientation in the
// schematic. The hit test position must be converted to library coordinates.
TRANSFORM t = GetParentComponent()->GetTransform().InverseTransform();
wxPoint pos = t.TransformCoordinate( aPosition - GetParentComponent()->GetPosition() );
pos.y *= -1; // Y axis polarity in schematic is inverted from library.
return m_libPin->GetBoundingBox().Contains( pos );
}

View File

@ -2,6 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2018 CERN
* Copyright (C) 2019 KiCad Developers, see change_log.txt for contributors.
* @author Jon Evans <jon@craftyjon.com>
*
* This program is free software; you can redistribute it and/or
@ -33,8 +34,7 @@ class SCH_COMPONENT;
class SCH_PIN : public SCH_ITEM
{
LIB_PIN* m_pin;
SCH_COMPONENT* m_comp;
LIB_PIN* m_libPin;
wxPoint m_position;
bool m_isDangling;
@ -48,36 +48,38 @@ public:
SCH_PIN( const SCH_PIN& aPin );
SCH_PIN& operator=( const SCH_PIN& aPin );
wxString GetClass() const override
{
return wxT( "SCH_PIN" );
}
LIB_PIN* GetLibPin() const { return m_pin; }
SCH_COMPONENT* GetParentComponent() const;
SCH_COMPONENT* GetParentComponent() const { return m_comp; }
void SetParentComponent( SCH_COMPONENT* aComp ) { m_comp = aComp; }
LIB_PIN* GetLibPin() const { return m_libPin; }
wxString GetDefaultNetName( const SCH_SHEET_PATH aPath );
wxString GetSelectMenuText( EDA_UNITS_T aUnits ) const override;
void GetMsgPanelInfo( EDA_UNITS_T aUnits, MSG_PANEL_ITEMS& aList ) override;
void Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset ) override {}
void Move( const wxPoint& aMoveVector ) override {}
void MirrorY( int aYaxis_position ) override {}
void MirrorX( int aXaxis_position ) override {}
void Rotate( wxPoint aPosition ) override {}
wxPoint GetPosition() const override { return m_position; }
void SetPosition( const wxPoint& aPosition ) override { m_position = aPosition; }
bool IsDangling() const override { return m_isDangling; }
const EDA_RECT GetBoundingBox() const override;
bool HitTest( const wxPoint& aPosition ) const override;
bool IsDangling() const override { return m_isDangling; }
void SetIsDangling( bool isDangling ) { m_isDangling = isDangling; }
/// Returns the pin's position in global coordinates
@ -88,15 +90,15 @@ public:
* While many of these are currently simply covers for the equivalent LIB_PIN methods,
* the new EESchema file format will soon allow us to override them at the SCH level.
*/
bool IsVisible() const { return m_pin->IsVisible(); }
bool IsVisible() const { return m_libPin->IsVisible(); }
const wxString& GetName() const { return m_pin->GetName(); }
const wxString& GetName() const { return m_libPin->GetName(); }
const wxString& GetNumber() const { return m_pin->GetNumber(); }
const wxString& GetNumber() const { return m_libPin->GetNumber(); }
ELECTRICAL_PINTYPE GetType() const { return m_pin->GetType(); }
ELECTRICAL_PINTYPE GetType() const { return m_libPin->GetType(); }
bool IsPowerConnection() const { return m_pin->IsPowerConnection(); }
bool IsPowerConnection() const { return m_libPin->IsPowerConnection(); }
#if defined(DEBUG)