summaryrefslogtreecommitdiff
path: root/gerbonara/cad/kicad
diff options
context:
space:
mode:
Diffstat (limited to 'gerbonara/cad/kicad')
-rw-r--r--gerbonara/cad/kicad/base_types.py39
-rw-r--r--gerbonara/cad/kicad/schematic.py56
-rw-r--r--gerbonara/cad/kicad/symbols.py13
3 files changed, 82 insertions, 26 deletions
diff --git a/gerbonara/cad/kicad/base_types.py b/gerbonara/cad/kicad/base_types.py
index 9acef7b..d29586e 100644
--- a/gerbonara/cad/kicad/base_types.py
+++ b/gerbonara/cad/kicad/base_types.py
@@ -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
diff --git a/gerbonara/cad/kicad/schematic.py b/gerbonara/cad/kicad/schematic.py
index 1a1af9d..00272dd 100644
--- a/gerbonara/cad/kicad/schematic.py
+++ b/gerbonara/cad/kicad/schematic.py
@@ -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):
diff --git a/gerbonara/cad/kicad/symbols.py b/gerbonara/cad/kicad/symbols.py
index 6193b57..4767b88 100644
--- a/gerbonara/cad/kicad/symbols.py
+++ b/gerbonara/cad/kicad/symbols.py
@@ -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')