diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index 3c67dd1f9d..450c387970 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -1711,6 +1711,13 @@ std::tuple BOARD::GetTrackLength( const TRACK& aTrack ) con if( !inPad ) length += segLen; + + if( track->Type() == PCB_VIA_T ) + { + VIA* via = static_cast( track ); + BOARD_STACKUP& stackup = GetDesignSettings().GetStackupDescriptor(); + length += stackup.GetLayerDistance( via->TopLayer(), via->BottomLayer() ); + } } else if( PAD* pad = dyn_cast( item ) ) { diff --git a/pcbnew/board_stackup_manager/class_board_stackup.cpp b/pcbnew/board_stackup_manager/class_board_stackup.cpp index 3e403df128..b586cb12c0 100644 --- a/pcbnew/board_stackup_manager/class_board_stackup.cpp +++ b/pcbnew/board_stackup_manager/class_board_stackup.cpp @@ -699,6 +699,38 @@ void BOARD_STACKUP::FormatBoardStackup( OUTPUTFORMATTER* aFormatter, } +int BOARD_STACKUP::GetLayerDistance( PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer ) const +{ + wxASSERT( IsCopperLayer( aFirstLayer ) && IsCopperLayer( aSecondLayer ) ); + + if( aFirstLayer == aSecondLayer ) + return 0; + + if( aSecondLayer < aFirstLayer ) + std::swap( aFirstLayer, aSecondLayer ); + + int total = 0; + + for( BOARD_STACKUP_ITEM* item : m_list ) + { + // Will be UNDEFINED_LAYER for dielectrics + PCB_LAYER_ID layer = item->GetBrdLayerId(); + + if( layer != UNDEFINED_LAYER && !IsCopperLayer( layer ) ) + continue; // Silk/mask layer + else if( layer != UNDEFINED_LAYER && layer <= aFirstLayer ) + continue; // Copper layer before first + else if( layer != UNDEFINED_LAYER && layer >= aSecondLayer ) + break; // Copper layer after last: we're done + + for( int sublayer = 0; sublayer < item->GetSublayersCount(); sublayer++ ) + total += item->GetThickness( sublayer ); + } + + return total; +} + + bool IsPrmSpecified( const wxString& aPrmValue ) { // return true if the param value is specified: diff --git a/pcbnew/board_stackup_manager/class_board_stackup.h b/pcbnew/board_stackup_manager/class_board_stackup.h index ecb5790459..38c12b27bd 100644 --- a/pcbnew/board_stackup_manager/class_board_stackup.h +++ b/pcbnew/board_stackup_manager/class_board_stackup.h @@ -303,6 +303,16 @@ public: */ void FormatBoardStackup( OUTPUTFORMATTER* aFormatter, const BOARD* aBoard, int aNestLevel ) const; + + /** + * Calculates the distance (height) between the two given copper layers. This factors in the + * thickness of any dielectric and copper layers between the two given layers, but not the + * height of the given copper layers. + * @param aFirstLayer is a copper layer + * @param aSecondLayer is a different copper layer + * @return the height (in IU) between the two layers + */ + int GetLayerDistance( PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer ) const; }; diff --git a/pcbnew/router/pns_itemset.h b/pcbnew/router/pns_itemset.h index f8ab9b9b6d..c846487466 100644 --- a/pcbnew/router/pns_itemset.h +++ b/pcbnew/router/pns_itemset.h @@ -173,6 +173,11 @@ public: return m_items[index].item; } + ENTRIES::iterator begin() { return m_items.begin(); } + ENTRIES::iterator end() { return m_items.end(); } + ENTRIES::const_iterator cbegin() const { return m_items.cbegin(); } + ENTRIES::const_iterator cend() const { return m_items.cend(); } + void Add( ITEM* aItem, bool aBecomeOwner = false ) { m_items.push_back( ENTRY( aItem, aBecomeOwner ) ); diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 22d51ccba8..799802dd31 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -517,6 +517,17 @@ bool PNS_KICAD_IFACE_BASE::ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* } +int PNS_KICAD_IFACE_BASE::StackupHeight( int aFirstLayer, int aSecondLayer ) const +{ + if( !m_board ) + return 0; + + BOARD_STACKUP& stackup = m_board->GetDesignSettings().GetStackupDescriptor(); + + return stackup.GetLayerDistance( ToLAYER_ID( aFirstLayer ), ToLAYER_ID( aSecondLayer ) ); +} + + int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( const wxString& aNetName, wxString& aComplementNet, wxString& aBaseDpName ) { diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h index d909b148fc..4a6c987752 100644 --- a/pcbnew/router/pns_kicad_iface.h +++ b/pcbnew/router/pns_kicad_iface.h @@ -66,6 +66,7 @@ public: void RemoveItem( PNS::ITEM* aItem ) override; void Commit() override {} bool ImportSizes( PNS::SIZES_SETTINGS& aSizes, PNS::ITEM* aStartItem, int aNet ) override; + int StackupHeight( int aFirstLayer, int aSecondLayer ) const override; void UpdateNet( int aNetCode ) override {} diff --git a/pcbnew/router/pns_meander_placer.cpp b/pcbnew/router/pns_meander_placer.cpp index f42cd1ee5c..c7563d682a 100644 --- a/pcbnew/router/pns_meander_placer.cpp +++ b/pcbnew/router/pns_meander_placer.cpp @@ -89,12 +89,23 @@ bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem ) long long int MEANDER_PLACER::origPathLength() const { long long int total = m_padToDieLenth; - for( const ITEM* item : m_tunedPath.CItems() ) + + for( int idx = 0; idx < m_tunedPath.Size(); idx++ ) { + const ITEM* item = m_tunedPath[idx]; + if( const LINE* l = dyn_cast( item ) ) { total += l->CLine().Length(); } + else if( item->OfKind( ITEM::VIA_T ) && idx > 0 && idx < m_tunedPath.Size() - 1 ) + { + int layerPrev = m_tunedPath[idx - 1]->Layer(); + int layerNext = m_tunedPath[idx + 1]->Layer(); + + if( layerPrev != layerNext ) + total += m_router->GetInterface()->StackupHeight( layerPrev, layerNext ); + } } return total; diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index c959208dce..867a38df5c 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -101,6 +101,7 @@ enum DRAG_MODE virtual void HideItem( ITEM* aItem ) = 0; virtual void Commit() = 0; virtual bool ImportSizes( SIZES_SETTINGS& aSizes, ITEM* aStartItem, int aNet ) = 0; + virtual int StackupHeight( int aFirstLayer, int aSecondLayer ) const = 0; virtual void EraseView() = 0; virtual void UpdateNet( int aNetCode ) = 0;