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;