Add support for hole collisions to PNS.

This commit is contained in:
Jeff Young 2019-07-21 16:35:41 -06:00
parent b79d2d9258
commit 6f44b00b2c
2 changed files with 126 additions and 162 deletions

View File

@ -19,14 +19,87 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <class_board.h>
#include <class_board_item.h>
#include <class_pad.h>
#include <class_track.h> // For ::VIA
#include <pad_shapes.h>
#include "pns_item.h" #include "pns_item.h"
#include "pns_line.h" #include "pns_line.h"
typedef VECTOR2I::extended_type ecoord;
namespace PNS { namespace PNS {
bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, static int holeRadius( BOARD_ITEM* aItem )
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
{ {
if( aItem->Type() == PCB_PAD_T )
{
const D_PAD* pad = static_cast<const D_PAD*>( aItem );
if( pad->GetDrillSize().x && pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
return pad->GetDrillSize().x / 2;
else
return 0;
}
else if( aItem->Type() == PCB_VIA_T )
{
return static_cast<const ::VIA*>( aItem )->GetDrillValue() / 2;
}
return 0;
}
bool ITEM::CollideHoles( const ITEM* aOther, bool aNeedMTV, VECTOR2I& aMTV ) const
{
BOARD_ITEM* a = Parent();
BOARD_ITEM* b = aOther->Parent();
if( !a || !b )
return false;
// Holes with identical locations are allowable
if( a->GetPosition() == b->GetPosition() )
return false;
int radius_a = holeRadius( a );
int radius_b = holeRadius( b );
// Do both objects have holes?
if( radius_a > 0 && radius_b > 0 )
{
int holeToHoleMin = a->GetBoard()->GetDesignSettings().m_HoleToHoleMin;
ecoord min_dist = holeToHoleMin + radius_a + radius_b;
ecoord min_dist_sq = min_dist * min_dist;
const VECTOR2I delta = b->GetPosition() - a->GetPosition();
ecoord dist_sq = delta.SquaredEuclideanNorm();
if( dist_sq < min_dist_sq )
{
if( aNeedMTV )
aMTV = delta.Resize( min_dist - sqrt( dist_sq ) + 3 ); // fixme: apparent rounding error
return true;
}
}
return false;
}
bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV,
bool aDifferentNetsOnly ) const
{
// hole-to-hole is a mechanical constraint (broken drill bits) not an electrical one, so
// it must be checked before checking aDifferentNetsOnly
if( CollideHoles( aOther, aNeedMTV, aMTV ) )
return true;
// same nets? no collision! // same nets? no collision!
if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 ) if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
return false; return false;
@ -35,14 +108,12 @@ bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV,
if( !m_layers.Overlaps( aOther->m_layers ) ) if( !m_layers.Overlaps( aOther->m_layers ) )
return false; return false;
return Shape()->Collide( aOther->Shape(), aClearance ); return Shape()->Collide( aOther->Shape(), aClearance, aMTV );
// fixme: MTV
} }
bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const bool aDifferentNetsOnly ) const
{ {
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV, aDifferentNetsOnly ) ) if( collideSimple( aOther, aClearance, aNeedMTV, aMTV, aDifferentNetsOnly ) )
return true; return true;
@ -51,36 +122,26 @@ bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV,
if( aOther->m_kind == LINE_T ) if( aOther->m_kind == LINE_T )
{ {
const LINE* line = static_cast<const LINE*>( aOther ); const LINE* line = static_cast<const LINE*>( aOther );
int clearance = aClearance - line->Width() / 2;
if( line->EndsWithVia() ) if( line->EndsWithVia() )
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV, aDifferentNetsOnly ); return collideSimple( &line->Via(), clearance, aNeedMTV, aMTV, aDifferentNetsOnly );
} }
return false; return false;
} }
const std::string ITEM::KindStr() const std::string ITEM::KindStr() const
{ {
switch( m_kind ) switch( m_kind )
{ {
case LINE_T: case LINE_T: return "line";
return "line"; case SEGMENT_T: return "segment";
case VIA_T: return "via";
case SEGMENT_T: case JOINT_T: return "joint";
return "segment"; case SOLID_T: return "solid";
default: return "unknown";
case VIA_T:
return "via";
case JOINT_T:
return "joint";
case SOLID_T:
return "solid";
default:
return "unknown";
} }
} }

View File

@ -2,7 +2,7 @@
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013-2017 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software: you can redistribute it and/or modify it * This program is free software: you can redistribute it and/or modify it
@ -139,92 +139,19 @@ public:
* *
* Returns the kind of the item, as string * Returns the kind of the item, as string
*/ */
const std::string KindStr() const; std::string KindStr() const;
/** void SetParent( BOARD_CONNECTED_ITEM* aParent ) { m_parent = aParent; }
* Function SetParent() BOARD_CONNECTED_ITEM* Parent() const { return m_parent; }
*
* Sets the corresponding parent object in the host application's model.
*/
void SetParent( BOARD_CONNECTED_ITEM* aParent )
{
m_parent = aParent;
}
/** void SetNet( int aNet ) { m_net = aNet; }
* Function Parent() int Net() const { return m_net; }
*
* Returns the corresponding parent object in the host application's model.
*/
BOARD_CONNECTED_ITEM* Parent() const
{
return m_parent;
}
/** const LAYER_RANGE& Layers() const { return m_layers; }
* Function SetNet() void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
*
* Sets the item's net to aNet
*/
void SetNet( int aNet )
{
m_net = aNet;
}
/** void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
* Function Net() virtual int Layer() const { return Layers().Start(); }
*
* Returns the item's net.
*/
int Net() const
{
return m_net;
}
bool InAnyNet() const
{
return m_net != UnusedNet;
}
/**
* Function SetLayers()
*
* Sets the layers spanned by the item to aLayers.
*/
void SetLayers( const LAYER_RANGE& aLayers )
{
m_layers = aLayers;
}
/**
* Function SetLayer()
*
* Sets the layers spanned by the item to a single layer aLayer.
*/
void SetLayer( int aLayer )
{
m_layers = LAYER_RANGE( aLayer, aLayer );
}
/**
* Function Layers()
*
* Returns the contiguous set of layers spanned by the item.
*/
const LAYER_RANGE& Layers() const
{
return m_layers;
}
/**
* Function Layer()
*
* Returns the item's layer, for single-layered items only.
*/
virtual int Layer() const
{
return Layers().Start();
}
/** /**
* Function LayersOverlap() * Function LayersOverlap()
@ -237,16 +164,19 @@ public:
return Layers().Overlaps( aOther->Layers() ); return Layers().Overlaps( aOther->Layers() );
} }
/**
* Function Owner()
*
* Returns the owner of this item, or NULL if there's none.
*/
NODE* Owner() const { return m_owner; }
/** /**
* Functon SetOwner() * Functon SetOwner()
* *
* Sets the node that owns this item. An item can belong to a single * Sets the node that owns this item. An item can belong to a single NODE or be unowned.
* NODE or stay unowned.
*/ */
void SetOwner( NODE* aOwner ) void SetOwner( NODE* aOwner ) { m_owner = aOwner; }
{
m_owner = aOwner;
}
/** /**
* Function BelongsTo() * Function BelongsTo()
@ -258,20 +188,12 @@ public:
return m_owner == aNode; return m_owner == aNode;
} }
/**
* Function Owner()
*
* Returns the owner of this item, or NULL if there's none.
*/
NODE* Owner() const { return m_owner; }
/** /**
* Function Collide() * Function Collide()
* *
* Checks for a collision (clearance violation) with between us and item aOther. * Checks for a collision (clearance violation) with between us and item aOther.
* Collision checking takes all PCB stuff into accound (layers, nets, DRC rules). * Collision checking takes all PCB stuff into accound (layers, nets, DRC rules).
* Optionally returns a minimum translation vector for force propagation * Optionally returns a minimum translation vector for force propagation algorithm.
* algorithm.
* *
* @param aOther item to check collision against * @param aOther item to check collision against
* @param aClearance desired clearance * @param aClearance desired clearance
@ -279,8 +201,15 @@ public:
* @param aMTV the minimum translation vector * @param aMTV the minimum translation vector
* @return true, if a collision was found. * @return true, if a collision was found.
*/ */
virtual bool Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, virtual bool Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly = true ) const; bool aDifferentNetsOnly = true ) const;
/**
* Function CollideHoles()
*
* Similar to Collide(), above, but checks for hole-to-hole-minimum violations.
*/
bool CollideHoles( const ITEM* aOther, bool aNeedMTV, VECTOR2I& aMTV ) const;
/** /**
* Function Collide() * Function Collide()
@ -290,7 +219,6 @@ public:
bool Collide( const ITEM* aOther, int aClearance, bool aDifferentNetsOnly = true ) const bool Collide( const ITEM* aOther, int aClearance, bool aDifferentNetsOnly = true ) const
{ {
VECTOR2I dummy; VECTOR2I dummy;
return Collide( aOther, aClearance, false, dummy, aDifferentNetsOnly ); return Collide( aOther, aClearance, false, dummy, aDifferentNetsOnly );
} }
@ -305,30 +233,12 @@ public:
return NULL; return NULL;
} }
virtual void Mark( int aMarker ) virtual void Mark( int aMarker ) { m_marker = aMarker; }
{ virtual void Unmark( int aMarker = -1 ) { m_marker &= ~aMarker; }
m_marker = aMarker; virtual int Marker() const { return m_marker; }
}
virtual void Unmark( int aMarker = -1 ) virtual void SetRank( int aRank ) { m_rank = aRank; }
{ virtual int Rank() const { return m_rank; }
m_marker &= ~aMarker;
}
virtual int Marker() const
{
return m_marker;
}
virtual void SetRank( int aRank )
{
m_rank = aRank;
}
virtual int Rank() const
{
return m_rank;
}
virtual VECTOR2I Anchor( int n ) const virtual VECTOR2I Anchor( int n ) const
{ {
@ -345,26 +255,19 @@ public:
return Marker() & MK_LOCKED; return Marker() & MK_LOCKED;
} }
void SetRoutable( bool aRoutable ) void SetRoutable( bool aRoutable ) { m_routable = aRoutable; }
{ bool IsRoutable() const { return m_routable; }
m_routable = aRoutable;
}
bool IsRoutable() const
{
return m_routable;
}
private: private:
bool collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, bool collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const; VECTOR2I& aMTV, bool aDifferentNetsOnly ) const;
protected: protected:
PnsKind m_kind; PnsKind m_kind;
BOARD_CONNECTED_ITEM* m_parent; BOARD_CONNECTED_ITEM* m_parent;
NODE* m_owner; NODE* m_owner;
LAYER_RANGE m_layers; LAYER_RANGE m_layers;
bool m_movable; bool m_movable;
int m_net; int m_net;