PNS: Allow width-caused DRC violations at start of route

Also fix an issue where DRC violations introduced by the
width change action could be committed in walk/shove mode.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/14805
This commit is contained in:
Jon Evans 2023-05-25 23:10:00 -04:00
parent fbe185b99b
commit 942ee13cd1
5 changed files with 78 additions and 26 deletions

View File

@ -619,6 +619,7 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM*
} }
aSizes.SetTrackWidth( trackWidth ); aSizes.SetTrackWidth( trackWidth );
aSizes.SetBoardMinTrackWidth( bds.m_TrackMinWidth );
aSizes.SetTrackWidthIsExplicit( !bds.m_UseConnectedTrackWidth || bds.m_TempOverrideTrackWidth ); aSizes.SetTrackWidthIsExplicit( !bds.m_UseConnectedTrackWidth || bds.m_TempOverrideTrackWidth );
int viaDiameter = bds.m_ViasMinSize; int viaDiameter = bds.m_ViasMinSize;

View File

@ -1156,6 +1156,16 @@ void LINE_PLACER::routeStep( const VECTOR2I& aP )
{ {
m_tail = prevTail; m_tail = prevTail;
m_head = prevHead; m_head = prevHead;
// If we fail to walk out of the initial point (no tail), instead of returning an empty
// line, return a zero-length line so that the user gets some feedback that routing is
// happening. This will get pruned later.
if( m_tail.PointCount() == 0 )
{
m_tail.Line().Append( m_p_start );
m_tail.Line().Append( m_p_start, true );
}
fail = true; fail = true;
} }
@ -1235,6 +1245,11 @@ const LINE LINE_PLACER::Trace() const
{ {
SHAPE_LINE_CHAIN l( m_tail.CLine() ); SHAPE_LINE_CHAIN l( m_tail.CLine() );
l.Append( m_head.CLine() ); l.Append( m_head.CLine() );
// Only simplify if we have more than two points, because if we have a zero-length seg as the
// only part of the trace, we don't want it to be removed at this stage (will be the case if
// the routing start point violates DRC due to track width in shove/walk mode, for example).
if( l.PointCount() > 2 )
l.Simplify(); l.Simplify();
LINE tmp( m_head ); LINE tmp( m_head );
@ -1515,11 +1530,13 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
aEndItem->SetNet( m_currentNet ); aEndItem->SetNet( m_currentNet );
} }
} }
}
// Collisions still prevent fixing unless "Allow DRC violations" is checked // Collisions still prevent fixing unless "Allow DRC violations" is checked
// Note that collisions can occur even in walk/shove modes if the beginning of the trace
// collides (for example if the starting track width is too high)
if( !Settings().AllowDRCViolations() && m_world->CheckColliding( &pl ) ) if( !Settings().AllowDRCViolations() && m_world->CheckColliding( &pl ) )
return false; return false;
}
const SHAPE_LINE_CHAIN& l = pl.CLine(); const SHAPE_LINE_CHAIN& l = pl.CLine();

View File

@ -316,6 +316,12 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
dummyStartLine.SetNet( aStartItem ? aStartItem->Net() : 0 ); dummyStartLine.SetNet( aStartItem ? aStartItem->Net() : 0 );
dummyStartLine.SetWidth( m_sizes.TrackWidth() ); dummyStartLine.SetWidth( m_sizes.TrackWidth() );
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
{
// If the only reason we collide is track width; it's better to allow the user to start
// anyway and just highlight the resulting collisions, so they can change width later.
dummyStartLine.SetWidth( m_sizes.BoardMinTrackWidth() );
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) ) if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
{ {
ITEM_SET dummyStartSet( &dummyStartLine ); ITEM_SET dummyStartSet( &dummyStartLine );
@ -330,6 +336,7 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
return false; return false;
} }
} }
}
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR ) else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
{ {
if( !aStartItem ) if( !aStartItem )
@ -369,6 +376,14 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
dummyStartLineB.SetNet( dpPair.PrimP()->Net() ); dummyStartLineB.SetNet( dpPair.PrimP()->Net() );
dummyStartLineB.SetWidth( m_sizes.DiffPairWidth() ); dummyStartLineB.SetWidth( m_sizes.DiffPairWidth() );
if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
|| m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
{
// If the only reason we collide is track width; it's better to allow the user to start
// anyway and just highlight the resulting collisions, so they can change width later.
dummyStartLineA.SetWidth( m_sizes.BoardMinTrackWidth() );
dummyStartLineB.SetWidth( m_sizes.BoardMinTrackWidth() );
if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T ) if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
|| m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) ) || m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
{ {
@ -386,6 +401,7 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
return false; return false;
} }
} }
}
return true; return true;
} }
@ -696,7 +712,6 @@ void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent, bool aDragging )
if( !aNode ) if( !aNode )
return; return;
if( Settings().Mode() == RM_MarkObstacles || m_forceMarkObstaclesMode )
markViolations( aNode, aCurrent, removed ); markViolations( aNode, aCurrent, removed );
aNode->GetUpdatedItems( removed, added ); aNode->GetUpdatedItems( removed, added );

View File

@ -73,6 +73,9 @@ public:
bool TrackWidthIsExplicit() const { return m_trackWidthIsExplicit; } bool TrackWidthIsExplicit() const { return m_trackWidthIsExplicit; }
void SetTrackWidthIsExplicit( bool aIsExplicit ) { m_trackWidthIsExplicit = aIsExplicit; } void SetTrackWidthIsExplicit( bool aIsExplicit ) { m_trackWidthIsExplicit = aIsExplicit; }
int BoardMinTrackWidth() const { return m_boardMinTrackWidth; }
void SetBoardMinTrackWidth( int aWidth ) { m_boardMinTrackWidth = aWidth; }
int DiffPairWidth() const { return m_diffPairWidth; } int DiffPairWidth() const { return m_diffPairWidth; }
int DiffPairGap() const { return m_diffPairGap; } int DiffPairGap() const { return m_diffPairGap; }
@ -135,6 +138,7 @@ private:
int m_minClearance; int m_minClearance;
int m_trackWidth; int m_trackWidth;
bool m_trackWidthIsExplicit; bool m_trackWidthIsExplicit;
int m_boardMinTrackWidth;
VIATYPE m_viaType; VIATYPE m_viaType;
int m_viaDiameter; int m_viaDiameter;

View File

@ -214,7 +214,22 @@ void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN_BASE* aL, KIGFX:
gal->SetIsFill( false ); gal->SetIsFill( false );
for( int s = 0; s < aL->GetSegmentCount(); s++ ) for( int s = 0; s < aL->GetSegmentCount(); s++ )
gal->DrawLine( aL->GetSegment( s ).A, aL->GetSegment( s ).B ); {
SEG seg = aL->GetSegment( s );
if( seg.A == seg.B )
{
gal->SetIsFill( true );
gal->SetIsStroke( false );
gal->DrawCircle( seg.A, gal->GetLineWidth() / 2 );
gal->SetIsFill( false );
gal->SetIsStroke( true );
}
else
{
gal->DrawLine( seg.A, seg.B );
}
}
const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL ); const SHAPE_LINE_CHAIN* lineChain = dynamic_cast<const SHAPE_LINE_CHAIN*>( aL );