7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 08:21:39 +00:00

Implement dnagling wire to bus entry ERC

Also, rename the dangling flag/getter to match the flag in SCH_LINE for
consistency.
This commit is contained in:
Ian McInerney 2025-01-03 14:58:57 +00:00
parent d847e2bd92
commit e845db1977
4 changed files with 71 additions and 43 deletions

View File

@ -3776,33 +3776,61 @@ bool CONNECTION_GRAPH::ercCheckDanglingWireEndpoints( const CONNECTION_SUBGRAPH*
for( SCH_ITEM* item : aSubgraph->m_items )
{
if( item->Type() != SCH_LINE_T || item->GetLayer() != LAYER_WIRE )
if( item->GetLayer() != LAYER_WIRE )
continue;
SCH_LINE* line = static_cast<SCH_LINE*>( item );
if( line->IsGraphicLine() )
continue;
auto report_error = [&]( VECTOR2I& location )
if( item->Type() == SCH_LINE_T )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNCONNECTED_WIRE_ENDPOINT );
SCH_LINE* line = static_cast<SCH_LINE*>( item );
ercItem->SetItems( line );
ercItem->SetSheetSpecificPath( sheet );
ercItem->SetErrorMessage( _( "Unconnected wire endpoint" ) );
if( line->IsGraphicLine() )
continue;
SCH_MARKER* marker = new SCH_MARKER( ercItem, location );
sheet.LastScreen()->Append( marker );
auto report_error = [&]( VECTOR2I& location )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNCONNECTED_WIRE_ENDPOINT );
err_count++;
};
ercItem->SetItems( line );
ercItem->SetSheetSpecificPath( sheet );
ercItem->SetErrorMessage( _( "Unconnected wire endpoint" ) );
if( line->IsStartDangling() )
report_error( line->GetConnectionPoints()[0] );
SCH_MARKER* marker = new SCH_MARKER( ercItem, location );
sheet.LastScreen()->Append( marker );
err_count++;
};
if( line->IsStartDangling() )
report_error( line->GetConnectionPoints()[0] );
if( line->IsEndDangling() )
report_error( line->GetConnectionPoints()[1] );
}
else if( item->Type() == SCH_BUS_WIRE_ENTRY_T )
{
SCH_BUS_WIRE_ENTRY* entry = static_cast<SCH_BUS_WIRE_ENTRY*>( item );
auto report_error = [&]( VECTOR2I& location )
{
std::shared_ptr<ERC_ITEM> ercItem = ERC_ITEM::Create( ERCE_UNCONNECTED_WIRE_ENDPOINT );
ercItem->SetItems( entry );
ercItem->SetSheetSpecificPath( sheet );
ercItem->SetErrorMessage( _( "Unconnected wire to bus entry" ) );
SCH_MARKER* marker = new SCH_MARKER( ercItem, location );
sheet.LastScreen()->Append( marker );
err_count++;
};
if( entry->IsStartDangling() )
report_error( entry->GetConnectionPoints()[0] );
if( entry->IsEndDangling() )
report_error( entry->GetConnectionPoints()[1] );
}
if( line->IsEndDangling() )
report_error( line->GetConnectionPoints()[1] );
}
return err_count > 0;

View File

@ -56,7 +56,7 @@ SCH_BUS_ENTRY_BASE::SCH_BUS_ENTRY_BASE( KICAD_T aType, const VECTOR2I& pos, bool
if( aFlipY )
m_size.y *= -1;
m_isDanglingStart = m_isDanglingEnd = true;
m_isStartDangling = m_isEndDangling = true;
m_lastResolvedWidth = schIUScale.MilsToIU( DEFAULT_WIRE_WIDTH_MILS );
m_lastResolvedLineStyle = LINE_STYLE::SOLID;
@ -316,10 +316,10 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
std::vector<DANGLING_END_ITEM>& aItemListByPos,
const SCH_SHEET_PATH* aPath )
{
bool previousStateStart = m_isDanglingStart;
bool previousStateEnd = m_isDanglingEnd;
bool previousStateStart = m_isStartDangling;
bool previousStateEnd = m_isEndDangling;
m_isDanglingStart = m_isDanglingEnd = true;
m_isStartDangling = m_isEndDangling = true;
// Store the connection type and state for the start (0) and end (1)
bool has_wire[2] = { false };
@ -362,13 +362,13 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
// A bus-wire entry is connected at both ends if it has a bus and a wire on its
// ends. Otherwise, we connect only one end (in the case of a wire-wire or bus-bus)
if( ( has_wire[0] && has_bus[1] ) || ( has_wire[1] && has_bus[0] ) )
m_isDanglingEnd = m_isDanglingStart = false;
m_isEndDangling = m_isStartDangling = false;
else if( has_wire[0] || has_bus[0] )
m_isDanglingStart = false;
m_isStartDangling = false;
else if( has_wire[1] || has_bus[1] )
m_isDanglingEnd = false;
m_isEndDangling = false;
return (previousStateStart != m_isDanglingStart) || (previousStateEnd != m_isDanglingEnd);
return (previousStateStart != m_isStartDangling) || (previousStateEnd != m_isEndDangling);
}
@ -376,10 +376,10 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
std::vector<DANGLING_END_ITEM>& aItemListByPos,
const SCH_SHEET_PATH* aPath )
{
bool previousStateStart = m_isDanglingStart;
bool previousStateEnd = m_isDanglingEnd;
bool previousStateStart = m_isStartDangling;
bool previousStateEnd = m_isEndDangling;
m_isDanglingStart = m_isDanglingEnd = true;
m_isStartDangling = m_isEndDangling = true;
// TODO: filter using get_lower as we only use one item type
for( unsigned ii = 0; ii < aItemListByType.size(); ii++ )
@ -397,9 +397,9 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
DANGLING_END_ITEM& nextItem = aItemListByType[++ii];
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), m_pos ) )
m_isDanglingStart = false;
m_isStartDangling = false;
if( IsPointOnSegment( item.GetPosition(), nextItem.GetPosition(), GetEnd() ) )
m_isDanglingEnd = false;
m_isEndDangling = false;
}
break;
@ -408,13 +408,13 @@ bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aIt
}
}
return (previousStateStart != m_isDanglingStart) || (previousStateEnd != m_isDanglingEnd);
return (previousStateStart != m_isStartDangling) || (previousStateEnd != m_isEndDangling);
}
bool SCH_BUS_ENTRY_BASE::IsDangling() const
{
return m_isDanglingStart || m_isDanglingEnd;
return m_isStartDangling || m_isEndDangling;
}

View File

@ -40,10 +40,10 @@ public:
SCH_BUS_ENTRY_BASE( KICAD_T aType, const VECTOR2I& pos = VECTOR2I( 0, 0 ),
bool aFlipY = false );
bool IsDanglingStart() const { return m_isDanglingStart; }
bool IsDanglingEnd() const { return m_isDanglingEnd; }
bool IsStartDangling() const { return m_isStartDangling; }
bool IsEndDangling() const { return m_isEndDangling; }
void SetEndDangling( bool aDanglingState ) { m_isDanglingEnd = aDanglingState; }
void SetEndDangling( bool aDanglingState ) { m_isEndDangling = aDanglingState; }
// Do not create a copy constructor. The one generated by the compiler is adequate.
@ -117,8 +117,8 @@ public:
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
bool IsPointClickableAnchor( const VECTOR2I& aPos ) const override
{
return ( GetPosition() == aPos && IsDanglingStart() )
|| ( GetEnd() == aPos && IsDanglingEnd() );
return ( GetPosition() == aPos && IsStartDangling() )
|| ( GetEnd() == aPos && IsEndDangling() );
}
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
@ -150,8 +150,8 @@ private:
protected:
VECTOR2I m_pos;
VECTOR2I m_size;
bool m_isDanglingStart;
bool m_isDanglingEnd;
bool m_isStartDangling;
bool m_isEndDangling;
STROKE_PARAMS m_stroke;
// If real-time connectivity gets disabled (due to being too slow on a particular

View File

@ -2882,13 +2882,13 @@ void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
m_gal->SetStrokeColor( color.Brightened( 0.3 ) );
m_gal->SetLineWidth( m_schSettings.GetDanglingIndicatorThickness() );
if( aEntry->IsDanglingStart() )
if( aEntry->IsStartDangling() )
{
m_gal->DrawCircle( aEntry->GetPosition(),
aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );
}
if( aEntry->IsDanglingEnd() )
if( aEntry->IsEndDangling() )
{
m_gal->DrawCircle( aEntry->GetEnd(),
aEntry->GetPenWidth() + KiROUND( TARGET_BUSENTRY_RADIUS / 2.0 ) );