Add support for hole collisions to PNS.
This commit is contained in:
parent
b79d2d9258
commit
6f44b00b2c
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue