35    const int start = aForward ? 0 : aLine.
PointCount() - 1;
 
   36    const int delta = aForward ? 1 : -1;
 
   48    for( 
int vertex = start + 
delta; aForward ? vertex < aLine.
PointCount() : vertex >= 0; vertex += 
delta )
 
   52        bool containsA = shape->Contains( seg.
A );
 
   53        bool containsB = shape->Contains( seg.
B );
 
   55        if( containsA && containsB )
 
   65            if( shape->Collide( seg, 0, 
nullptr, &loc ) )
 
   72    if( !aForward && clip < start )
 
   73        aLine.
Remove( clip + 1, start );
 
   74    else if( clip > start )
 
   75        aLine.
Remove( start, clip - 1 );
 
 
   84                                                                     const PAD* aStartPad, 
const PAD* aEndPad,
 
   88    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
   89    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"========== CalculateLengthDetails START ==========" ) );
 
   90    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: input has %zu items" ), aItems.size() );
 
   91    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: optimisations - OptimiseViaLayers=%d, MergeTracks=%d, OptimiseTracesInPads=%d, InferViaInPad=%d" ),
 
   96    int initialPads = 0, initialVias = 0, initialLines = 0, initialUnknown = 0;
 
  101            case LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD:  initialPads++; 
break;
 
  102            case LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA:  initialVias++; 
break;
 
  103            case LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE: initialLines++; 
break;
 
  104            default: initialUnknown++; 
break;
 
  107    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: initial items - PADs=%d, VIAs=%d, LINEs=%d, UNKNOWN=%d" ),
 
  108                initialPads, initialVias, initialLines, initialUnknown );
 
  113        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: performing optimisations..." ) );
 
  115        std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
 
  116        std::vector<LENGTH_DELAY_CALCULATION_ITEM*> lines;
 
  117        std::vector<LENGTH_DELAY_CALCULATION_ITEM*> vias;
 
  120        std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> linesPositionMap;
 
  123        std::map<VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>> padsPositionMap;
 
  127            if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
 
  129                pads.emplace_back( &item );
 
  130                padsPositionMap[item.GetPad()->GetPosition()].insert( &item );
 
  132            else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA )
 
  134                vias.emplace_back( &item );
 
  136            else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
 
  138                lines.emplace_back( &item );
 
  139                linesPositionMap[item.GetLine().CPoint( 0 )].insert( &item );
 
  140                linesPositionMap[item.GetLine().CLastPoint()].insert( &item );
 
  146            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: optimising via layers (%zu vias)" ), vias.size() );
 
  152            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: merging tracks (%zu lines)" ), lines.size() );
 
  158            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: optimising traces in pads" ) );
 
  168        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: creating layer detail maps" ) );
 
  169        details.
LayerLengths = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
 
  172            details.
LayerDelays = std::make_unique<std::map<PCB_LAYER_ID, int64_t>>();
 
  175    const bool useHeight = 
m_board->GetDesignSettings().m_UseHeightForLengthCalcs;
 
  176    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: useHeight=%d" ), useHeight );
 
  183        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: inferring vias in pads" ) );
 
  189    int processedPads = 0, processedVias = 0, processedLines = 0;
 
  190    int mergedRetired = 0, unknownType = 0;
 
  192    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: processing %zu items..." ), aItems.size() );
 
  198            || item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::UNKNOWN )
 
  208        if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
 
  210            const int64_t length = item.GetLine().Length();
 
  216                ( *details.
LayerLengths )[item.GetStartLayer()] += length;
 
  218        else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
 
  220            const auto [layerStart, layerEnd] = item.GetLayers();
 
  226            wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: via from layer %d to %d, height=%lld" ),
 
  227                        layerStart, layerEnd, viaHeight );
 
  229        else if( item.Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
 
  231            int64_t padToDie = item.GetPad()->GetPadToDieLength();
 
  237                wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: pad with pad-to-die length=%lld" ), padToDie );
 
  241    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: processed items - PADs=%d, VIAs=%d, LINEs=%d" ),
 
  242                processedPads, processedVias, processedLines );
 
  243    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: skipped items - merged/retired=%d, unknown=%d" ),
 
  244                mergedRetired, unknownType );
 
  249        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: calculating time domain statistics" ) );
 
  253        ctx.
NetClass = aItems.front().GetEffectiveNetClass(); 
 
  257        wxASSERT( itemDelays.size() == aItems.size() );
 
  259        for( 
size_t i = 0; i < aItems.size(); ++i )
 
  263            if( item.
Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
 
  270            else if( item.
Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::VIA && useHeight )
 
  274            else if( item.
Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::PAD )
 
  280        wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: total delays - Track=%lld, Via=%lld, PadToDie=%lld" ),
 
  284    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"CalculateLengthDetails: RESULTS:" ) );
 
  285    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"  Track length: %lld" ), details.
TrackLength );
 
  286    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"  Via length: %d (from %d vias)" ), details.
ViaLength, details.
NumVias );
 
  287    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"  Pad-to-die length: %d (from %d pads)" ), details.
PadToDieLength, details.
NumPads );
 
  288    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"  TOTAL LENGTH: %lld" ), details.
TotalLength() );
 
  289    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"========== CalculateLengthDetails END ==========" ) );
 
  290    wxLogTrace( wxT( 
"PNS_TUNE" ), wxT( 
"" ) );
 
 
  299    if( aPad && aItem.
Type() == LENGTH_DELAY_CALCULATION_ITEM::TYPE::LINE )
 
  304        if( !padLayers.
Contains( startBottomLayer ) )
 
 
  318                                                   const PAD* aEndPad )
 const 
 
  326                                                  const PAD* aEndPad )
 const 
 
  336    if( !
m_board || !
m_board->GetDesignSettings().m_UseHeightForLengthCalcs )
 
  339    if( 
m_board->GetDesignSettings().m_HasStackup )
 
 
  354        std::vector<LENGTH_DELAY_CALCULATION_ITEM*>&                            aLines,
 
  355        std::map<
VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aLinesPositionMap )
 
  358    std::vector<LENGTH_DELAY_CALCULATION_ITEM*> pads;
 
  362        aLinesPositionMap[line->GetLine().CPoint( 0 )].erase( line );
 
  363        aLinesPositionMap[line->GetLine().CLastPoint()].erase( line );
 
  367    auto tryMerge = [&removeFromPositionMap, &aLinesPositionMap]( 
const MERGE_POINT                    aMergePoint,
 
  372        const auto startItr = aLinesPositionMap.find( aMergePos );
 
  374        if( startItr == aLinesPositionMap.end() )
 
  377        std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& startItems = startItr->second;
 
  379        if( startItems.size() != 1 )
 
  389        if( aPrimaryItem->GetStartLayer() != lineToMerge->
GetStartLayer() )
 
  395        removeFromPositionMap( lineToMerge );
 
  407        removeFromPositionMap( primaryItem );
 
  413        bool mergeComplete = 
false;
 
  415        while( !mergeComplete )
 
  417            bool startMerged = 
false;
 
  418            bool endMerged = 
false;
 
  426            mergeComplete = !startMerged && !endMerged;
 
 
  439            for( 
auto itr = aSecondary.
CPoints().begin() + 1; itr != aSecondary.
CPoints().end(); ++itr )
 
  440                aPrimary.
Insert( 0, *itr );
 
  446            for( 
auto itr = aSecondary.
CPoints().rbegin() + 1; itr != aSecondary.
CPoints().rend(); ++itr )
 
  447                aPrimary.
Insert( 0, *itr );
 
  454            for( 
auto itr = aSecondary.
CPoints().begin() + 1; itr != aSecondary.
CPoints().end(); ++itr )
 
  461            for( 
auto itr = aSecondary.
CPoints().rbegin() + 1; itr != aSecondary.
CPoints().rend(); ++itr )
 
 
  469                                                     const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines )
 
  473        const PAD* 
pad = padItem->GetPad();
 
  481            const PCB_LAYER_ID pcbLayer = lineItem->GetStartLayer();
 
 
  491        const std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aVias, std::vector<LENGTH_DELAY_CALCULATION_ITEM*>& aLines,
 
  492        std::map<
VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>&       aLinesPositionMap,
 
  493        const std::map<
VECTOR2I, std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>>& aPadsPositionMap )
 
  497        auto lineItr = aLinesPositionMap.find( 
via->GetVia()->GetPosition() );
 
  499        if( lineItr == aLinesPositionMap.end() )
 
  502        std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& connectedLines = lineItr->second;
 
  504        if( connectedLines.empty() )
 
  507            via->SetLayers( 
via->GetVia()->GetLayer(), 
via->GetVia()->GetLayer() );
 
  509        else if( connectedLines.size() == 1 )
 
  512            bool               isViaInPad = 
false;
 
  513            const PCB_LAYER_ID lineLayer = ( *connectedLines.begin() )->GetStartLayer();
 
  515            auto padItr = aPadsPositionMap.find( 
via->GetVia()->GetPosition() );
 
  517            if( padItr != aPadsPositionMap.end() )
 
  520                const std::unordered_set<LENGTH_DELAY_CALCULATION_ITEM*>& pads = padItr->second;
 
  522                if( pads.size() == 1 )
 
  538                via->SetLayers( lineLayer, lineLayer );
 
  548                layers.
set( lineItem->GetStartLayer() );
 
  564                via->SetLayers( firstLayer, firstLayer );
 
  566                via->SetLayers( firstLayer, lastLayer );
 
 
  584    if( shape->Contains( aLine.
CPoint( 0 ) ) )
 
  586    else if( shape->Contains( aLine.
CLastPoint() ) )
 
 
  625            std::vector<VECTOR2I> points{ track->GetStart(), track->GetEnd() };
 
  636    else if( 
const PAD* 
pad = 
dynamic_cast<const PAD*
>( aBoardItem ) )
 
  641        const LSET&  layers = 
pad->Padstack().LayerSet();
 
  653        item.
SetLayers( firstLayer, secondLayer );
 
 
  664        std::unique_ptr<TUNING_PROFILE_PARAMETERS_IFACE>&& aProvider )
 
 
BASE_SET & set(size_t pos)
 
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
 
virtual NETCLASS * GetEffectiveNetClass() const
Return the NETCLASS for this item.
 
Manage layers needed to make a physical board.
 
void BuildDefaultStackupList(const BOARD_DESIGN_SETTINGS *aSettings, int aActiveCopperLayersCount=0)
Create a default stackup, according to the current BOARD_DESIGN_SETTINGS settings.
 
int GetLayerDistance(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Calculate the distance (height) between the two given copper layers.
 
Lightweight class which holds a pad, via, or a routed trace outline.
 
void SetLine(const SHAPE_LINE_CHAIN &aLine)
Sets the source SHAPE_LINE_CHAIN of this item.
 
void SetVia(const PCB_VIA *aVia)
Sets the VIA associated with this item.
 
TYPE Type() const
Gets the routing item type.
 
void SetPad(const PAD *aPad)
Sets the parent PAD associated with this item.
 
void SetMergeStatus(const MERGE_STATUS aStatus)
Sets the MERGE_STATUS of this item.
 
SHAPE_LINE_CHAIN & GetLine() const
Gets the SHAPE_LINE_CHAIN associated with this item.
 
const PAD * GetPad() const
Gets the parent PAD associated with this item.
 
PCB_LAYER_ID GetStartLayer() const
Gets the start board layer for the proxied item.
 
void SetEffectiveNetClass(const NETCLASS *aNetClass)
Sets the effective net class for the item.
 
void CalculateViaLayers(const BOARD *aBoard)
Calculates active via payers for a proxied VIA object.
 
void SetLayers(const PCB_LAYER_ID aStart, const PCB_LAYER_ID aEnd=PCB_LAYER_ID::UNDEFINED_LAYER)
Sets the first and last layers associated with this item.
 
std::unique_ptr< TUNING_PROFILE_PARAMETERS_IFACE > m_tuningProfileParameters
The active provider of tuning profile parameters.
 
int64_t CalculateLengthForDelay(int64_t aDesiredDelay, const TUNING_PROFILE_GEOMETRY_CONTEXT &aCtx) const
Calculates the length of track required for the given delay in a specific geometry context.
 
int64_t CalculatePropagationDelayForShapeLineChain(const SHAPE_LINE_CHAIN &aShape, const TUNING_PROFILE_GEOMETRY_CONTEXT &aCtx) const
Gets the propagation delay for the given shape line chain.
 
static void clipLineToPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aLayer, bool aForward=true)
Clips the given line to the minimal direct electrical length within the pad.
 
MERGE_POINT
Enum to describe whether track merging is attempted from the start or end of a track segment.
 
void inferViaInPad(const PAD *aPad, const LENGTH_DELAY_CALCULATION_ITEM &aItem, LENGTH_DELAY_STATS &aDetails) const
Infers if there is a via in the given pad.
 
static void optimiseTracesInPads(const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aPads, const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines)
Optimises the given set of items to minimise the electrical path length.
 
static void mergeLines(std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines, std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aLinesPositionMap)
Merges any lines (traces) that are contiguous, on one layer, and with no junctions.
 
int64_t CalculateDelay(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical propagation delay of the given items.
 
int64_t CalculateLength(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr) const
Calculates the electrical length of the given items.
 
int StackupHeight(PCB_LAYER_ID aFirstLayer, PCB_LAYER_ID aSecondLayer) const
Returns the stackup distance between the two given layers.
 
void SynchronizeTuningProfileProperties() const
Ensure time domain properties provider is synced with board / project settings if required.
 
BOARD * m_board
The parent board for all items.
 
LENGTH_DELAY_CALCULATION_ITEM GetLengthCalculationItem(const BOARD_CONNECTED_ITEM *aBoardItem) const
Return a LENGTH_CALCULATION_ITEM constructed from the given BOARD_CONNECTED_ITEM.
 
static void optimiseViaLayers(const std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aVias, std::vector< LENGTH_DELAY_CALCULATION_ITEM * > &aLines, std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aLinesPositionMap, const std::map< VECTOR2I, std::unordered_set< LENGTH_DELAY_CALCULATION_ITEM * > > &aPadsPositionMap)
Optimises the via layers.
 
void SetTuningProfileParametersProvider(std::unique_ptr< TUNING_PROFILE_PARAMETERS_IFACE > &&aProvider)
Sets the provider for tuning profile parameter resolution.
 
static void mergeShapeLineChains(SHAPE_LINE_CHAIN &aPrimary, const SHAPE_LINE_CHAIN &aSecondary, MERGE_POINT aMergePoint)
Merges two SHAPE_LINE_CHAINs where there is a shared endpoing.
 
LENGTH_DELAY_STATS CalculateLengthDetails(std::vector< LENGTH_DELAY_CALCULATION_ITEM > &aItems, PATH_OPTIMISATIONS aOptimisations, const PAD *aStartPad=nullptr, const PAD *aEndPad=nullptr, LENGTH_DELAY_LAYER_OPT aLayerOpt=LENGTH_DELAY_LAYER_OPT::NO_LAYER_DETAIL, LENGTH_DELAY_DOMAIN_OPT aDomain=LENGTH_DELAY_DOMAIN_OPT::NO_DELAY_DETAIL) const
Calculates the electrical length of the given items.
 
static void OptimiseTraceInPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aPcbLayer)
Optimises the given trace / line to minimise the electrical path length within the given pad.
 
LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
 
LSET is a set of PCB_LAYER_IDs.
 
copper_layers_iterator copper_layers_end() const
 
LSEQ CuStack() const
Return a sequence of copper layers in starting from the front/top and extending to the back/bottom.
 
copper_layers_iterator copper_layers_begin() const
 
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
 
const LSET & LayerSet() const
 
bool FlashLayer(int aLayer, bool aOnlyCheckIfPermitted=false) const
Check to see whether the pad should be flashed on the specific layer.
 
VECTOR2I GetPosition() const override
 
const PADSTACK & Padstack() const
 
const std::shared_ptr< SHAPE_POLY_SET > & GetEffectivePolygon(PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
 
const VECTOR2I & GetMid() const
 
const VECTOR2I & GetStart() const
 
const VECTOR2I & GetEnd() const
 
virtual int GetWidth() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
bool IsPtOnArc(size_t aPtIndex) const
 
virtual const VECTOR2I GetPoint(int aIndex) const override
 
int PointCount() const
Return the number of points (vertices) in this line chain.
 
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
 
const std::vector< SHAPE_ARC > & CArcs() const
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
 
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
 
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
 
void Insert(size_t aVertex, const VECTOR2I &aP)
 
const std::vector< VECTOR2I > & CPoints() const
 
a few functions useful in geometry calculations.
 
PCB_LAYER_ID
A quick note on layer IDs:
 
LENGTH_DELAY_DOMAIN_OPT
Enum which controls the calculation domain of the length / delay calculation methods.
 
LENGTH_DELAY_LAYER_OPT
Enum which controls the level of detail returned by the length / delay calculation methods.
 
Holds length measurement result details and statistics.
 
std::unique_ptr< std::map< PCB_LAYER_ID, int64_t > > LayerDelays
 
int64_t TotalLength() const
Calculates the total electrical length for this set of statistics.
 
std::unique_ptr< std::map< PCB_LAYER_ID, int64_t > > LayerLengths
 
int64_t TotalDelay() const
Calculates the total electrical propagation delay for this set of statistics.
 
Struct to control which optimisations the length calculation code runs on the given path objects.
 
bool InferViaInPad
Determines if there is a via-in-pad present on the board but not in the item set.
 
bool OptimiseViaLayers
Optimise via layers for height calculations, ensuring only the distance between routed segments is co...
 
bool MergeTracks
Merges all contiguous (end-to-end, same layer) tracks.
 
bool OptimiseTracesInPads
Optimises the electrical length of tracks within pads.
 
A data structure to contain basic geometry data which can affect signal propagation calculations.
 
const NETCLASS * NetClass
The net class this track belongs to.
 
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
 
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
 
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
 
VECTOR2< int32_t > VECTOR2I