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();
|
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_page = new PAGE_INFO( PAGE_INFO::Custom );
|
||||||
m_titleBlock = new TITLE_BLOCK;
|
m_titleBlock = new TITLE_BLOCK;
|
||||||
|
@ -399,7 +399,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||||
pin->SetNameTextSize( 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 );
|
symbol->AddDrawItem( pin );
|
||||||
|
|
||||||
pin = new LIB_PIN( symbol );
|
pin = new LIB_PIN( symbol );
|
||||||
|
@ -413,7 +413,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||||
pin->SetNameTextSize( 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 );
|
symbol->AddDrawItem( pin );
|
||||||
|
|
||||||
pin = new LIB_PIN( symbol );
|
pin = new LIB_PIN( symbol );
|
||||||
|
@ -427,7 +427,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||||
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
pin->SetNumberTextSize( schIUScale.MilsToIU( 50 ) );
|
||||||
pin->SetNameTextSize( 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 );
|
symbol->AddDrawItem( pin );
|
||||||
|
|
||||||
addItem( symbol );
|
addItem( symbol );
|
||||||
|
@ -452,16 +452,19 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
|
||||||
if( sch_item && sch_item->IsConnectable() )
|
if( sch_item && sch_item->IsConnectable() )
|
||||||
{
|
{
|
||||||
sch_item->AutoplaceFields( nullptr, false );
|
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 )
|
for( EDA_ITEM* item : m_previewItems )
|
||||||
{
|
{
|
||||||
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
|
SCH_ITEM* sch_item = dynamic_cast<SCH_ITEM*>( item );
|
||||||
|
|
||||||
if( sch_item && sch_item->IsConnectable() )
|
if( sch_item && sch_item->IsConnectable() )
|
||||||
sch_item->UpdateDanglingState( endPoints, nullptr );
|
sch_item->UpdateDanglingState( endPointsByType, endPointsByPos, nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomFitPreview();
|
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,
|
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath )
|
||||||
{
|
{
|
||||||
bool previousStateStart = m_isDanglingStart;
|
bool previousStateStart = m_isDanglingStart;
|
||||||
bool previousStateEnd = m_isDanglingEnd;
|
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_wire[2] = { false };
|
||||||
bool has_bus[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 )
|
if( item.GetItem() == this )
|
||||||
continue;
|
continue;
|
||||||
|
@ -344,7 +345,7 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
|
||||||
case BUS_END:
|
case BUS_END:
|
||||||
{
|
{
|
||||||
// The bus has created 2 DANGLING_END_ITEMs, one per 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 ) )
|
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||||
has_bus[0] = true;
|
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,
|
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath )
|
||||||
{
|
{
|
||||||
bool previousStateStart = m_isDanglingStart;
|
bool previousStateStart = m_isDanglingStart;
|
||||||
bool previousStateEnd = m_isDanglingEnd;
|
bool previousStateEnd = m_isDanglingEnd;
|
||||||
|
|
||||||
m_isDanglingStart = m_isDanglingEnd = true;
|
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 )
|
if( item.GetItem() == this )
|
||||||
continue;
|
continue;
|
||||||
|
@ -391,7 +394,7 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
|
||||||
case BUS_END:
|
case BUS_END:
|
||||||
{
|
{
|
||||||
// The bus has created 2 DANGLING_END_ITEMs, one per 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 ) )
|
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
|
||||||
m_isDanglingStart = false;
|
m_isDanglingStart = false;
|
||||||
|
|
|
@ -195,8 +195,9 @@ public:
|
||||||
|
|
||||||
BITMAPS GetMenuImage() const override;
|
BITMAPS GetMenuImage() const override;
|
||||||
|
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
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
|
* Pointer to the bus item (usually a bus wire) connected to this bus-wire
|
||||||
|
@ -240,8 +241,9 @@ public:
|
||||||
|
|
||||||
BITMAPS GetMenuImage() const override;
|
BITMAPS GetMenuImage() const override;
|
||||||
|
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
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
|
* 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;
|
} _SCH_ITEM_DESC;
|
||||||
|
|
||||||
IMPLEMENT_ENUM_TO_WXANY( SCH_LAYER_ID )
|
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;
|
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
|
* 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
|
* 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.
|
* @param aSheet is the sheet path to update connections for.
|
||||||
* @return True if the dangling state has changed from it's current setting.
|
* @return True if the dangling state has changed from it's current setting.
|
||||||
*/
|
*/
|
||||||
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath = nullptr )
|
||||||
{
|
{
|
||||||
return false;
|
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,
|
bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath )
|
||||||
{
|
{
|
||||||
bool previousState = m_isDangling;
|
bool previousState = m_isDangling;
|
||||||
m_isDangling = true;
|
VECTOR2I text_pos = GetTextPos();
|
||||||
|
m_isDangling = true;
|
||||||
m_connectionType = CONNECTION_TYPE::NONE;
|
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 )
|
if( item.GetItem() == this )
|
||||||
continue;
|
continue;
|
||||||
|
@ -1121,33 +1124,68 @@ bool SCH_LABEL_BASE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemL
|
||||||
case LABEL_END:
|
case LABEL_END:
|
||||||
case SHEET_LABEL_END:
|
case SHEET_LABEL_END:
|
||||||
case NO_CONNECT_END:
|
case NO_CONNECT_END:
|
||||||
if( GetTextPos() == item.GetPosition() )
|
if( text_pos == item.GetPosition() )
|
||||||
{
|
{
|
||||||
m_isDangling = false;
|
m_isDangling = false;
|
||||||
|
|
||||||
if( aPath && item.GetType() != PIN_END )
|
if( aPath && item.GetType() != PIN_END )
|
||||||
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
AddConnectionTo( *aPath, static_cast<SCH_ITEM*>( item.GetItem() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BUS_END:
|
default: break;
|
||||||
m_connectionType = CONNECTION_TYPE::BUS;
|
}
|
||||||
KI_FALLTHROUGH;
|
|
||||||
|
|
||||||
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(),
|
m_isDangling = !TestSegmentHit( text_pos, item.GetPosition(), nextItem.GetPosition(),
|
||||||
nextItem.GetPosition(), accuracy );
|
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 )
|
auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
|
||||||
m_connectionType = CONNECTION_TYPE::NET;
|
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
|
// Add the line to the connected items, since it won't be picked
|
||||||
// up by a search of intersecting connection points
|
// 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 );
|
AddConnectionTo( *aPath, sch_item );
|
||||||
sch_item->AddConnectionTo( *aPath, this );
|
sch_item->AddConnectionTo( *aPath, this );
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( !m_isDangling )
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_isDangling )
|
if( m_isDangling )
|
||||||
|
|
|
@ -306,8 +306,9 @@ public:
|
||||||
|
|
||||||
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
|
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
|
||||||
|
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||||
|
|
||||||
bool IsDangling() const override { return m_isDangling; }
|
bool IsDangling() const override { return m_isDangling; }
|
||||||
void SetIsDangling( bool aIsDangling ) { m_isDangling = aIsDangling; }
|
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,
|
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
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;
|
DANGLING_END_ITEM& item = *it;
|
||||||
bool previousEndState = m_endIsDangling;
|
|
||||||
|
|
||||||
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 )
|
m_startIsDangling = false;
|
||||||
continue;
|
break;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
|
||||||
|
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||||
|
|
||||||
bool IsStartDangling() const { return m_startIsDangling; }
|
bool IsStartDangling() const { return m_startIsDangling; }
|
||||||
bool IsEndDangling() const { return m_endIsDangling; }
|
bool IsEndDangling() const { return m_endIsDangling; }
|
||||||
|
|
|
@ -1361,36 +1361,46 @@ void SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath,
|
||||||
{
|
{
|
||||||
PROF_TIMER timer( __FUNCTION__ );
|
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 )
|
[&]( SCH_ITEM* item )
|
||||||
{
|
{
|
||||||
if( item->IsConnectable() )
|
if( item->IsConnectable() )
|
||||||
item->GetEndPoints( endPoints );
|
item->GetEndPoints( endPointsByType );
|
||||||
};
|
};
|
||||||
|
|
||||||
auto update_state =
|
auto update_state =
|
||||||
[&]( SCH_ITEM* item )
|
[&]( SCH_ITEM* item )
|
||||||
{
|
{
|
||||||
if( item->UpdateDanglingState( endPoints, aPath ) )
|
if( item->UpdateDanglingState( endPointsByType, endPointsByPos, aPath ) )
|
||||||
{
|
{
|
||||||
if( aChangedHandler )
|
if( aChangedHandler )
|
||||||
(*aChangedHandler)( item );
|
( *aChangedHandler )( item );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for( SCH_ITEM* item : Items() )
|
for( SCH_ITEM* item : Items() )
|
||||||
{
|
{
|
||||||
|
get_ends( item );
|
||||||
getends( item );
|
item->RunOnChildren( get_ends );
|
||||||
item->RunOnChildren( getends );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() )
|
for( SCH_ITEM* item : Items() )
|
||||||
{
|
{
|
||||||
update_state( item );
|
update_state( item );
|
||||||
item->RunOnChildren( update_state );
|
item->RunOnChildren( update_state );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
if( wxLog::IsAllowedTraceMask( DanglingProfileMask ) )
|
||||||
timer.Show();
|
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,
|
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath )
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
for( SCH_SHEET_PIN* sheetPin : m_pins )
|
||||||
changed |= sheetPin->UpdateDanglingState( aItemList );
|
changed |= sheetPin->UpdateDanglingState( aItemListByType, aItemListByPos );
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,8 +341,9 @@ public:
|
||||||
|
|
||||||
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
|
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
|
||||||
|
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||||
|
|
||||||
bool IsConnectable() const override { return true; }
|
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,
|
bool SCH_SYMBOL::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath )
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath )
|
||||||
{
|
{
|
||||||
bool changed = false;
|
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;
|
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
|
// 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
|
// 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
|
// 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 WIRE_END:
|
||||||
case NO_CONNECT_END:
|
case NO_CONNECT_END:
|
||||||
case JUNCTION_END:
|
case JUNCTION_END:
|
||||||
|
pin->SetIsDangling( false );
|
||||||
if( pos == each_item.GetPosition() )
|
do_break = true;
|
||||||
pin->SetIsDangling( false );
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !pin->IsDangling() )
|
if( do_break )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -758,8 +758,9 @@ public:
|
||||||
* @param aItemList is list of all #DANGLING_END_ITEM items to be tested.
|
* @param aItemList is list of all #DANGLING_END_ITEM items to be tested.
|
||||||
* @return true if any pin's state has changed.
|
* @return true if any pin's state has changed.
|
||||||
*/
|
*/
|
||||||
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
|
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
|
||||||
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
std::vector<DANGLING_END_ITEM>& aItemListByPos,
|
||||||
|
const SCH_SHEET_PATH* aPath = nullptr ) override;
|
||||||
|
|
||||||
VECTOR2I GetPinPhysicalPosition( const LIB_PIN* Pin ) const;
|
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 );
|
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() ) )
|
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.entry->SetEndDangling( false );
|
||||||
m_busUnfold.label->SetIsDangling( 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 )
|
for( EDA_ITEM* item : selection )
|
||||||
static_cast<SCH_ITEM*>( item )->GetEndPoints( internalPoints );
|
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 )
|
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