router: prevent pushout/bogus collision of via with is own hole (or copper) when dragging
The root cause was not removing the original (pre-dragging) via from the world, comparing the ITEM::Parent() pointers of the items was only hiding the main issue. This also fixes the PNSViaCollisions test in the qa/ suite.
This commit is contained in:
parent
882e48b457
commit
0180cb380f
|
@ -323,7 +323,7 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
|
||||||
if( Settings().AllowDRCViolations() )
|
if( Settings().AllowDRCViolations() )
|
||||||
m_dragStatus = true;
|
m_dragStatus = true;
|
||||||
else
|
else
|
||||||
m_dragStatus = !m_world->CheckColliding( m_draggedItems );
|
m_dragStatus = !m_lastNode->CheckColliding( m_draggedItems );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -398,13 +398,14 @@ bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
|
||||||
|
|
||||||
vias.insert( draggedVia.get() );
|
vias.insert( draggedVia.get() );
|
||||||
|
|
||||||
|
m_lastNode->Remove( via );
|
||||||
|
|
||||||
bool ok = propagateViaForces( m_lastNode, vias );
|
bool ok = propagateViaForces( m_lastNode, vias );
|
||||||
|
|
||||||
if( ok )
|
if( ok )
|
||||||
{
|
{
|
||||||
viaTargetPos = draggedVia->Pos();
|
viaTargetPos = draggedVia->Pos();
|
||||||
viaPropOk = true;
|
viaPropOk = true;
|
||||||
m_lastNode->Remove( via );
|
|
||||||
m_lastNode->Add( std::move(draggedVia) );
|
m_lastNode->Add( std::move(draggedVia) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -604,7 +605,7 @@ bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
|
||||||
|
|
||||||
m_dragStatus = ok;
|
m_dragStatus = ok;
|
||||||
|
|
||||||
return true;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -745,7 +746,17 @@ bool DRAGGER::Drag( const VECTOR2I& aP )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ret )
|
if( ret )
|
||||||
|
{
|
||||||
m_lastValidPoint = aP;
|
m_lastValidPoint = aP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( m_lastNode )
|
||||||
|
{
|
||||||
|
delete m_lastNode;
|
||||||
|
m_lastNode = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,27 @@ static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prune self-collisions, i.e. a via/pad annular ring with its own hole
|
||||||
|
static bool shouldWeConsiderHoleCollisions( const ITEM* aItem, const ITEM *aHead )
|
||||||
|
{
|
||||||
|
const HOLE *hi = aItem->OfKind( ITEM::HOLE_T ) ? static_cast<const HOLE*>( aItem ) : nullptr;
|
||||||
|
const HOLE *hh = aHead->OfKind( ITEM::HOLE_T ) ? static_cast<const HOLE*>( aHead ) : nullptr;
|
||||||
|
|
||||||
|
if( hi && hh ) // hole-to-hole case
|
||||||
|
{
|
||||||
|
if ( !hi->ParentPadVia() || !hh->ParentPadVia() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return hi->ParentPadVia() != hh->ParentPadVia();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hi )
|
||||||
|
return hi->ParentPadVia() != aHead;
|
||||||
|
else if( hh )
|
||||||
|
return hh->ParentPadVia() != aItem;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
||||||
COLLISION_SEARCH_CONTEXT* aCtx ) const
|
COLLISION_SEARCH_CONTEXT* aCtx ) const
|
||||||
|
@ -61,13 +82,12 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
||||||
int clearanceEpsilon = aNode->GetRuleResolver()->ClearanceEpsilon();
|
int clearanceEpsilon = aNode->GetRuleResolver()->ClearanceEpsilon();
|
||||||
bool collisionsFound = false;
|
bool collisionsFound = false;
|
||||||
|
|
||||||
//printf( "******************** CollideSimple %lu\n", aCtx->obstacles.size() );
|
|
||||||
|
|
||||||
//printf( "h %p n %p t %p ctx %p\n", aHead, aNode, this, aCtx );
|
|
||||||
|
|
||||||
if( this == aHead ) // we cannot be self-colliding
|
if( this == aHead ) // we cannot be self-colliding
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if ( !shouldWeConsiderHoleCollisions( this, aHead ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
// Special cases for "head" lines with vias attached at the end. Note that this does not
|
// Special cases for "head" lines with vias attached at the end. Note that this does not
|
||||||
// support head-line-via to head-line-via collisions, but you can't route two independent
|
// support head-line-via to head-line-via collisions, but you can't route two independent
|
||||||
// tracks at once so it shouldn't come up.
|
// tracks at once so it shouldn't come up.
|
||||||
|
@ -86,8 +106,15 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode,
|
||||||
|
|
||||||
// And a special case for the "head" via's hole.
|
// And a special case for the "head" via's hole.
|
||||||
|
|
||||||
if( holeH && !HasSameParentPadVia( holeH ) )
|
|
||||||
collisionsFound |= collideSimple( holeH, aNode, aCtx );
|
if( holeH && shouldWeConsiderHoleCollisions( this, holeH ) )
|
||||||
|
{
|
||||||
|
if (collideSimple( holeH, aNode, aCtx ) )
|
||||||
|
{
|
||||||
|
collisionsFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Sadly collision routines ignore SHAPE_POLY_LINE widths so we have to pass them in as part
|
// Sadly collision routines ignore SHAPE_POLY_LINE widths so we have to pass them in as part
|
||||||
// of the clearance value.
|
// of the clearance value.
|
||||||
|
|
|
@ -251,11 +251,6 @@ public:
|
||||||
bool IsFreePad() const { return m_isFreePad; }
|
bool IsFreePad() const { return m_isFreePad; }
|
||||||
|
|
||||||
virtual ITEM* ParentPadVia() const { return nullptr; }
|
virtual ITEM* ParentPadVia() const { return nullptr; }
|
||||||
virtual bool HasSameParentPadVia( const ITEM* aOther ) const
|
|
||||||
{
|
|
||||||
return ParentPadVia() && aOther->ParentPadVia()
|
|
||||||
&& ParentPadVia()->Parent() == aOther->ParentPadVia()->Parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsVirtual() const
|
bool IsVirtual() const
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue