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/>.
*/
#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_line.h"
typedef VECTOR2I::extended_type ecoord;
namespace PNS {
bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
static int holeRadius( BOARD_ITEM* aItem )
{
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!
if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
return false;
@ -35,14 +108,12 @@ bool ITEM::collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV,
if( !m_layers.Overlaps( aOther->m_layers ) )
return false;
return Shape()->Collide( aOther->Shape(), aClearance );
// fixme: MTV
return Shape()->Collide( aOther->Shape(), aClearance, aMTV );
}
bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV,
bool aDifferentNetsOnly ) const
{
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV, aDifferentNetsOnly ) )
return true;
@ -51,36 +122,26 @@ bool ITEM::Collide( const ITEM* aOther, int aClearance, bool aNeedMTV,
if( aOther->m_kind == LINE_T )
{
const LINE* line = static_cast<const LINE*>( aOther );
int clearance = aClearance - line->Width() / 2;
if( line->EndsWithVia() )
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV, aDifferentNetsOnly );
return collideSimple( &line->Via(), clearance, aNeedMTV, aMTV, aDifferentNetsOnly );
}
return false;
}
const std::string ITEM::KindStr() const
std::string ITEM::KindStr() const
{
switch( m_kind )
{
case LINE_T:
return "line";
case SEGMENT_T:
return "segment";
case VIA_T:
return "via";
case JOINT_T:
return "joint";
case SOLID_T:
return "solid";
default:
return "unknown";
case LINE_T: return "line";
case SEGMENT_T: return "segment";
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
*
* 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>
*
* 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
*/
const std::string KindStr() const;
std::string KindStr() const;
/**
* Function SetParent()
*
* Sets the corresponding parent object in the host application's model.
*/
void SetParent( BOARD_CONNECTED_ITEM* aParent )
{
m_parent = aParent;
}
void SetParent( BOARD_CONNECTED_ITEM* aParent ) { m_parent = aParent; }
BOARD_CONNECTED_ITEM* Parent() const { return m_parent; }
/**
* Function Parent()
*
* Returns the corresponding parent object in the host application's model.
*/
BOARD_CONNECTED_ITEM* Parent() const
{
return m_parent;
}
void SetNet( int aNet ) { m_net = aNet; }
int Net() const { return m_net; }
/**
* Function SetNet()
*
* Sets the item's net to aNet
*/
void SetNet( int aNet )
{
m_net = aNet;
}
const LAYER_RANGE& Layers() const { return m_layers; }
void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
/**
* Function Net()
*
* 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();
}
void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
virtual int Layer() const { return Layers().Start(); }
/**
* Function LayersOverlap()
@ -237,16 +164,19 @@ public:
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()
*
* Sets the node that owns this item. An item can belong to a single
* NODE or stay unowned.
* Sets the node that owns this item. An item can belong to a single NODE or be unowned.
*/
void SetOwner( NODE* aOwner )
{
m_owner = aOwner;
}
void SetOwner( NODE* aOwner ) { m_owner = aOwner; }
/**
* Function BelongsTo()
@ -258,20 +188,12 @@ public:
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()
*
* Checks for a collision (clearance violation) with between us and item aOther.
* Collision checking takes all PCB stuff into accound (layers, nets, DRC rules).
* Optionally returns a minimum translation vector for force propagation
* algorithm.
* Optionally returns a minimum translation vector for force propagation algorithm.
*
* @param aOther item to check collision against
* @param aClearance desired clearance
@ -279,8 +201,15 @@ public:
* @param aMTV the minimum translation vector
* @return true, if a collision was found.
*/
virtual bool Collide( const ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly = true ) const;
virtual bool Collide( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV,
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()
@ -290,7 +219,6 @@ public:
bool Collide( const ITEM* aOther, int aClearance, bool aDifferentNetsOnly = true ) const
{
VECTOR2I dummy;
return Collide( aOther, aClearance, false, dummy, aDifferentNetsOnly );
}
@ -305,30 +233,12 @@ public:
return NULL;
}
virtual void Mark( int aMarker )
{
m_marker = aMarker;
}
virtual void Mark( int aMarker ) { m_marker = aMarker; }
virtual void Unmark( int aMarker = -1 ) { m_marker &= ~aMarker; }
virtual int Marker() const { return m_marker; }
virtual void Unmark( int aMarker = -1 )
{
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 void SetRank( int aRank ) { m_rank = aRank; }
virtual int Rank() const { return m_rank; }
virtual VECTOR2I Anchor( int n ) const
{
@ -345,26 +255,19 @@ public:
return Marker() & MK_LOCKED;
}
void SetRoutable( bool aRoutable )
{
m_routable = aRoutable;
}
bool IsRoutable() const
{
return m_routable;
}
void SetRoutable( bool aRoutable ) { m_routable = aRoutable; }
bool IsRoutable() const { return m_routable; }
private:
bool collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV,
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const;
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const;
protected:
PnsKind m_kind;
BOARD_CONNECTED_ITEM* m_parent;
NODE* m_owner;
LAYER_RANGE m_layers;
NODE* m_owner;
LAYER_RANGE m_layers;
bool m_movable;
int m_net;