26#include <unordered_map>
39 if( !aFootprint || aNetChain.
IsEmpty() )
42 std::vector<const PAD*> chainPads;
51 chainPads.push_back(
pad );
54 if( chainPads.size() < 2 )
57 int firstNet = chainPads.front()->GetNetCode();
59 auto crossesNet = [firstNet](
const PAD* p ) {
return p->GetNetCode() != firstNet; };
61 if( !std::any_of( chainPads.begin() + 1, chainPads.end(), crossesNet ) )
66 for(
size_t i = 0; i < chainPads.size(); ++i )
68 for(
size_t j = i + 1; j < chainPads.size(); ++j )
70 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
74 -
VECTOR2D( chainPads[j]->GetCenter() );
75 maxSpan = std::max( maxSpan,
delta.EuclideanNorm() );
85 if( !aBoard || aNetChain.
IsEmpty() )
99 if( !aBoard || aNetChain.
IsEmpty() )
100 return aDefaultBridgeUnitDelay;
113 const std::shared_ptr<TUNING_PROFILES> tuningParams =
115 const TUNING_PROFILE& tuningProfile = tuningParams->GetTuningProfile( tuningProfileName );
120 return aDefaultBridgeUnitDelay;
125 const double aDefaultBridgeUnitDelay )
127 if( !aBoard || aNetChain.
IsEmpty() )
132 if( lengthIU <= 0.0 )
138 return { lengthIU, delayIU };
143 const double aDefaultBridgeUnitDelay )
145 std::vector<CHAIN_BRIDGE> bridges;
147 if( !aBoard || aNetChain.
IsEmpty() )
157 std::vector<PAD*> chainPads;
159 for(
PAD*
pad : fp->Pads() )
164 chainPads.push_back(
pad );
167 if( chainPads.size() < 2 )
170 for(
size_t i = 0; i < chainPads.size(); ++i )
172 for(
size_t j = i + 1; j < chainPads.size(); ++j )
174 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
178 -
VECTOR2D( chainPads[j]->GetCenter() );
179 double length =
delta.EuclideanNorm();
180 double delay = delayIUPerMm * length /
pcbIUScale.IU_PER_MM;
182 bridges.push_back(
CHAIN_BRIDGE{ chainPads[i], chainPads[j], length, delay } );
192 const PAD* aStartPad,
const PAD* aEndPad )
196 if( !aBoard || !aStartPad || !aEndPad || aStartPad == aEndPad )
212 if( !queryNetInfo || queryNetInfo->
GetNetChain().IsEmpty() )
220 if( aStartPad->
GetNet() != queryNetInfo )
226 if( aEndPad->
GetNet() != queryNetInfo )
232 const wxString& chainName = queryNetInfo->
GetNetChain();
238 std::unordered_map<int, std::set<int>> adjacency;
242 std::set<int> startSeeds;
243 std::set<int> endSeeds;
244 bool queryNetHasBridge =
false;
246 auto seedIfEndpoint = [&](
const PAD* aBridgePad,
int aNeighborNet,
247 const PAD* aQueryPad, std::set<int>& aSeeds )
249 if( aBridgePad == aQueryPad && aNeighborNet != aQueryNet )
250 aSeeds.insert( aNeighborNet );
255 if( !br.padA || !br.padB )
258 int netA = br.padA->GetNetCode();
259 int netB = br.padB->GetNetCode();
261 if( netA == aQueryNet || netB == aQueryNet )
263 queryNetHasBridge =
true;
264 seedIfEndpoint( br.padA, netB, aStartPad, startSeeds );
265 seedIfEndpoint( br.padB, netA, aStartPad, startSeeds );
266 seedIfEndpoint( br.padA, netB, aEndPad, endSeeds );
267 seedIfEndpoint( br.padB, netA, aEndPad, endSeeds );
271 adjacency[netA].insert( netB );
272 adjacency[netB].insert( netA );
277 if( !queryNetHasBridge )
283 auto bfsFill = [&](
const std::set<int>& aSeeds, std::set<int>& aOut )
285 std::queue<int> frontier;
287 for(
int seed : aSeeds )
289 if( aOut.insert( seed ).second )
290 frontier.push( seed );
293 while( !frontier.empty() )
295 int cur = frontier.front();
298 auto it = adjacency.find( cur );
300 if( it == adjacency.end() )
303 for(
int nbr : it->second )
305 if( aOut.insert( nbr ).second )
306 frontier.push( nbr );
311 bfsFill( startSeeds,
result.beforeStart );
312 bfsFill( endSeeds,
result.afterEnd );
314 for(
int net :
result.beforeStart )
316 if(
result.afterEnd.count( net ) )
constexpr EDA_IU_SCALE pcbIUScale
NETINFO_ITEM * GetNet() const
Return #NET_INFO object for a given item.
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Information pertinent to a Pcbnew printed circuit board.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
PROJECT * GetProject() const
wxString GetTuningProfile() const
bool HasTuningProfile() const
Handle the data for a net.
const wxString & GetNetChain() const
std::shared_ptr< TUNING_PROFILES > & TuningProfileParameters()
virtual PROJECT_FILE & GetProjectFile() const
std::tuple< double, double > BoardChainBridging(const BOARD *aBoard, const wxString &aNetChain, const double aDefaultBridgeUnitDelay)
Compute both the chain bridging length and its associated propagation delay (in internal delay IU,...
double ChainBridgingDelayPerMm(const BOARD *aBoard, const wxString &aNetChain, const double aDefaultBridgeUnitDelay)
Pick a single per-IU-per-mm delay for a given chain.
NET_CHAIN_PARTITION PartitionNetChainAroundNet(const BOARD *aBoard, int aQueryNet, const PAD *aStartPad, const PAD *aEndPad)
Partition the chain containing aQueryNet around it, cut at the bridges incident on aStartPad and aEnd...
std::vector< CHAIN_BRIDGE > EnumerateChainBridges(const BOARD *aBoard, const wxString &aNetChain, const double aDefaultBridgeUnitDelay)
Enumerate every per-pad-pair bridge edge contributed by every footprint on the board to the named cha...
double BoardChainBridgingLength(const BOARD *aBoard, const wxString &aNetChain)
Sum chain bridging length across every footprint on the board.
double FootprintChainBridgingLength(const FOOTPRINT *aFootprint, const wxString &aNetChain)
Compute the bridging length contributed by a single footprint to a net chain.
One series-component bridge edge inside a chain graph.
Result of PartitionNetChainAroundNet().
Represents a single line in the tuning profile configuration grid.
int m_NetChainBridgePropagationDelay
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D