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/>.
|
* 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";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue