Performance UpdateDanglingState
Avoid O(N^2) by spatial sorting, don't run checks if the bounding boxes
don't overlap.
A second copy is ordered by type to help classes that only want to check
a few types having to walk the whole list.
(cherry picked from commit b7b64d959f
)
This commit is contained in:
parent
ffd470d94d
commit
7d5583f687
|
@ -242,7 +242,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
|||
{
|
||||
KIGFX::VIEW* view = m_preview->GetView();
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
m_page = new PAGE_INFO( PAGE_INFO::Custom );
|
||||
m_titleBlock = new TITLE_BLOCK;
|
||||
|
@ -399,7 +399,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
|||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
pin->SetNameTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
|
@ -413,7 +413,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
|||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
pin->SetNameTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
pin = new LIB_PIN( symbol );
|
||||
|
@ -427,7 +427,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
|||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
pin->SetNameTextSize( schIUScale.MilsToIU( 50 ) );
|
||||
|
||||
endPoints.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
endPointsByType.emplace_back( PIN_END, pin, mapLibItemPosition( pin->GetPosition() ) );
|
||||
symbol->AddDrawItem( pin );
|
||||
|
||||
addItem( symbol );
|
||||
|
@ -452,16 +452,19 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
|||
if( sch_item && sch_item->IsConnectable() )
|
||||
{
|
||||
sch_item->AutoplaceFields( nullptr, false );
|
||||
sch_item->GetEndPoints( endPoints );
|
||||
sch_item->GetEndPoints( endPointsByType );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : m_previewItems )
|
||||
{
|
||||
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
|
||||
|
||||
if( sch_item && sch_item->IsConnectable() )
|
||||
sch_item->UpdateDanglingState( endPoints, nullptr );
|
||||
sch_item->UpdateDanglingState( endPointsByType, endPointsByPos, nullptr );
|
||||
}
|
||||
|
||||
zoomFitPreview();
|
||||
|
|
|
@ -312,8 +312,9 @@ void SCH_BUS_ENTRY_BASE::Rotate( const VECTOR2I& aCenter )
|
|||
}
|
||||
|
||||
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
|
@ -324,9 +325,9 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
|||
bool has_wire[2] = { false };
|
||||
bool has_bus[2] = { false };
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
@ -344,7 +345,7 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
|||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
has_bus[0] = true;
|
||||
|
@ -371,17 +372,19 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
|||
}
|
||||
|
||||
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousStateStart = m_isDanglingStart;
|
||||
bool previousStateEnd = m_isDanglingEnd;
|
||||
|
||||
m_isDanglingStart = m_isDanglingEnd = true;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
// TODO: filter using get_lower as we only use one item type
|
||||
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = aItemListByType[ii];
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
@ -391,7 +394,7 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
|
|||
case BUS_END:
|
||||
{
|
||||
// The bus has created 2 DANGLING_END_ITEMs, one per end.
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
|
||||
|
||||
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||
m_isDanglingStart = false;
|
||||
|
|
|
@ -195,8 +195,9 @@ public:
|
|||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus item (usually a bus wire) connected to this bus-wire
|
||||
|
@ -240,8 +241,9 @@ public:
|
|||
|
||||
BITMAPS GetMenuImage() const override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
/**
|
||||
* Pointer to the bus items (usually bus wires) connected to this bus-bus
|
||||
|
|
|
@ -392,3 +392,50 @@ static struct SCH_ITEM_DESC
|
|||
} _SCH_ITEM_DESC;
|
||||
|
||||
IMPLEMENT_ENUM_TO_WXANY( SCH_LAYER_ID )
|
||||
|
||||
|
||||
static bool lessYX( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
const auto aPos = a.GetPosition();
|
||||
const auto bPos = b.GetPosition();
|
||||
return aPos.y < bPos.y ? true : ( aPos.y > bPos.y ? false : aPos.x < bPos.x );
|
||||
};
|
||||
|
||||
|
||||
static bool lessType( const DANGLING_END_ITEM& a, const DANGLING_END_ITEM& b )
|
||||
{
|
||||
return a.GetType() < b.GetType();
|
||||
};
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const VECTOR2I& aPos )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( PIN_END, nullptr, aPos );
|
||||
auto start = aItemListByPos.begin();
|
||||
auto end = aItemListByPos.end();
|
||||
return std::lower_bound( start, end, needle, lessYX );
|
||||
}
|
||||
|
||||
|
||||
std::vector<DANGLING_END_ITEM>::iterator
|
||||
DANGLING_END_ITEM_HELPER::get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
const DANGLING_END_T& aType )
|
||||
{
|
||||
DANGLING_END_ITEM needle = DANGLING_END_ITEM( aType, nullptr, VECTOR2I{} );
|
||||
auto start = aItemListByType.begin();
|
||||
auto end = aItemListByType.end();
|
||||
return std::lower_bound( start, end, needle, lessType );
|
||||
}
|
||||
|
||||
|
||||
void DANGLING_END_ITEM_HELPER::sort_dangling_end_items(
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos )
|
||||
{
|
||||
// WIRE_END pairs must be kept together. Hence stable sort.
|
||||
std::stable_sort( aItemListByType.begin(), aItemListByType.end(), lessType );
|
||||
// Sort by y first, pins are more likely to share x than y.
|
||||
std::sort( aItemListByPos.begin(), aItemListByPos.end(), lessYX );
|
||||
}
|
||||
|
|
|
@ -137,6 +137,20 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class DANGLING_END_ITEM_HELPER
|
||||
{
|
||||
public:
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_pos( std::vector<DANGLING_END_ITEM>& aItemListByPos, const VECTOR2I& aPos );
|
||||
|
||||
static std::vector<DANGLING_END_ITEM>::iterator
|
||||
get_lower_type( std::vector<DANGLING_END_ITEM>& aItemListByType, const DANGLING_END_T& aType );
|
||||
|
||||
/** Both contain the same information */
|
||||
static void sort_dangling_end_items( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos );
|
||||
};
|
||||
|
||||
typedef std::vector<SCH_ITEM*> SCH_ITEM_SET;
|
||||
|
||||
|
||||
|
@ -352,12 +366,15 @@ public:
|
|||
* If aSheet is passed a non-null pointer to a SCH_SHEET_PATH, the overridden method can
|
||||
* optionally use it to update sheet-local connectivity information
|
||||
*
|
||||
* @param aItemList is the list of items to test item against.
|
||||
* @param aItemListByType is the list of items to test item against. It's sorted
|
||||
* by item type, keeping WIRE_END pairs together.
|
||||
* @param aItemListByPos is the same list but sorted first by Y then by X.
|
||||
* @param aSheet is the sheet path to update connections for.
|
||||
* @return True if the dangling state has changed from it's current setting.
|
||||
*/
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1101,16 +1101,19 @@ bool SCH_LABEL_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy
|
|||
}
|
||||
|
||||
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool previousState = m_isDangling;
|
||||
m_isDangling = true;
|
||||
bool previousState = m_isDangling;
|
||||
VECTOR2I text_pos = GetTextPos();
|
||||
m_isDangling = true;
|
||||
m_connectionType = CONNECTION_TYPE::NONE;
|
||||
|
||||
for( unsigned ii = 0; ii < aItemList.size(); ii++ )
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, text_pos );
|
||||
it < aItemListByPos.end() && it->GetPosition() == text_pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = aItemList[ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
@ -1121,33 +1124,68 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
|||
case LABEL_END:
|
||||
case SHEET_LABEL_END:
|
||||
case NO_CONNECT_END:
|
||||
if( GetTextPos() == item.GetPosition() )
|
||||
if( text_pos == item.GetPosition() )
|
||||
{
|
||||
m_isDangling = false;
|
||||
|
||||
if( aPath && item.GetType() != PIN_END )
|
||||
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BUS_END:
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
KI_FALLTHROUGH;
|
||||
default: break;
|
||||
}
|
||||
|
||||
case WIRE_END:
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, BUS_END );
|
||||
it < aItemListByType.end() && it->GetType() == BUS_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& nextItem = aItemList[++ii];
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( GetTextPos(), item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(),
|
||||
accuracy );
|
||||
|
||||
if( !m_isDangling )
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::BUS;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
if( aPath )
|
||||
{
|
||||
if( m_connectionType != CONNECTION_TYPE::BUS )
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
|
||||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
{
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_type( aItemListByType, WIRE_END );
|
||||
it < aItemListByType.end() && it->GetType() == WIRE_END; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
DANGLING_END_ITEM& nextItem = *( ++it );
|
||||
|
||||
int accuracy = 1; // We have rounding issues with an accuracy of 0
|
||||
|
||||
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(),
|
||||
nextItem.GetPosition(), accuracy );
|
||||
|
||||
if( m_isDangling )
|
||||
continue;
|
||||
|
||||
m_connectionType = CONNECTION_TYPE::NET;
|
||||
|
||||
// Add the line to the connected items, since it won't be picked
|
||||
// up by a search of intersecting connection points
|
||||
|
@ -1157,16 +1195,9 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
|||
AddConnectionTo( *aPath, sch_item );
|
||||
sch_item->AddConnectionTo( *aPath, this );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !m_isDangling )
|
||||
break;
|
||||
}
|
||||
|
||||
if( m_isDangling )
|
||||
|
|
|
@ -306,8 +306,9 @@ public:
|
|||
|
||||
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsDangling() const override { return m_isDangling; }
|
||||
void SetIsDangling( bool aIsDangling ) { m_isDangling = aIsDangling; }
|
||||
|
|
|
@ -610,44 +610,56 @@ void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
|||
}
|
||||
|
||||
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
if( IsConnectable() )
|
||||
if( !IsConnectable() )
|
||||
return false;
|
||||
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_start );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_start; it++ )
|
||||
{
|
||||
bool previousStartState = m_startIsDangling;
|
||||
bool previousEndState = m_endIsDangling;
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
m_startIsDangling = m_endIsDangling = true;
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
for( DANGLING_END_ITEM item : aItemList )
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
if( m_start == item.GetPosition() )
|
||||
m_startIsDangling = false;
|
||||
|
||||
if( m_end == item.GetPosition() )
|
||||
m_endIsDangling = false;
|
||||
|
||||
if( !m_startIsDangling && !m_endIsDangling )
|
||||
break;
|
||||
}
|
||||
m_startIsDangling = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
return false;
|
||||
for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_end );
|
||||
it < aItemListByPos.end() && it->GetPosition() == m_end; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& item = *it;
|
||||
|
||||
if( item.GetItem() == this )
|
||||
continue;
|
||||
|
||||
if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
|
||||
|| ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
|
||||
{
|
||||
m_endIsDangling = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We only use the bus dangling state for automatic line starting, so we don't care if it
|
||||
// has changed or not (and returning true will result in extra work)
|
||||
if( IsBus() )
|
||||
return false;
|
||||
|
||||
return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -254,8 +254,9 @@ public:
|
|||
|
||||
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsStartDangling() const { return m_startIsDangling; }
|
||||
bool IsEndDangling() const { return m_endIsDangling; }
|
||||
|
|
|
@ -1361,36 +1361,46 @@ void SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath,
|
|||
{
|
||||
PROF_TIMER timer( __FUNCTION__ );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
auto getends =
|
||||
auto get_ends =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->IsConnectable() )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
};
|
||||
|
||||
auto update_state =
|
||||
[&]( SCH_ITEM* item )
|
||||
{
|
||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
||||
if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
|
||||
{
|
||||
if( aChangedHandler )
|
||||
(*aChangedHandler)( item );
|
||||
( *aChangedHandler )( item );
|
||||
}
|
||||
};
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
|
||||
getends( item );
|
||||
item->RunOnChildren( getends );
|
||||
get_ends( item );
|
||||
item->RunOnChildren( get_ends );
|
||||
}
|
||||
|
||||
PROF_TIMER sortTimer( "SCH_SCREEN::TestDanglingEnds pre-sort" );
|
||||
endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
sortTimer.Stop();
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
sortTimer.Show();
|
||||
|
||||
for( SCH_ITEM* item : Items() )
|
||||
{
|
||||
update_state( item );
|
||||
item->RunOnChildren( update_state );
|
||||
}
|
||||
|
||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||
timer.Show();
|
||||
}
|
||||
|
|
|
@ -1000,13 +1000,14 @@ void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
||||
changed |= sheetPin->UpdateDanglingState( aItemList );
|
||||
changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
|
@ -341,8 +341,9 @@ public:
|
|||
|
||||
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
|
||||
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
bool IsConnectable() const override { return true; }
|
||||
|
||||
|
|
|
@ -2055,8 +2055,9 @@ void SCH_SYMBOL::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
|
|||
}
|
||||
|
||||
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath )
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
|
@ -2067,8 +2068,12 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
|||
|
||||
VECTOR2I pos = m_transform.TransformCoordinate( pin->GetLocalPosition() ) + m_pos;
|
||||
|
||||
for( DANGLING_END_ITEM& each_item : aItemList )
|
||||
auto lower = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, pos );
|
||||
bool do_break = false;
|
||||
|
||||
for( auto it = lower; it < aItemListByPos.end() && it->GetPosition() == pos; it++ )
|
||||
{
|
||||
DANGLING_END_ITEM& each_item = *it;
|
||||
// Some people like to stack pins on top of each other in a symbol to indicate
|
||||
// internal connection. While technically connected, it is not particularly useful
|
||||
// to display them that way, so skip any pins that are in the same symbol as this
|
||||
|
@ -2084,17 +2089,15 @@ bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
|||
case WIRE_END:
|
||||
case NO_CONNECT_END:
|
||||
case JUNCTION_END:
|
||||
|
||||
if( pos == each_item.GetPosition() )
|
||||
pin->SetIsDangling( false );
|
||||
|
||||
pin->SetIsDangling( false );
|
||||
do_break = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( !pin->IsDangling() )
|
||||
if( do_break )
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -758,8 +758,9 @@ public:
|
|||
* @param aItemList is list of all #DANGLING_END_ITEM items to be tested.
|
||||
* @return true if any pin's state has changed.
|
||||
*/
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||
|
||||
VECTOR2I GetPinPhysicalPosition( const LIB_PIN* Pin ) const;
|
||||
|
||||
|
|
|
@ -379,12 +379,14 @@ SCH_LINE* SCH_LINE_WIRE_BUS_TOOL::doUnfoldBus( const wxString& aNet, const VECTO
|
|||
|
||||
getViewControls()->SetCrossHairCursorPosition( m_busUnfold.entry->GetEnd(), false );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType;
|
||||
|
||||
for( SCH_ITEM* item : screen->Items().Overlapping( m_busUnfold.entry->GetBoundingBox() ) )
|
||||
item->GetEndPoints( endPoints );
|
||||
item->GetEndPoints( endPointsByType );
|
||||
|
||||
m_busUnfold.entry->UpdateDanglingState( endPoints );
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->UpdateDanglingState( endPointsByType, endPointsByPos );
|
||||
m_busUnfold.entry->SetEndDangling( false );
|
||||
m_busUnfold.label->SetIsDangling( false );
|
||||
|
||||
|
|
|
@ -586,8 +586,14 @@ bool SCH_MOVE_TOOL::doMoveSelection( const TOOL_EVENT& aEvent, SCH_COMMIT* aComm
|
|||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->GetEndPoints( internalPoints );
|
||||
|
||||
std::vector<DANGLING_END_ITEM> endPointsByType = internalPoints;
|
||||
std::vector<DANGLING_END_ITEM> endPointsByPos = endPointsByType;
|
||||
DANGLING_END_ITEM_HELPER::sort_dangling_end_items( endPointsByType,
|
||||
endPointsByPos );
|
||||
|
||||
for( EDA_ITEM* item : selection )
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( internalPoints );
|
||||
static_cast<SCH_ITEM*>( item )->UpdateDanglingState( endPointsByType,
|
||||
endPointsByPos );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue