TraceMaker
C++ API of the engine
Loading...
Searching...
No Matches
connectivity.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2#pragma once
3// Copper connectivity with KiCad's semantics, shared by the DRC (unconnected/dangling checks) and the router
4// (which pads are already joined).
5#include <numeric>
6#include <vector>
7
8#include "drc/copper.hpp"
9#include "geom/poly_index.hpp"
11#include "model/board.hpp"
12
13namespace tmk::drc {
14
15struct UnionFind {
16 std::vector<int> p;
17 explicit UnionFind(std::size_t n) : p(n) { std::iota(p.begin(), p.end(), 0); }
18 int find(int x) {
19 while (p[static_cast<std::size_t>(x)] != x) x = p[static_cast<std::size_t>(x)] = p[static_cast<std::size_t>(p[static_cast<std::size_t>(x)])];
20 return x;
21 }
22 void unite(int a, int b) {
23 a = find(a);
24 b = find(b);
25 if (a != b) p[static_cast<std::size_t>(std::max(a, b))] = std::min(a, b);
26 }
27};
28
30 std::vector<int> root; // cluster root per copper item
31 std::vector<std::uint8_t> end_hit; // per track/arc item: [2i] start connected, [2i+1] end connected
32 std::vector<model::LayerMask> via_layers; // per via item: layers with a connection
33};
34
35// `grid` must contain every item of `cm` (ids = item indices).
36// `overlap_links`: tracks, arcs, vias and board graphics of one net are also joined where their copper merely
37// overlaps (KiCad 10 links connectivity items by shape collision, so a track crossing another of its net joins
38// it). The DRC uses it; the router keeps end-point anchors (more conservative: it may route a redundant link).
39// `fills` (optional): edge buckets of the zone fills, so an item is tested against the fill edges near it only;
40// the result is the same as without (the linear test is the reference path, tests/test_refill.cpp).
41struct ZoneFills;
42Connectivity compute_connectivity(const model::Board& b, const CopperModel& cm, index::UniformGrid& grid, bool overlap_links = false,
43 const ZoneFills* fills = nullptr);
44
45// KiCad 10's item graph (pcbnew/connectivity, CN_VISITOR): items of any nets are linked when their copper touches
46// on a common layer, except two items that cannot change net (pads, zone fills, free vias) on different nets.
47// Tracks, arcs, vias and board copper graphics can change net. Footprint graphics and copper text are not part of it.
48// Pads of one net keep the stricter pad-to-pad rule of compute_connectivity (centre inside the other pad, or one
49// footprint's overlapping pads). Zone fills are left out of `adj`: testing every item against every large fill
50// polygon is slow, and only a few questions need them, so those ask zones_touching.
51struct ItemGraph {
52 std::vector<std::vector<int>> adj; // neighbours of each copper item, ascending (empty for items outside the graph)
53};
54bool in_item_graph(const CopperItem& it);
55bool can_change_net(const CopperItem& it);
57// Edge buckets of every zone fill (geom::PolygonIndex), so the zone questions below cost the nearby edges only.
58struct ZoneFills {
59 std::vector<int> slot; // per copper item: index into `index`, -1 if the item is not a zone fill
60 std::vector<geom::PolygonIndex> index;
61 explicit ZoneFills(const CopperModel& cm);
62};
63// Zone-fill items on `layers` whose copper is closer than `clearance` to `s` (0, the default: overlap only, as
64// KiCad's SHAPE::Collide; 1: touching counts),
65// ascending item indices.
66std::vector<int> zones_touching(const CopperModel& cm, const ZoneFills& zf, index::UniformGrid& grid, const geom::Shape& s,
67 model::LayerMask layers, Coord clearance = 0);
68
69// The nets KiCad's DRC sees after loading a board (CN_CONNECTIVITY_ALGO::PropagateNets, run by every connectivity
70// build): a via touching only zone fills takes a zone's net (its own if one of the zones has it, else the lowest);
71// then in every cluster of the graph without zones whose pads carry one net only, tracks, arcs, vias and board
72// graphics take that net (a stray via on a track joins the track's net; a track bridging two nets keeps its own).
73// Clusters without pads take the net of their first item with a net. Returns one net per copper item.
74std::vector<model::NetId> propagate_nets(const CopperModel& cm, const ItemGraph& g, const ZoneFills& zf, index::UniformGrid& grid);
75
76} // namespace tmk::drc
The board model (design doc 02 §3): every object TraceMaker reads from a .kicad_pcb,...
Copper items with exact shapes, built from the board model, for DRC and routing obstacles.
std::vector< model::NetId > propagate_nets(const CopperModel &cm, const ItemGraph &g, const ZoneFills &zf, index::UniformGrid &grid)
The nets KiCad's DRC sees after loading a board (CN_CONNECTIVITY_ALGO::PropagateNets,...
bool can_change_net(const CopperItem &it)
ItemGraph item_graph(const model::Board &b, const CopperModel &cm, index::UniformGrid &grid)
bool in_item_graph(const CopperItem &it)
std::vector< int > zones_touching(const CopperModel &cm, const ZoneFills &zf, index::UniformGrid &grid, const geom::Shape &s, model::LayerMask layers, Coord clearance=0)
Zone-fill items on layers whose copper is closer than clearance to s (0, the default: overlap only,...
Connectivity compute_connectivity(const model::Board &b, const CopperModel &cm, index::UniformGrid &grid, bool overlap_links=false, const ZoneFills *fills=nullptr)
std::uint64_t LayerMask
bit i = copper layer i in stack order (0 = F.Cu, last = B.Cu)
Definition board.hpp:22
std::int64_t Coord
Engine coordinate: signed 64-bit nanometres.
Definition units.hpp:12
Bucketed edges of one large closed polygon (a zone fill), so "does this disk touch the polygon?...
std::vector< std::uint8_t > end_hit
per track/arc item: [2i] start connected, [2i+1] end connected
std::vector< model::LayerMask > via_layers
per via item: layers with a connection
std::vector< int > root
cluster root per copper item
KiCad 10's item graph (pcbnew/connectivity, CN_VISITOR): items of any nets are linked when their copp...
std::vector< std::vector< int > > adj
neighbours of each copper item, ascending (empty for items outside the graph)
void unite(int a, int b)
UnionFind(std::size_t n)
std::vector< int > p
Edge buckets of every zone fill (geom::PolygonIndex), so the zone questions below cost the nearby edg...
ZoneFills(const CopperModel &cm)
std::vector< int > slot
per copper item: index into index, -1 if the item is not a zone fill
std::vector< geom::PolygonIndex > index
Uniform spatial hash grid over a bounding box (design doc 03 §2): O(1) insert, box queries return eac...