Better error messages when routing can't be started.
Fixes https://gitlab.com/kicad/code/kicad/issues/6541
This commit is contained in:
parent
f6578da824
commit
02cd8c99cd
|
@ -403,7 +403,7 @@ bool DIFF_PAIR_PLACER::SetLayer( int aLayer )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
OPT_VECTOR2I DIFF_PAIR_PLACER::getDanglingAnchor( NODE* aNode, ITEM* aItem )
|
OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem )
|
||||||
{
|
{
|
||||||
switch( aItem->Kind() )
|
switch( aItem->Kind() )
|
||||||
{
|
{
|
||||||
|
@ -429,20 +429,19 @@ OPT_VECTOR2I DIFF_PAIR_PLACER::getDanglingAnchor( NODE* aNode, ITEM* aItem )
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return OPT_VECTOR2I();
|
return OPT_VECTOR2I();
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem,
|
bool DIFF_PAIR_PLACER::FindDpPrimitivePair( NODE* aWorld, const VECTOR2I& aP, ITEM* aItem,
|
||||||
DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
|
DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
|
||||||
{
|
{
|
||||||
int netP, netN;
|
int netP, netN;
|
||||||
|
|
||||||
wxLogTrace( "PNS", "world %p", m_world );
|
wxLogTrace( "PNS", "world %p", aWorld );
|
||||||
|
|
||||||
bool result = m_world->GetRuleResolver()->DpNetPair( aItem, netP, netN );
|
bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
|
||||||
|
|
||||||
if( !result )
|
if( !result )
|
||||||
{
|
{
|
||||||
|
@ -460,7 +459,7 @@ bool DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem,
|
||||||
|
|
||||||
wxLogTrace( "PNS", "result %d", !!result );
|
wxLogTrace( "PNS", "result %d", !!result );
|
||||||
|
|
||||||
OPT_VECTOR2I refAnchor = getDanglingAnchor( m_currentNode, aItem );
|
OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
|
||||||
ITEM* primRef = aItem;
|
ITEM* primRef = aItem;
|
||||||
|
|
||||||
wxLogTrace( "PNS", "refAnchor %p", aItem );
|
wxLogTrace( "PNS", "refAnchor %p", aItem );
|
||||||
|
@ -478,7 +477,7 @@ bool DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem,
|
||||||
|
|
||||||
std::set<ITEM*> coupledItems;
|
std::set<ITEM*> coupledItems;
|
||||||
|
|
||||||
m_currentNode->AllItemsInNet( coupledNet, coupledItems );
|
aWorld->AllItemsInNet( coupledNet, coupledItems );
|
||||||
double bestDist = std::numeric_limits<double>::max();
|
double bestDist = std::numeric_limits<double>::max();
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
|
@ -486,7 +485,7 @@ bool DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem,
|
||||||
{
|
{
|
||||||
if( item->Kind() == aItem->Kind() )
|
if( item->Kind() == aItem->Kind() )
|
||||||
{
|
{
|
||||||
OPT_VECTOR2I anchor = getDanglingAnchor( m_currentNode, item );
|
OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
|
||||||
if( !anchor )
|
if( !anchor )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -524,7 +523,7 @@ bool DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem,
|
||||||
{
|
{
|
||||||
*aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
|
*aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
|
||||||
"for coupled net \"%s\"." ),
|
"for coupled net \"%s\"." ),
|
||||||
m_world->GetRuleResolver()->NetName( coupledNet ) );
|
aWorld->GetRuleResolver()->NetName( coupledNet ) );
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -548,49 +547,16 @@ int DIFF_PAIR_PLACER::gap() const
|
||||||
bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||||
{
|
{
|
||||||
VECTOR2I p( aP );
|
VECTOR2I p( aP );
|
||||||
wxString msg;
|
|
||||||
|
|
||||||
if( !aStartItem )
|
|
||||||
{
|
|
||||||
Router()->SetFailureReason( _( "Can't start a differential pair "
|
|
||||||
" in the middle of nowhere." ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setWorld( Router()->GetWorld() );
|
setWorld( Router()->GetWorld() );
|
||||||
m_currentNode = m_world;
|
m_currentNode = m_world;
|
||||||
|
|
||||||
if( !findDpPrimitivePair( aP, aStartItem, m_start, &msg ) )
|
if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start ) )
|
||||||
{
|
|
||||||
Router()->SetFailureReason( msg );
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
m_netP = m_start.PrimP()->Net();
|
m_netP = m_start.PrimP()->Net();
|
||||||
m_netN = m_start.PrimN()->Net();
|
m_netN = m_start.PrimN()->Net();
|
||||||
|
|
||||||
#if 0
|
|
||||||
// FIXME: this also needs to be factored out but not so important right now
|
|
||||||
// Check if the current track/via gap & track width settings are violated
|
|
||||||
BOARD* brd = NULL; // FIXME Router()->GetBoard();
|
|
||||||
NETCLASSPTR netclassP = brd->FindNet( m_netP )->GetNetClass();
|
|
||||||
NETCLASSPTR netclassN = brd->FindNet( m_netN )->GetNetClass();
|
|
||||||
int clearance = std::min( m_sizes.DiffPairGap(), m_sizes.DiffPairViaGap() );
|
|
||||||
|
|
||||||
if( clearance < netclassP->GetClearance() || clearance < netclassN->GetClearance() )
|
|
||||||
{
|
|
||||||
Router()->SetFailureReason( _( "Current track/via gap setting violates "
|
|
||||||
"design rules for this net." ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( m_sizes.DiffPairWidth() < brd->GetDesignSettings().m_TrackMinWidth )
|
|
||||||
{
|
|
||||||
Router()->SetFailureReason( _( "Current track width setting violates design rules." ) );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_currentStart = p;
|
m_currentStart = p;
|
||||||
m_currentEnd = p;
|
m_currentEnd = p;
|
||||||
m_placingVia = false;
|
m_placingVia = false;
|
||||||
|
@ -646,7 +612,7 @@ bool DIFF_PAIR_PLACER::routeHead( const VECTOR2I& aP )
|
||||||
|
|
||||||
DP_PRIMITIVE_PAIR target;
|
DP_PRIMITIVE_PAIR target;
|
||||||
|
|
||||||
if( findDpPrimitivePair( aP, m_currentEndItem, target ) )
|
if( FindDpPrimitivePair( m_currentNode, aP, m_currentEndItem, target ) )
|
||||||
{
|
{
|
||||||
gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
|
gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
|
||||||
m_snapOnTarget = true;
|
m_snapOnTarget = true;
|
||||||
|
|
|
@ -58,6 +58,9 @@ public:
|
||||||
DIFF_PAIR_PLACER( ROUTER* aRouter );
|
DIFF_PAIR_PLACER( ROUTER* aRouter );
|
||||||
~DIFF_PAIR_PLACER();
|
~DIFF_PAIR_PLACER();
|
||||||
|
|
||||||
|
static bool FindDpPrimitivePair( NODE* aWorld, const VECTOR2I& aP, ITEM* aItem,
|
||||||
|
DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg = nullptr );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Start()
|
* Function Start()
|
||||||
*
|
*
|
||||||
|
@ -235,9 +238,8 @@ private:
|
||||||
|
|
||||||
const VIA makeVia ( const VECTOR2I& aP, int aNet );
|
const VIA makeVia ( const VECTOR2I& aP, int aNet );
|
||||||
|
|
||||||
bool findDpPrimitivePair( const VECTOR2I& aP, ITEM* aItem, DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg = nullptr );
|
bool attemptWalk( NODE* aNode, DIFF_PAIR* aCurrent, DIFF_PAIR& aWalk, bool aPFirst,
|
||||||
OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem );
|
bool aWindCw, bool aSolidsOnly );
|
||||||
bool attemptWalk( NODE* aNode, DIFF_PAIR* aCurrent, DIFF_PAIR& aWalk, bool aPFirst, bool aWindCw, bool aSolidsOnly );
|
|
||||||
bool propagateDpHeadForces ( const VECTOR2I& aP, VECTOR2I& aNewP );
|
bool propagateDpHeadForces ( const VECTOR2I& aP, VECTOR2I& aNewP );
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include <pcb_painter.h>
|
#include <pcb_painter.h>
|
||||||
#include <pcbnew_settings.h>
|
#include <pcbnew_settings.h>
|
||||||
|
#include <pad.h>
|
||||||
|
#include <zone.h>
|
||||||
|
|
||||||
#include <geometry/shape.h>
|
#include <geometry/shape.h>
|
||||||
|
|
||||||
|
@ -169,6 +171,7 @@ bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM_SET aStartItems, int aDragM
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem, int aLayer )
|
bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem, int aLayer )
|
||||||
{
|
{
|
||||||
if( Settings().CanViolateDRC() && Settings().Mode() == RM_MarkObstacles )
|
if( Settings().CanViolateDRC() && Settings().Mode() == RM_MarkObstacles )
|
||||||
|
@ -179,12 +182,69 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
for( ITEM* item : candidates.Items() )
|
for( ITEM* item : candidates.Items() )
|
||||||
{
|
{
|
||||||
if( !item->IsRoutable() && item->Layers().Overlaps( aLayer ) )
|
if( !item->IsRoutable() && item->Layers().Overlaps( aLayer ) )
|
||||||
|
{
|
||||||
|
BOARD_ITEM* parent = item->Parent();
|
||||||
|
|
||||||
|
switch( parent->Type() )
|
||||||
|
{
|
||||||
|
case PCB_PAD_T:
|
||||||
|
{
|
||||||
|
PAD* pad = static_cast<PAD*>( parent );
|
||||||
|
|
||||||
|
if( pad->GetAttribute() == PAD_ATTRIB_NPTH )
|
||||||
|
SetFailureReason( _( "Cannot start routing from a non-plated hole." ) );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCB_ZONE_T:
|
||||||
|
case PCB_FP_ZONE_T:
|
||||||
|
{
|
||||||
|
ZONE* zone = static_cast<ZONE*>( parent );
|
||||||
|
|
||||||
|
if( !zone->GetZoneName().IsEmpty() )
|
||||||
|
{
|
||||||
|
SetFailureReason( wxString::Format( _( "Rule area '%s' disallows tracks." ),
|
||||||
|
zone->GetZoneName() ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetFailureReason( _( "Rule area disallows tracks." ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCB_TEXT_T:
|
||||||
|
case PCB_FP_TEXT_T:
|
||||||
|
SetFailureReason( _( "Cannot start routing from a text item." ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PCB_SHAPE_T:
|
||||||
|
case PCB_FP_SHAPE_T:
|
||||||
|
SetFailureReason( _( "Cannot start routing from a graphic." ) );
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_mode == PNS_MODE_ROUTE_SINGLE && aStartItem )
|
VECTOR2I startPoint = aStartItem ? aStartItem->Anchor( 0 ) : aWhere;
|
||||||
|
|
||||||
|
if( aStartItem && aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
|
||||||
|
{
|
||||||
|
VECTOR2I otherEnd = aStartItem->Anchor( 1 );
|
||||||
|
|
||||||
|
if( ( otherEnd - aWhere ).SquaredEuclideanNorm()
|
||||||
|
< ( startPoint - aWhere ).SquaredEuclideanNorm() )
|
||||||
|
{
|
||||||
|
startPoint = otherEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_mode == PNS_MODE_ROUTE_SINGLE )
|
||||||
{
|
{
|
||||||
VECTOR2I startPoint = aStartItem->Anchor( 0 );
|
|
||||||
SHAPE_LINE_CHAIN dummyStartSeg;
|
SHAPE_LINE_CHAIN dummyStartSeg;
|
||||||
LINE dummyStartLine;
|
LINE dummyStartLine;
|
||||||
|
|
||||||
|
@ -193,7 +253,7 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
|
|
||||||
dummyStartLine.SetShape( dummyStartSeg );
|
dummyStartLine.SetShape( dummyStartSeg );
|
||||||
dummyStartLine.SetLayer( aLayer );
|
dummyStartLine.SetLayer( aLayer );
|
||||||
dummyStartLine.SetNet( aStartItem->Net() );
|
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( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
|
||||||
|
@ -206,12 +266,65 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
for( ITEM* item : highlightedItems )
|
for( ITEM* item : highlightedItems )
|
||||||
m_iface->HideItem( item );
|
m_iface->HideItem( item );
|
||||||
|
|
||||||
|
SetFailureReason( _( "The routing start point violates DRC." ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR && aStartItem )
|
else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
|
||||||
{
|
{
|
||||||
// TODO
|
if( !aStartItem )
|
||||||
|
{
|
||||||
|
SetFailureReason( _( "Cannot start a differential pair in the middle of nowhere." ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DP_PRIMITIVE_PAIR dpPair;
|
||||||
|
wxString errorMsg;
|
||||||
|
|
||||||
|
if( !DIFF_PAIR_PLACER::FindDpPrimitivePair( m_world.get(), startPoint, aStartItem, dpPair,
|
||||||
|
&errorMsg ) )
|
||||||
|
{
|
||||||
|
SetFailureReason( errorMsg );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHAPE_LINE_CHAIN dummyStartSegA;
|
||||||
|
SHAPE_LINE_CHAIN dummyStartSegB;
|
||||||
|
LINE dummyStartLineA;
|
||||||
|
LINE dummyStartLineB;
|
||||||
|
|
||||||
|
dummyStartSegA.Append( dpPair.AnchorN() );
|
||||||
|
dummyStartSegA.Append( dpPair.AnchorN(), true );
|
||||||
|
|
||||||
|
dummyStartSegB.Append( dpPair.AnchorP() );
|
||||||
|
dummyStartSegB.Append( dpPair.AnchorP(), true );
|
||||||
|
|
||||||
|
dummyStartLineA.SetShape( dummyStartSegA );
|
||||||
|
dummyStartLineA.SetLayer( aLayer );
|
||||||
|
dummyStartLineA.SetNet( dpPair.PrimN()->Net() );
|
||||||
|
dummyStartLineA.SetWidth( m_sizes.DiffPairWidth() );
|
||||||
|
|
||||||
|
dummyStartLineB.SetShape( dummyStartSegB );
|
||||||
|
dummyStartLineB.SetLayer( aLayer );
|
||||||
|
dummyStartLineB.SetNet( dpPair.PrimP()->Net() );
|
||||||
|
dummyStartLineB.SetWidth( m_sizes.DiffPairWidth() );
|
||||||
|
|
||||||
|
if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
|
||||||
|
|| m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
|
||||||
|
{
|
||||||
|
ITEM_SET dummyStartSet;
|
||||||
|
NODE::ITEM_VECTOR highlightedItems;
|
||||||
|
|
||||||
|
dummyStartSet.Add( dummyStartLineA );
|
||||||
|
dummyStartSet.Add( dummyStartLineB );
|
||||||
|
markViolations( m_world.get(), dummyStartSet, highlightedItems );
|
||||||
|
|
||||||
|
for( ITEM* item : highlightedItems )
|
||||||
|
m_iface->HideItem( item );
|
||||||
|
|
||||||
|
SetFailureReason( _( "The routing start point violates DRC." ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -220,10 +333,7 @@ bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem,
|
||||||
bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
|
bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
|
||||||
{
|
{
|
||||||
if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
|
if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
|
||||||
{
|
|
||||||
SetFailureReason( _( "The routing start point violates DRC." ) );
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
m_forceMarkObstaclesMode = false;
|
m_forceMarkObstaclesMode = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue