Fixing more tests
This commit is contained in:
parent
bda404c18b
commit
5a41d96fe3
5 changed files with 49 additions and 22 deletions
|
|
@ -13,6 +13,7 @@ from . import primitive as ap
|
|||
from .expression import *
|
||||
from ..utils import MM
|
||||
|
||||
# we make our own here instead of using math.degrees to make sure this works with expressions, too.
|
||||
def rad_to_deg(x):
|
||||
return (x / math.pi) * 180
|
||||
|
||||
|
|
@ -190,6 +191,7 @@ class GenericMacros:
|
|||
*_generic_hole(4)])
|
||||
|
||||
# w must be larger than h
|
||||
# params: width, height, *hole, rotation
|
||||
obround = ApertureMacro('GNO', [
|
||||
ap.CenterLine('mm', [1, var(1), var(2), 0, 0, var(5) * -deg_per_rad]),
|
||||
ap.Circle('mm', [1, var(2), +var(1)/2, 0, var(5) * -deg_per_rad]),
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from .expression import Expression, UnitExpression, ConstantExpression, expr
|
|||
|
||||
from .. import graphic_primitives as gp
|
||||
from .. import graphic_objects as go
|
||||
from ..utils import rotate_point
|
||||
|
||||
|
||||
def point_distance(a, b):
|
||||
|
|
@ -20,9 +21,11 @@ def point_distance(a, b):
|
|||
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
|
||||
|
||||
|
||||
# we make our own here instead of using math.degrees to make sure this works with expressions, too.
|
||||
def deg_to_rad(a):
|
||||
return a * (math.pi / 180)
|
||||
|
||||
|
||||
def rad_to_deg(a):
|
||||
return a * (180 / math.pi)
|
||||
|
||||
|
|
@ -92,7 +95,7 @@ class Circle(Primitive):
|
|||
|
||||
def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True):
|
||||
with self.Calculator(self, variable_binding, unit) as calc:
|
||||
x, y = gp.rotate_point(calc.x, calc.y, deg_to_rad(calc.rotation) + rotation, 0, 0)
|
||||
x, y = rotate_point(calc.x, calc.y, deg_to_rad(calc.rotation) + rotation, 0, 0)
|
||||
x, y = x+offset[0], y+offset[1]
|
||||
return [ gp.Circle(x, y, calc.diameter/2, polarity_dark=(bool(calc.exposure) == polarity_dark)) ]
|
||||
|
||||
|
|
@ -123,6 +126,7 @@ class VectorLine(Primitive):
|
|||
delta_y = calc.end_y - calc.start_y
|
||||
length = point_distance((calc.start_x, calc.start_y), (calc.end_x, calc.end_y))
|
||||
|
||||
center_x, center_y = rotate_point(center_x, center_y, deg_to_rad(calc.rotation) + rotation, 0, 0)
|
||||
center_x, center_y = center_x+offset[0], center_y+offset[1]
|
||||
rotation += deg_to_rad(calc.rotation) + math.atan2(delta_y, delta_x)
|
||||
|
||||
|
|
@ -181,7 +185,7 @@ class Polygon(Primitive):
|
|||
def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True):
|
||||
with self.Calculator(self, variable_binding, unit) as calc:
|
||||
rotation += deg_to_rad(calc.rotation)
|
||||
x, y = gp.rotate_point(calc.x, calc.y, rotation, 0, 0)
|
||||
x, y = rotate_point(calc.x, calc.y, rotation, 0, 0)
|
||||
x, y = x+offset[0], y+offset[1]
|
||||
return [ gp.ArcPoly.from_regular_polygon(calc.x, calc.y, calc.diameter/2, calc.n_vertices, rotation,
|
||||
polarity_dark=(bool(calc.exposure) == polarity_dark)) ]
|
||||
|
|
@ -209,7 +213,7 @@ class Thermal(Primitive):
|
|||
def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True):
|
||||
with self.Calculator(self, variable_binding, unit) as calc:
|
||||
rotation += deg_to_rad(calc.rotation)
|
||||
x, y = gp.rotate_point(calc.x, calc.y, rotation, 0, 0)
|
||||
x, y = rotate_point(calc.x, calc.y, rotation, 0, 0)
|
||||
x, y = x+offset[0], y+offset[1]
|
||||
|
||||
dark = (bool(calc.exposure) == polarity_dark)
|
||||
|
|
@ -271,7 +275,7 @@ class Outline(Primitive):
|
|||
def to_graphic_primitives(self, offset, rotation, variable_binding={}, unit=None, polarity_dark=True):
|
||||
with self.Calculator(self, variable_binding, unit) as calc:
|
||||
rotation += deg_to_rad(calc.rotation)
|
||||
bound_coords = [ gp.rotate_point(calc(x), calc(y), rotation, 0, 0) for x, y in self.coords ]
|
||||
bound_coords = [ rotate_point(calc(x), calc(y), rotation, 0, 0) for x, y in self.coords ]
|
||||
bound_coords = [ (x+offset[0], y+offset[1]) for x, y in bound_coords ]
|
||||
bound_radii = [None] * len(bound_coords)
|
||||
return [gp.ArcPoly(bound_coords, bound_radii, polarity_dark=(bool(calc.exposure) == polarity_dark))]
|
||||
|
|
|
|||
|
|
@ -392,8 +392,8 @@ class ObroundAperture(Aperture):
|
|||
return ApertureMacroInstance(GenericMacros.obround,
|
||||
[MM(inst.w, self.unit),
|
||||
MM(inst.h, self.unit),
|
||||
MM(inst.hole_dia, self.unit),
|
||||
MM(inst.hole_rect_h, self.unit),
|
||||
MM(inst.hole_dia, self.unit) or 0,
|
||||
MM(inst.hole_rect_h, self.unit) or 0,
|
||||
inst.rotation])
|
||||
|
||||
def _params(self, unit=None):
|
||||
|
|
|
|||
|
|
@ -24,8 +24,9 @@ from ... import graphic_primitives as gp
|
|||
from ... import graphic_objects as go
|
||||
from ... import apertures as ap
|
||||
from ...newstroke import Newstroke
|
||||
from ...utils import MM
|
||||
from ...utils import MM, rotate_point
|
||||
from ...aperture_macros.parse import GenericMacros, ApertureMacro
|
||||
from ...aperture_macros import primitive as amp
|
||||
|
||||
|
||||
@sexp_type('property')
|
||||
|
|
@ -113,10 +114,10 @@ class Rectangle:
|
|||
x2, y2 = self.end.x, self.end.y
|
||||
x1, x2 = min(x1, x2), max(x1, x2)
|
||||
y1, y2 = min(y1, y2), max(y1, y2)
|
||||
w, h = x2-x1, y1-y2
|
||||
w, h = x2-x1, y2-y1
|
||||
|
||||
if self.fill == Atom.solid:
|
||||
yield go.Region.from_rectangle(x1, y1, w, y, unit=MM)
|
||||
yield go.Region.from_rectangle(x1, y1, w, h, unit=MM)
|
||||
|
||||
dasher = Dasher(self)
|
||||
dasher.move(x1, y1)
|
||||
|
|
@ -364,21 +365,27 @@ class Pad:
|
|||
options: OmitDefault(CustomPadOptions) = None
|
||||
primitives: OmitDefault(CustomPadPrimitives) = None
|
||||
|
||||
def render(self, variables=None):
|
||||
def render(self, variables=None, margin=None):
|
||||
#if self.type in (Atom.connect, Atom.np_thru_hole):
|
||||
# return
|
||||
if self.drill and self.drill.offset:
|
||||
ox, oy = rotate_point(self.drill.offset.x, self.drill.offset.y, math.radians(self.at.rotation))
|
||||
else:
|
||||
ox, oy = 0, 0
|
||||
|
||||
yield go.Flash(self.at.x, self.at.y, self.aperture(), unit=MM)
|
||||
yield go.Flash(self.at.x+ox, self.at.y+oy, self.aperture(margin), unit=MM)
|
||||
|
||||
def aperture(self, margin=None):
|
||||
rotation = -math.radians(self.at.rotation)
|
||||
|
||||
def aperture(self):
|
||||
if self.shape == Atom.circle:
|
||||
return ap.CircleAperture(self.size.x, unit=MM)
|
||||
|
||||
elif self.shape == Atom.rect:
|
||||
return ap.RectangleAperture(self.size.x, self.size.y, unit=MM).rotated(self.at.rotation)
|
||||
return ap.RectangleAperture(self.size.x, self.size.y, unit=MM).rotated(rotation)
|
||||
|
||||
elif self.shape == Atom.oval:
|
||||
return ap.ObroundAperture(self.size.x, self.size.y, unit=MM).rotated(self.at.rotation)
|
||||
return ap.ObroundAperture(self.size.x, self.size.y, unit=MM).rotated(rotation)
|
||||
|
||||
elif self.shape == Atom.trapezoid:
|
||||
# KiCad's trapezoid aperture "rect_delta" param is just weird to the point that I think it's probably
|
||||
|
|
@ -386,14 +393,17 @@ class Pad:
|
|||
# original bounding box, and the trapezoid's base and tip length are 3mm and 1mm.
|
||||
|
||||
x, y = self.size.x, self.size.y
|
||||
dx, dy = self.rect_delta.x, self.rect_delta.y
|
||||
if self.rect_delta:
|
||||
dx, dy = self.rect_delta.x, self.rect_delta.y
|
||||
else: # RF_Antenna/Pulse_W3011 has trapezoid pads w/o rect_delta, which KiCad renders as plain rects.
|
||||
dx, dy = 0, 0
|
||||
|
||||
# Note: KiCad already uses MM units, so no conversion needed here.
|
||||
return ap.ApertureMacroInstance(GenericMacros.isosceles_trapezoid,
|
||||
[x+dx, y+dy,
|
||||
2*max(dx, dy),
|
||||
0, 0, # no hole
|
||||
math.radians(self.at.rotation)], unit=MM)
|
||||
rotation], unit=MM)
|
||||
|
||||
elif self.shape == Atom.roundrect:
|
||||
x, y = self.size.x, self.size.y
|
||||
|
|
@ -402,7 +412,7 @@ class Pad:
|
|||
[x, y,
|
||||
r,
|
||||
0, 0, # no hole
|
||||
math.radians(self.at.rotation)], unit=MM)
|
||||
rotation], unit=MM)
|
||||
|
||||
elif self.shape == Atom.custom:
|
||||
primitives = []
|
||||
|
|
@ -410,7 +420,16 @@ class Pad:
|
|||
for obj in self.primitives.all():
|
||||
for gn_obj in obj.render():
|
||||
primitives += gn_obj._aperture_macro_primitives() # todo: precision params
|
||||
macro = ApertureMacro(primitives=primitives).rotated(self.at.rotation)
|
||||
|
||||
if self.options:
|
||||
if self.options.anchor == Atom.rect and self.size.x > 0 and self.size.y > 0:
|
||||
primitives.append(amp.CenterLine(MM, [1, self.size.x, self.size.y, 0, 0, 0]))
|
||||
|
||||
elif self.options.anchor == Atom.circle and self.size.x > 0:
|
||||
primitives.append(amp.Circle(MM, [1, self.size.x, 0, 0, 0]))
|
||||
|
||||
|
||||
macro = ApertureMacro(primitives=primitives).rotated(rotation)
|
||||
return ap.ApertureMacroInstance(macro, unit=MM)
|
||||
|
||||
def render_drill(self):
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ def test_round_trip(kicad_mod_file):
|
|||
assert original == stage1
|
||||
|
||||
|
||||
# Regrettably, we have to re-implement a significant part of the SVG spec to fix up the SVGs that kicad-cli produces.
|
||||
|
||||
def _compute_style(elem):
|
||||
current_style = {}
|
||||
for elem in [*reversed(list(elem.parents)), elem]:
|
||||
|
|
@ -187,14 +189,14 @@ def test_render(kicad_mod_file, tmpfile, print_on_error):
|
|||
|
||||
layer = stack[('top', 'courtyard')]
|
||||
bounds = []
|
||||
print('===== BOUNDS =====')
|
||||
#print('===== BOUNDS =====')
|
||||
for obj in layer.objects:
|
||||
if isinstance(obj, (go.Line, go.Arc)):
|
||||
bbox = (min_x, min_y), (max_x, max_y) = obj.bounding_box(unit=MM)
|
||||
import textwrap
|
||||
print(f'{min_x: 3.6f} {min_y: 3.6f} {max_x: 3.6f} {max_y: 3.6f}', '\n'.join(textwrap.wrap(str(obj), width=80, subsequent_indent=' '*(3+4*(3+1+6)))))
|
||||
#import textwrap
|
||||
#print(f'{min_x: 3.6f} {min_y: 3.6f} {max_x: 3.6f} {max_y: 3.6f}', '\n'.join(textwrap.wrap(str(obj), width=80, subsequent_indent=' '*(3+4*(3+1+6)))))
|
||||
bounds.append(bbox)
|
||||
print('===== END =====')
|
||||
#print('===== END =====')
|
||||
|
||||
if not bounds:
|
||||
print('Footprint has no paths on courtyard layer')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue