diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp
index 148cbd9e3a..57e570b085 100644
--- a/pcbnew/router/pns_item.cpp
+++ b/pcbnew/router/pns_item.cpp
@@ -19,14 +19,87 @@
* with this program. If not, see .
*/
+#include
+#include
+#include
+#include // For ::VIA
+#include
+
#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( 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( 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( 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";
}
}
diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h
index e413eecdad..d07b548b22 100644
--- a/pcbnew/router/pns_item.h
+++ b/pcbnew/router/pns_item.h
@@ -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
*
* 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;