Eeschema: Force output ordering
The RTree does not have a deterministic iterator, so extracting items may be in arbitrary order, causing issues as the schematic appears to change when comparing to previous revisions. This uses the SCH_ITEM comparison operator to for ordering by type, then by custom sorting within type. For the netlist, we choose the first available unit in the sheet for each component. Fixes #3811 | https://gitlab.com/kicad/code/kicad/issues/3811
This commit is contained in:
parent
128ec782dd
commit
55eb687184
|
@ -212,7 +212,30 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeComponents()
|
|||
|
||||
for( unsigned i = 0; i < sheetList.size(); i++ )
|
||||
{
|
||||
|
||||
auto cmp = []( const SCH_COMPONENT* a, const SCH_COMPONENT* b ) {
|
||||
return a->GetField( REFERENCE )->GetText() < b->GetField( REFERENCE )->GetText();
|
||||
};
|
||||
|
||||
std::set<SCH_COMPONENT*, decltype( cmp )> ordered_components( cmp );
|
||||
|
||||
for( auto item : sheetList[i].LastScreen()->Items().OfType( SCH_COMPONENT_T ) )
|
||||
{
|
||||
auto comp = static_cast<SCH_COMPONENT*>( item );
|
||||
auto test = ordered_components.insert( comp );
|
||||
|
||||
if( !test.second )
|
||||
{
|
||||
if( ( *( test.first ) )->GetUnit() > comp->GetUnit() )
|
||||
{
|
||||
ordered_components.erase( test.first );
|
||||
ordered_components.insert( comp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( auto item : ordered_components )
|
||||
{
|
||||
SCH_COMPONENT* comp = findNextComponent( item, &sheetList[i] );
|
||||
|
||||
|
|
|
@ -1714,7 +1714,7 @@ bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
|
|||
if( Type() != aItem.Type() )
|
||||
return Type() < aItem.Type();
|
||||
|
||||
SCH_COMPONENT* component = (SCH_COMPONENT*) &aItem;
|
||||
auto component = static_cast<const SCH_COMPONENT*>( &aItem );
|
||||
|
||||
EDA_RECT rect = GetBodyBoundingBox();
|
||||
|
||||
|
@ -1727,7 +1727,7 @@ bool SCH_COMPONENT::operator <( const SCH_ITEM& aItem ) const
|
|||
if( m_Pos.y != component->m_Pos.y )
|
||||
return m_Pos.y < component->m_Pos.y;
|
||||
|
||||
return false;
|
||||
return GetTimeStamp() < aItem.GetTimeStamp();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -171,8 +171,18 @@ void SCH_ITEM::SwapData( SCH_ITEM* aItem )
|
|||
|
||||
bool SCH_ITEM::operator < ( const SCH_ITEM& aItem ) const
|
||||
{
|
||||
wxCHECK_MSG( false, this->Type() < aItem.Type(),
|
||||
wxT( "Less than operator not defined for " ) + GetClass() );
|
||||
bool retval = ( Type() < aItem.Type() );
|
||||
|
||||
if( Type() != aItem.Type() )
|
||||
return Type() < aItem.Type();
|
||||
|
||||
if( GetTimeStamp() != aItem.GetTimeStamp() )
|
||||
return GetTimeStamp() < aItem.GetTimeStamp();
|
||||
|
||||
if( GetPosition().x != aItem.GetPosition().x )
|
||||
return GetPosition().x < aItem.GetPosition().x;
|
||||
|
||||
return GetPosition().y < aItem.GetPosition().y;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#include <algorithm>
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <cctype>
|
||||
#include <set>
|
||||
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/filename.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <gr_text.h>
|
||||
#include <kiway.h>
|
||||
|
@ -1877,7 +1879,15 @@ void SCH_LEGACY_PLUGIN::Format( SCH_SCREEN* aScreen )
|
|||
saveBusAlias( alias );
|
||||
}
|
||||
|
||||
// Enforce item ordering
|
||||
auto cmp = []( const SCH_ITEM* a, const SCH_ITEM* b ) { return *a < *b; };
|
||||
std::multiset<SCH_ITEM*, decltype( cmp )> save_map( cmp );
|
||||
|
||||
for( auto item : aScreen->Items() )
|
||||
save_map.insert( item );
|
||||
|
||||
|
||||
for( auto& item : save_map )
|
||||
{
|
||||
switch( item->Type() )
|
||||
{
|
||||
|
|
|
@ -689,7 +689,7 @@ bool SCH_LINE::operator <( const SCH_ITEM& aItem ) const
|
|||
if( Type() != aItem.Type() )
|
||||
return Type() < aItem.Type();
|
||||
|
||||
SCH_LINE* line = (SCH_LINE*) &aItem;
|
||||
auto line = static_cast<const SCH_LINE*>( &aItem );
|
||||
|
||||
if( GetLength() != line->GetLength() )
|
||||
return GetLength() < line->GetLength();
|
||||
|
|
|
@ -263,6 +263,24 @@ void SCH_TEXT::SwapData( SCH_ITEM* aItem )
|
|||
}
|
||||
|
||||
|
||||
bool SCH_TEXT::operator<( const SCH_ITEM& aItem ) const
|
||||
{
|
||||
if( Type() != aItem.Type() )
|
||||
return Type() < aItem.Type();
|
||||
|
||||
auto other = static_cast<const SCH_TEXT*>( &aItem );
|
||||
|
||||
|
||||
if( GetPosition().x != other->GetPosition().x )
|
||||
return GetPosition().x < other->GetPosition().x;
|
||||
|
||||
if( GetPosition().y != other->GetPosition().y )
|
||||
return GetPosition().y < other->GetPosition().y;
|
||||
|
||||
return GetText() < other->GetText();
|
||||
}
|
||||
|
||||
|
||||
int SCH_TEXT::GetPenSize() const
|
||||
{
|
||||
int pensize = GetThickness();
|
||||
|
|
|
@ -270,6 +270,8 @@ public:
|
|||
|
||||
const EDA_RECT GetBoundingBox() const override;
|
||||
|
||||
bool operator<( const SCH_ITEM& aItem ) const override;
|
||||
|
||||
int GetPenSize() const override;
|
||||
|
||||
// Geometric transforms (used in block operations):
|
||||
|
|
Loading…
Reference in New Issue