24#include <unordered_map>
37 if( !aFootprint || aNetChain.
IsEmpty() )
40 std::vector<const PAD*> chainPads;
49 chainPads.push_back(
pad );
52 if( chainPads.size() < 2 )
55 int firstNet = chainPads.front()->GetNetCode();
57 auto crossesNet = [firstNet](
const PAD* p ) {
return p->GetNetCode() != firstNet; };
59 if( !std::any_of( chainPads.begin() + 1, chainPads.end(), crossesNet ) )
64 for(
size_t i = 0; i < chainPads.size(); ++i )
66 for(
size_t j = i + 1; j < chainPads.size(); ++j )
68 if( chainPads[i]->GetNetCode() == chainPads[j]->GetNetCode() )
72 -
VECTOR2D( chainPads[j]->GetCenter() );
73 maxSpan = std::max( maxSpan,
delta.EuclideanNorm() );
83 if( !aBoard || aNetChain.
IsEmpty() )
99 if( !aBoard || aNetChain.
IsEmpty() )
112 std::tie( std::ignore, tLen, std::ignore, tDelay, std::ignore ) =
115 if( tLen > 0.0 && tDelay > 0.0 )
117 delayIUPerMm = tDelay / ( tLen /
pcbIUScale.IU_PER_MM );
128 if( !aBoard || aNetChain.
IsEmpty() )
133 if( lengthIU <= 0.0 )
139 return { lengthIU, delayIU };
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.
std::tuple< int, double, double, double, double > GetTrackLength(const PCB_TRACK &aTrack) const
Return data on the length and number of track segments connected to a given track.
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
Handle the data for a net.
const wxString & GetNetChain() const
double ChainBridgingDelayPerMm(const BOARD *aBoard, const wxString &aNetChain)
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::tuple< double, double > BoardChainBridging(const BOARD *aBoard, const wxString &aNetChain)
Compute both the chain bridging length and its associated propagation delay (in internal delay IU,...
std::vector< CHAIN_BRIDGE > EnumerateChainBridges(const BOARD *aBoard, const wxString &aNetChain)
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.
constexpr double DEFAULT_PROPAGATION_DELAY_PS_PER_MM
One series-component bridge edge inside a chain graph.
Result of PartitionNetChainAroundNet().
wxString result
Test unit parsing edge cases and error handling.
VECTOR2< double > VECTOR2D