Kicad schematic rendering WIP
This commit is contained in:
parent
60674ab5b3
commit
b69e9fded4
3 changed files with 82 additions and 26 deletions
|
|
@ -80,7 +80,8 @@ class Stroke:
|
|||
|
||||
attrs = {'stroke': color,
|
||||
'stroke_linecap': 'round',
|
||||
'stroke_widtj': self.width}
|
||||
'stroke_linejoin': 'round',
|
||||
'stroke_width': self.width or 0.254}
|
||||
|
||||
if self.type not in (Atom.default, Atom.solid):
|
||||
attrs['stroke_dasharray'] = {
|
||||
|
|
@ -313,6 +314,14 @@ class TextMixin:
|
|||
d = ' '.join(self.svg_path_data())
|
||||
yield Tag('path', d=d, fill='none', stroke=color, stroke_width=f'{self.line_width:.3f}', stroke_linecap='round')
|
||||
|
||||
@property
|
||||
def _text_offset(self):
|
||||
return (0, 0)
|
||||
|
||||
@property
|
||||
def rotation(self):
|
||||
return self.at.rotation
|
||||
|
||||
def render(self, variables={}):
|
||||
if not self.effects or self.effects.hide or not self.effects.font:
|
||||
return
|
||||
|
|
@ -327,17 +336,30 @@ class TextMixin:
|
|||
w = max_x - min_x
|
||||
h = max_y - min_y
|
||||
|
||||
offx = -min_x + {
|
||||
h_just = self.effects.justify.h if self.effects.justify else None
|
||||
v_just = self.effects.justify.v if self.effects.justify else None
|
||||
|
||||
rot = self.rotation
|
||||
# KiCad already flips h_just in these cases, making the rotation param redundant.
|
||||
if rot == 180:
|
||||
rot = 0
|
||||
|
||||
if rot == 270 and self.at.rotation != 270:
|
||||
h_just = {Atom.right: Atom.left, Atom.left: Atom.right}.get(h_just, h_just)
|
||||
|
||||
offx, offy = self._text_offset
|
||||
|
||||
offx += -min_x + {
|
||||
None: -w/2,
|
||||
Atom.right: -w,
|
||||
Atom.left: 0
|
||||
}[self.effects.justify.h if self.effects.justify else None]
|
||||
}[h_just]
|
||||
|
||||
offy = {
|
||||
offy += {
|
||||
None: self.size/2,
|
||||
Atom.top: self.size,
|
||||
Atom.bottom: 0
|
||||
}[self.effects.justify.v if self.effects.justify else None]
|
||||
}[v_just]
|
||||
|
||||
aperture = ap.CircleAperture(self.line_width or 0.2, unit=MM)
|
||||
for stroke in strokes:
|
||||
|
|
@ -345,7 +367,7 @@ class TextMixin:
|
|||
|
||||
for x, y in stroke:
|
||||
x, y = x+offx, y+offy
|
||||
x, y = rotate_point(x, y, math.radians(self.at.rotation or 0))
|
||||
x, y = rotate_point(x, y, math.radians(-rot or 0))
|
||||
x, y = x+self.at.x, y+self.at.y
|
||||
out.append((x, y))
|
||||
|
||||
|
|
@ -429,6 +451,11 @@ class DrawnProperty(TextMixin):
|
|||
hide: Flag() = False
|
||||
tstamp: Timestamp = None
|
||||
effects: TextEffect = field(default_factory=TextEffect)
|
||||
_ : SEXP_END = None
|
||||
parent: object = None
|
||||
|
||||
def __after_parse(self, parent=None):
|
||||
self.parent = parent
|
||||
|
||||
# Alias value for text mixin
|
||||
@property
|
||||
|
|
|
|||
|
|
@ -187,6 +187,10 @@ class LocalLabel(TextMixin):
|
|||
effects: TextEffect = field(default_factory=TextEffect)
|
||||
uuid: UUID = field(default_factory=UUID)
|
||||
|
||||
@property
|
||||
def _text_offset(self):
|
||||
return (0, -2*self.line_width)
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
yield from TextMixin.to_svg(self, colorscheme.text)
|
||||
|
||||
|
|
@ -283,6 +287,11 @@ class DrawnProperty(TextMixin):
|
|||
at: AtPos = field(default_factory=AtPos)
|
||||
hide: Flag() = False
|
||||
effects: TextEffect = field(default_factory=TextEffect)
|
||||
_: SEXP_END = None
|
||||
parent: object = None
|
||||
|
||||
def __after_parse__(self, parent=None):
|
||||
self.parent = parent
|
||||
|
||||
# Alias value for text mixin
|
||||
@property
|
||||
|
|
@ -293,6 +302,10 @@ class DrawnProperty(TextMixin):
|
|||
def text(self, value):
|
||||
self.value = value
|
||||
|
||||
@property
|
||||
def rotation(self):
|
||||
return self.parent.rotation + self.at.rotation
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
if not self.hide:
|
||||
yield from TextMixin.to_svg(self, colorscheme.text)
|
||||
|
|
@ -323,26 +336,39 @@ class SymbolInstance:
|
|||
def __after_parse__(self, parent):
|
||||
self.schematic = parent
|
||||
|
||||
@property
|
||||
def rotation(self):
|
||||
return self.at.rotation
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
children = []
|
||||
rot = self.at.rotation
|
||||
|
||||
for prop in self.properties:
|
||||
children += prop.to_svg()
|
||||
sym = self.schematic.lookup_symbol(self.lib_name, self.lib_id)
|
||||
|
||||
sym = self.schematic.lookup_symbol(self.lib_name, self.lib_id).raw_units[self.unit - 1]
|
||||
for elem in sym.graphical_elements:
|
||||
children += elem.to_svg(colorscheme)
|
||||
name = f'{sym.name}_0_1'
|
||||
if name in sym.global_units.get(1, {}):
|
||||
for elem in sym.global_units[1][name].graphical_elements:
|
||||
children += elem.to_svg(colorscheme)
|
||||
|
||||
name = f'{sym.name}_{self.unit}_1'
|
||||
if name in sym.styles.get(1, {}):
|
||||
for elem in sym.styles[1][name].graphical_elements:
|
||||
children += elem.to_svg(colorscheme)
|
||||
|
||||
xform = f'translate({self.at.x:.3f} {self.at.y:.3f})'
|
||||
if self.at.rotation:
|
||||
xform = f'rotate({self.at.rotation}) {xform}'
|
||||
if rot:
|
||||
xform += f'rotate({-rot})'
|
||||
if self.mirror.x:
|
||||
xform = f'scale(-1 1) {xform}'
|
||||
if self.mirror.y:
|
||||
xform = f'scale(1 -1) {xform}'
|
||||
xform += f'scale(-1 1)'
|
||||
if not self.mirror.y:
|
||||
xform += f'scale(1 -1)'
|
||||
|
||||
yield Tag('g', children=children, transform=xform, fill=colorscheme.fill, stroke=colorscheme.lines)
|
||||
|
||||
for prop in self.properties:
|
||||
yield from prop.to_svg()
|
||||
|
||||
|
||||
@sexp_type('path')
|
||||
class SubsheetCrosslinkSheet:
|
||||
|
|
@ -399,6 +425,10 @@ class Subsheet:
|
|||
def __before_sexp__(self):
|
||||
self._properties = [self.sheet_name, self.file_name]
|
||||
|
||||
@property
|
||||
def rotation(self):
|
||||
return 0
|
||||
|
||||
def open(self, search_dir=None, safe=True):
|
||||
if search_dir is None:
|
||||
if not self.schematic.original_filename:
|
||||
|
|
@ -496,18 +526,18 @@ class Schematic:
|
|||
|
||||
@property
|
||||
def elements(self):
|
||||
yield from self.images
|
||||
yield from self.polylines
|
||||
yield from self.symbols
|
||||
yield from self.junctions
|
||||
yield from self.no_connects
|
||||
yield from self.bus_entries
|
||||
yield from self.wires
|
||||
yield from self.buses
|
||||
yield from self.images
|
||||
yield from self.polylines
|
||||
yield from self.texts
|
||||
yield from self.local_labels
|
||||
yield from self.global_labels
|
||||
yield from self.hierarchical_labels
|
||||
yield from self.symbols
|
||||
yield from self.subsheets
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
|
|
|
|||
|
|
@ -96,12 +96,12 @@ class Pin:
|
|||
return (x1, y1), (x2, y2)
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
x1, y1 = self.at.x, self.at.y
|
||||
x2, y2 = x1+self.length, y1
|
||||
xform = {'transform': f'rotate({-self.at.rotation} {x1} {y1})'}
|
||||
x1, y1 = 0, 0
|
||||
x2, y2 = self.length, 0
|
||||
xform = {'transform': f'translate({self.at.x:.3f} {self.at.y:.3f}) rotate({self.at.rotation})'}
|
||||
style = {'stroke_width': 0.254, 'stroke': colorscheme.lines, 'stroke_linecap': 'round'}
|
||||
|
||||
yield Tag('path', **xform, **style, d=f'M {x1:.6f} {y1:.6f} L {x2:.6f} {y2:.6f}')
|
||||
yield Tag('path', **xform, **style, d=f'M 0 0 L {self.length:.3f} 0')
|
||||
|
||||
eps = 1
|
||||
for tag in {
|
||||
|
|
@ -160,8 +160,6 @@ class Pin:
|
|||
else:
|
||||
raise ValueError(f'Invalid pin rotation {self.at.rotation}')
|
||||
|
||||
yield f'M {line.x1:.3f} {line.y1:.3f} L {line.x2:.3f} {line.y2:.3f}'
|
||||
|
||||
d = []
|
||||
for stroke in strokes:
|
||||
points = []
|
||||
|
|
@ -171,7 +169,8 @@ class Pin:
|
|||
x, y = x+self.at.x, y+self.at.y
|
||||
points.append(f'{x:.3f} {y:.3f}')
|
||||
d.append('M '+ ' L '.join(points) + ' ')
|
||||
yield Tag('path', d=d, fill='none', stroke=colorscheme.text, stroke_width='0.254', stroke_linecap='round')
|
||||
yield Tag('path', d=' '.join(d), fill='none', stroke=colorscheme.text, stroke_width='0.254', stroke_linecap='round', stroke_linejoin='round')
|
||||
print('name', self.name.value)
|
||||
|
||||
|
||||
@sexp_type('fill')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue