Improve connected schematic label placement (Mims-style)
- Add lead stub wires (0.75 unit) from collector and emitter pins for clearance between transistor and first component - Transistor label placed right of body, all chain labels on left - Offset parallel paths (RE/CE) label on right, facing outward - Wider parallel path spacing (2.5 units) for label breathing room - Down-turning components label outward based on path direction - Parameterized label_loc in _draw_vert_chain for context-aware placement
This commit is contained in:
parent
4bc68a58bd
commit
c120a179c8
@ -775,8 +775,14 @@ def _label_multiterminal(d, placed, comp: SpiceComponent) -> None:
|
||||
# ── Connected Layout Renderer ────────────────────────────────
|
||||
|
||||
|
||||
def _draw_vert_chain(d, parsed, start, components, going_up, end_type, end_node):
|
||||
"""Draw a chain of components vertically, terminated by Vdd or Ground."""
|
||||
def _draw_vert_chain(
|
||||
d, parsed, start, components, going_up, end_type, end_node, label_loc="right"
|
||||
):
|
||||
"""Draw a chain of components vertically, terminated by Vdd or Ground.
|
||||
|
||||
label_loc controls which side labels appear on ("left" or "right").
|
||||
Classic drafting rule: labels face outward from the circuit center.
|
||||
"""
|
||||
import schemdraw.elements as elm
|
||||
|
||||
direction = "up" if going_up else "down"
|
||||
@ -785,7 +791,7 @@ def _draw_vert_chain(d, parsed, start, components, going_up, end_type, end_node)
|
||||
if i == 0 and start is not None:
|
||||
elem = elem.at(start)
|
||||
elem = getattr(elem, direction)()
|
||||
elem = elem.label(_component_label(comp), loc="left")
|
||||
elem = elem.label(_component_label(comp), loc=label_loc)
|
||||
d.add(elem)
|
||||
|
||||
if end_type == "ground":
|
||||
@ -810,9 +816,10 @@ def _draw_horiz_then_down(d, parsed, start, path, going_right):
|
||||
|
||||
is_last = i == len(comps) - 1
|
||||
if is_last and len(comps) > 1:
|
||||
# Turn downward at the bend
|
||||
# Turn downward at the bend — label faces outward
|
||||
d.push()
|
||||
d.add(elem.down().label(_component_label(comp), loc="right"))
|
||||
down_label = "right" if going_right else "left"
|
||||
d.add(elem.down().label(_component_label(comp), loc=down_label))
|
||||
if path.end_type == "ground":
|
||||
d.add(elm.Ground())
|
||||
elif path.end_type == "supply":
|
||||
@ -856,10 +863,11 @@ def _render_connected(parsed: ParsedNetlist, layout: ActiveLayout) -> str:
|
||||
signal_names = {s.name for s in layout.signal_sources}
|
||||
is_inverted = layout.device_type in ("bjt_pnp", "pfet")
|
||||
|
||||
# Place active device at the center
|
||||
# Place active device at the center — label goes right of the body
|
||||
# (Mims convention: transistor type label beside the symbol)
|
||||
if layout.device_type.startswith("bjt"):
|
||||
dev_elem = elm.BjtPnp() if is_inverted else elm.BjtNpn()
|
||||
q = d.add(dev_elem.label(_component_label(layout.device)))
|
||||
q = d.add(dev_elem.label(_component_label(layout.device), loc="right"))
|
||||
anchors = {
|
||||
"collector": q.collector,
|
||||
"base": q.base,
|
||||
@ -869,7 +877,7 @@ def _render_connected(parsed: ParsedNetlist, layout: ActiveLayout) -> str:
|
||||
input_term = "base"
|
||||
else:
|
||||
dev_elem = elm.PFet() if is_inverted else elm.NFet()
|
||||
q = d.add(dev_elem.label(_component_label(layout.device)))
|
||||
q = d.add(dev_elem.label(_component_label(layout.device), loc="right"))
|
||||
anchors = {
|
||||
"drain": q.drain,
|
||||
"gate": q.gate,
|
||||
@ -905,38 +913,61 @@ def _render_connected(parsed: ParsedNetlist, layout: ActiveLayout) -> str:
|
||||
|
||||
total = len(up_paths) + len(down_paths) + len(input_paths) + len(output_paths)
|
||||
|
||||
# Junction wire for input terminal when paths branch
|
||||
# Mims-style label placement: vertical labels go LEFT,
|
||||
# keeping clear of the VCC/Ground terminators above/below.
|
||||
# The transistor label sits on the RIGHT, so left is open.
|
||||
# Offset parallel paths (i > 0) flip to RIGHT to face outward.
|
||||
vert_label = "left"
|
||||
|
||||
# Lead stub wires from collector/emitter create clearance from Q
|
||||
# (Mims always drew short leads from transistor pins)
|
||||
if term_name == input_term and total > 1:
|
||||
# Base/gate: junction wire left for bias branching
|
||||
junc = d.add(elm.Line().at(anchor).left(1))
|
||||
draw_from = junc.end
|
||||
elif term_name == supply_term and (up_paths or output_paths):
|
||||
# Collector/drain: short stub up for clearance
|
||||
lead = d.add(elm.Line().at(anchor).up().length(0.75))
|
||||
draw_from = lead.end
|
||||
elif term_name not in (supply_term, input_term) and (down_paths):
|
||||
# Emitter/source: short stub down for clearance
|
||||
lead = d.add(elm.Line().at(anchor).down().length(0.75))
|
||||
draw_from = lead.end
|
||||
else:
|
||||
draw_from = anchor
|
||||
|
||||
# Vertical-up paths (toward supply rail)
|
||||
for i, p in enumerate(up_paths):
|
||||
d.push()
|
||||
# Offset parallel paths flip label side to avoid overlap
|
||||
loc = "right" if i > 0 else vert_label
|
||||
if i > 0:
|
||||
d.add(elm.Line().at(draw_from).right(1.5 * i))
|
||||
d.add(elm.Line().at(draw_from).right(2.5 * i))
|
||||
_draw_vert_chain(
|
||||
d, parsed, None, p.components, True, p.end_type, p.end_node
|
||||
d, parsed, None, p.components, True, p.end_type, p.end_node,
|
||||
label_loc=loc,
|
||||
)
|
||||
else:
|
||||
_draw_vert_chain(
|
||||
d, parsed, draw_from, p.components, True, p.end_type, p.end_node
|
||||
d, parsed, draw_from, p.components, True, p.end_type, p.end_node,
|
||||
label_loc=loc,
|
||||
)
|
||||
d.pop()
|
||||
|
||||
# Vertical-down paths (toward ground)
|
||||
for i, p in enumerate(down_paths):
|
||||
d.push()
|
||||
loc = "right" if i > 0 else vert_label
|
||||
if i > 0:
|
||||
d.add(elm.Line().at(draw_from).right(1.5 * i))
|
||||
d.add(elm.Line().at(draw_from).right(2.5 * i))
|
||||
_draw_vert_chain(
|
||||
d, parsed, None, p.components, False, p.end_type, p.end_node
|
||||
d, parsed, None, p.components, False, p.end_type, p.end_node,
|
||||
label_loc=loc,
|
||||
)
|
||||
else:
|
||||
_draw_vert_chain(
|
||||
d, parsed, draw_from, p.components, False, p.end_type, p.end_node
|
||||
d, parsed, draw_from, p.components, False, p.end_type, p.end_node,
|
||||
label_loc=loc,
|
||||
)
|
||||
d.pop()
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user