MCPcopy Create free account
hub / github.com/SLiCAP/SLiCAP_python / box_symbol_svg

Function box_symbol_svg

SLiCAP/schematic/subcircuit.py:145–222  ·  view source on GitHub ↗

Return a standalone SVG holding a default block symbol for ``defn``. ``placement`` is the **visual** clockwise-from-top-left pin order (default: the ``.subckt`` node order). It only moves where each named pin is drawn — ``data-nodes`` stays in the fixed ``.subckt`` order, since a SLiCA

(defn: SubcktDef, placement: list | None = None,
                   extra_w: float = 0.0, extra_h: float = 0.0)

Source from the content-addressed store, hash-verified

143
144
145def box_symbol_svg(defn: SubcktDef, placement: list | None = None,
146 extra_w: float = 0.0, extra_h: float = 0.0) -> str:
147 """Return a standalone SVG holding a default block symbol for ``defn``.
148
149 ``placement`` is the **visual** clockwise-from-top-left pin order (default:
150 the ``.subckt`` node order). It only moves where each named pin is drawn —
151 ``data-nodes`` stays in the fixed ``.subckt`` order, since a SLiCAP ``X``
152 instance lists its nodes positionally against the ``.subckt`` header. So
153 reordering pins never changes the netlist, only the look.
154
155 ``extra_w`` / ``extra_h`` grow (or, when negative, shrink) each half-dimension
156 relative to the auto-fit minimum — the Place dialog's width/height +/- buttons.
157 Shrinking is allowed down to an absolute floor; below the auto-fit size names
158 may overlap, which is then the user's call. The box stays on the grid.
159 """
160 ports = list(defn.ports) # data-nodes / netlist order
161 placement = list(placement) if placement else list(ports)
162 n_top, n_right, n_bottom, n_left = _side_counts(len(placement))
163
164 hw_min, hh_min = _min_half(placement)
165 half_w = max(_FLOOR, hw_min + extra_w)
166 half_h = max(_FLOOR, hh_min + extra_h)
167
168 # Clockwise slots (top L→R, right T→B, bottom R→L, left B→T): each is
169 # (edge_x, edge_y, node_x, node_y). placement[i] occupies slot i.
170 slots: list[tuple[float, float, float, float]] = []
171 for x in _spread(n_top, half_w):
172 slots.append((x, -half_h, x, -half_h - _STUB))
173 for y in _spread(n_right, half_h):
174 slots.append((half_w, y, half_w + _STUB, y))
175 for x in reversed(_spread(n_bottom, half_w)):
176 slots.append((x, half_h, x, half_h + _STUB))
177 for y in reversed(_spread(n_left, half_h)):
178 slots.append((-half_w, y, -half_w - _STUB, y))
179 pos = {placement[i]: slots[i] for i in range(len(placement))}
180
181 def _f(v: float) -> str: # tidy number formatting
182 return f"{v:g}"
183
184 # The box + pin stubs + node markers only. The block name (model label) and
185 # the pin names are drawn by ComponentItem so they stay upright under any
186 # rotation/flip — never baked into the (rotating) symbol art.
187 lines = [
188 f'<rect x="{_f(-half_w)}" y="{_f(-half_h)}" '
189 f'width="{_f(2 * half_w)}" height="{_f(2 * half_h)}" '
190 f'fill="none" stroke="black" stroke-width="1"/>',
191 "",
192 "<!-- Pins -->",
193 ]
194 for port in ports:
195 ex, ey, nx, ny = pos[port]
196 lines.append(
197 f'<line x1="{_f(ex)}" y1="{_f(ey)}" x2="{_f(nx)}" y2="{_f(ny)}" '
198 f'stroke="black" stroke-width="1"/>'
199 )
200 lines.append("")
201 for port in ports:
202 _ex, _ey, nx, ny = pos[port]

Callers 2

_build_symbolFunction · 0.85
_on_place_subcircuitMethod · 0.85

Calls 4

_side_countsFunction · 0.85
_min_halfFunction · 0.85
_spreadFunction · 0.85
_fFunction · 0.70

Tested by

no test coverage detected