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:
parent
fbe185b99b
commit
942ee13cd1
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1224,10 +1234,10 @@ bool LINE_PLACER::route( const VECTOR2I& aP )
|
||||||
{
|
{
|
||||||
routeStep( aP );
|
routeStep( aP );
|
||||||
|
|
||||||
if (!m_head.PointCount() )
|
if( !m_head.PointCount() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return m_head.CPoint(-1) == aP;
|
return m_head.CPoint( -1 ) == aP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1235,7 +1245,12 @@ 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() );
|
||||||
l.Simplify();
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
LINE tmp( m_head );
|
LINE tmp( m_head );
|
||||||
|
|
||||||
|
@ -1515,12 +1530,14 @@ 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
|
|
||||||
if( !Settings().AllowDRCViolations() && m_world->CheckColliding( &pl ) )
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
const SHAPE_LINE_CHAIN& l = pl.CLine();
|
const SHAPE_LINE_CHAIN& l = pl.CLine();
|
||||||
|
|
||||||
if( !l.SegmentCount() )
|
if( !l.SegmentCount() )
|
||||||
|
|
|
@ -318,16 +318,23 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
|
|
||||||
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
|
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
|
||||||
{
|
{
|
||||||
ITEM_SET dummyStartSet( &dummyStartLine );
|
// If the only reason we collide is track width; it's better to allow the user to start
|
||||||
NODE::ITEM_VECTOR highlightedItems;
|
// anyway and just highlight the resulting collisions, so they can change width later.
|
||||||
|
dummyStartLine.SetWidth( m_sizes.BoardMinTrackWidth() );
|
||||||
|
|
||||||
markViolations( m_world.get(), dummyStartSet, highlightedItems );
|
if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
|
||||||
|
{
|
||||||
|
ITEM_SET dummyStartSet( &dummyStartLine );
|
||||||
|
NODE::ITEM_VECTOR highlightedItems;
|
||||||
|
|
||||||
for( ITEM* item : highlightedItems )
|
markViolations( m_world.get(), dummyStartSet, highlightedItems );
|
||||||
m_iface->HideItem( item );
|
|
||||||
|
|
||||||
SetFailureReason( _( "The routing start point violates DRC." ) );
|
for( ITEM* item : highlightedItems )
|
||||||
return false;
|
m_iface->HideItem( item );
|
||||||
|
|
||||||
|
SetFailureReason( _( "The routing start point violates DRC." ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
|
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
|
||||||
|
@ -372,18 +379,27 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
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 ) )
|
||||||
{
|
{
|
||||||
ITEM_SET dummyStartSet;
|
// If the only reason we collide is track width; it's better to allow the user to start
|
||||||
NODE::ITEM_VECTOR highlightedItems;
|
// anyway and just highlight the resulting collisions, so they can change width later.
|
||||||
|
dummyStartLineA.SetWidth( m_sizes.BoardMinTrackWidth() );
|
||||||
|
dummyStartLineB.SetWidth( m_sizes.BoardMinTrackWidth() );
|
||||||
|
|
||||||
dummyStartSet.Add( dummyStartLineA );
|
if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
|
||||||
dummyStartSet.Add( dummyStartLineB );
|
|| m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
|
||||||
markViolations( m_world.get(), dummyStartSet, highlightedItems );
|
{
|
||||||
|
ITEM_SET dummyStartSet;
|
||||||
|
NODE::ITEM_VECTOR highlightedItems;
|
||||||
|
|
||||||
for( ITEM* item : highlightedItems )
|
dummyStartSet.Add( dummyStartLineA );
|
||||||
m_iface->HideItem( item );
|
dummyStartSet.Add( dummyStartLineB );
|
||||||
|
markViolations( m_world.get(), dummyStartSet, highlightedItems );
|
||||||
|
|
||||||
SetFailureReason( _( "The routing start point violates DRC." ) );
|
for( ITEM* item : highlightedItems )
|
||||||
return false;
|
m_iface->HideItem( item );
|
||||||
|
|
||||||
|
SetFailureReason( _( "The routing start point violates DRC." ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,8 +712,7 @@ 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 );
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue