Polygon layout works pretty well now, add star shape
This commit is contained in:
parent
5c2db13c3e
commit
299527fa72
3 changed files with 74 additions and 28 deletions
|
|
@ -26,7 +26,7 @@ import math
|
|||
import click
|
||||
from gerbonara.layers import LayerStack
|
||||
|
||||
from .geometry import PlanarInductor, divisors, CircleShape, SectorShape
|
||||
from .geometry import PlanarInductor, divisors, CircleShape, SectorShape, StarShape
|
||||
from .kicad import footprint_to_board
|
||||
from .svg import make_transparent_svg
|
||||
|
||||
|
|
@ -88,7 +88,8 @@ def cli(ctx, footprint_name, clipboard, single_layer, arc_tolerance, circle_segm
|
|||
footprint = model.render_footprint(footprint_name, arc_tolerance, circle_segments)
|
||||
|
||||
except ValueError as e:
|
||||
raise click.ClickException(*e.args)
|
||||
#raise click.ClickException(*e.args)
|
||||
raise
|
||||
|
||||
data = None
|
||||
if format == 'kicad-footprint':
|
||||
|
|
@ -179,3 +180,16 @@ def sector(ctx, outfile, angle, **kwargs):
|
|||
angle = math.radians(angle)
|
||||
shape = SectorShape(angle=angle, **kwargs)
|
||||
ctx.obj['write'](shape, outfile)
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--inner-diameter', type=float, default=25, help='Inner diameter [mm]')
|
||||
@click.option('--outer-diameter', type=float, default=50, help='Outer diameter [mm]')
|
||||
@click.option('--points', type=int, default=5, help='Number of points')
|
||||
@click.option('--arc-tolerance', type=float, default=0.05, help='Tolerance for splitting arc into straight segments [mm] (default: 0.05 mm)')
|
||||
@click.option('--annular-width', type=float, default=5, help='Width of the trace area on the outside of the shape [mm]')
|
||||
@click.argument('outfile', required=False, type=click.Path(writable=True, dir_okay=False, path_type=Path))
|
||||
@click.pass_context
|
||||
def star(ctx, outfile, **kwargs):
|
||||
shape = StarShape(**kwargs)
|
||||
ctx.obj['write'](shape, outfile)
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ class CircleShape(Shape):
|
|||
points.append((xn, yn))
|
||||
dists.append(dist((xp, yp), (xn, yn)))
|
||||
|
||||
return points, sum(dists), None
|
||||
return points, sum(dists), [None]*len(points)
|
||||
|
||||
|
||||
def project_point(self, r, a, r_ref=None):
|
||||
|
|
@ -182,7 +182,7 @@ class OffsetShape(Shape):
|
|||
|
||||
def project_point(self, r, a, r_ref=None):
|
||||
# Skeletonator uses a t coordinate from 0 - 1 per revolution instead of a radian angle.
|
||||
return self.sk.project_point(a/(2*pi), r, r_ref=r_ref)
|
||||
return self.sk.project_point(a/(2*pi) % 1, r, r_ref=r_ref)
|
||||
|
||||
|
||||
def offset_exterior(self, margin):
|
||||
|
|
@ -240,6 +240,32 @@ class SectorShape(OffsetShape):
|
|||
return f'{self.outer_diameter:.2f} x {self.inner_diameter:.2f} mm {degrees(self.angle):.0f} deg sector'
|
||||
|
||||
|
||||
@dataclass
|
||||
class StarShape(OffsetShape):
|
||||
inner_diameter: float
|
||||
outer_diameter: float
|
||||
annular_width: float
|
||||
points: int = 5
|
||||
arc_tolerance: float = 0.05 # mm
|
||||
polygon: list = field(init=False)
|
||||
|
||||
def __post_init__(self):
|
||||
# center on y axis
|
||||
pt = lambda r, a: (-r*sin(a), r*cos(a))
|
||||
circle = lambda r, n, phase: [pt(r, (i + phase)*2*pi/n) for i in range(n)]
|
||||
self.polygon = [x for pair in zip(circle(self.outer_diameter/2, self.points, 0), circle(self.inner_diameter/2, self.points, 0.5)) for x in pair]
|
||||
super().__post_init__()
|
||||
|
||||
@property
|
||||
def slug(self):
|
||||
return f'star_{self.outer_diameter:.2f}x{self.inner_diameter:.2f}'
|
||||
|
||||
@property
|
||||
def desc(self):
|
||||
purpose = ', for demonic purposes' if self.points == 5 else ''
|
||||
return f'{self.outer_diameter:.2f} x {self.inner_diameter:.2f} mm star shape{purpose}'
|
||||
|
||||
|
||||
@dataclass
|
||||
class PlanarInductor():
|
||||
shape: Shape
|
||||
|
|
@ -436,12 +462,14 @@ class PlanarInductor():
|
|||
|
||||
else:
|
||||
# Add a straight connecting segment connecting the inner point to the outside of the spiral.
|
||||
xq, yq = shape.project_point(shape.outer_radius, fold_angle)
|
||||
ref = angle_refs_layer0[-1]
|
||||
xq, yq = self.shape.project_point(self.shape.outer_radius, fold_angle, r_ref=ref)
|
||||
angle_refs_layer1 = [ref, ref]
|
||||
points_layer1 = [(xn, yn), (xq, yq)]
|
||||
footprint.lines.append(kicad.make_line(xn, yn, xq, yq, self.trace_width, self.layer_pair[1]))
|
||||
|
||||
arms_layers[0].append(points_layer0)
|
||||
arms_layers[1].append(points_layer1)
|
||||
arms_layers[0].append((points_layer0, angle_refs_layer0))
|
||||
arms_layers[1].append((points_layer1, angle_refs_layer1))
|
||||
|
||||
for i in range(self.twists):
|
||||
start_angle = i*self.sector_angle
|
||||
|
|
@ -454,11 +482,13 @@ class PlanarInductor():
|
|||
if i%2 != 0:
|
||||
r -= 2*self.via_offset
|
||||
|
||||
xv, yv = self.shape.project_point(r, fold_angle, r_ref=ref_n)
|
||||
points_layer0, refs_layer0 = arms_layers[0][i]
|
||||
points_layer1, refs_layer1 = arms_layers[1][i]
|
||||
|
||||
if self.via_offset:
|
||||
footprint.lines.append(kicad.make_line(*arms_layers[0][i][-1], xv, yv, self.trace_width, self.layer_pair[0]))
|
||||
footprint.lines.append(kicad.make_line(xv, yv, *arms_layers[1][i][0], self.trace_width, self.layer_pair[1]))
|
||||
xv, yv = self.shape.project_point(r, fold_angle, r_ref=refs_layer0[-1])
|
||||
|
||||
footprint.lines.append(kicad.make_line(*points_layer0[-1], xv, yv, self.trace_width, self.layer_pair[0]))
|
||||
footprint.lines.append(kicad.make_line(xv, yv, *points_layer1[0], self.trace_width, self.layer_pair[1]))
|
||||
|
||||
footprint.pads.append(kicad.make_via(xv, yv,
|
||||
self.via_diameter, self.via_drill, self.clearance,
|
||||
|
|
@ -466,19 +496,21 @@ class PlanarInductor():
|
|||
|
||||
# Handle outer via ring and process staggering if enabled unless we are at the start of the coil, where we will
|
||||
# place pads below.
|
||||
r = self.outer_via_ring_radius
|
||||
|
||||
if self.stagger_outer_vias:
|
||||
if i%2 != 0:
|
||||
r += 2*self.via_offset
|
||||
|
||||
points_layer0, refs_layer0 = arms_layers[0][i]
|
||||
points_layer1, refs_layer1 = arms_layers[1][(i - self.turns) % self.twists]
|
||||
|
||||
xv, yv = self.shape.project_point(r, start_angle, r_ref=refs_layer0[0])
|
||||
|
||||
footprint.lines.append(kicad.make_line(*points_layer0[0], xv, yv, self.trace_width, self.layer_pair[0]))
|
||||
footprint.lines.append(kicad.make_line(*points_layer1[-1], xv, yv, self.trace_width, self.layer_pair[1]))
|
||||
|
||||
if i > 0:
|
||||
r = self.outer_via_ring_radius
|
||||
|
||||
if self.stagger_outer_vias:
|
||||
if i%2 != 0:
|
||||
r += 2*self.via_offset
|
||||
|
||||
xv, yv = self.shape.project_point(r, start_angle, r_ref=ref_0)
|
||||
|
||||
if self.via_offset:
|
||||
footprint.lines.append(kicad.make_line(*arms_layers[0][i][0], xv, yv, self.trace_width, self.layer_pair[0]))
|
||||
footprint.lines.append(kicad.make_line(*arms_layers[1][(i - self.turns) % self.twists][-1], xv, yv, self.trace_width, self.layer_pair[1]))
|
||||
|
||||
footprint.pads.append(kicad.make_via(xv, yv,
|
||||
self.via_diameter, self.via_drill, self.clearance,
|
||||
self.layer_pair))
|
||||
|
|
|
|||
|
|
@ -122,8 +122,8 @@ class Skeletonator:
|
|||
t_end = t_start + 1
|
||||
r_outer = r_interpolate(t_start)
|
||||
r_inner = r_interpolate(t_end)
|
||||
oc_arcs, outer_circumference = self.map_circumference(r_outer)
|
||||
ic_arcs, inner_circumference = self.map_circumference(r_inner)
|
||||
r_ref = min(r_inner, r_outer) # Handle outward spirals where the radii are swapped
|
||||
_ic_arcs, inner_circumference = self.map_circumference(r_ref)
|
||||
|
||||
angle = t_start
|
||||
circumference_angles = []
|
||||
|
|
@ -142,8 +142,8 @@ class Skeletonator:
|
|||
_arc, p2_proj = self.project_arc(p2, rp2)
|
||||
|
||||
if approx_in_range(t1, tp1, tp2):
|
||||
yield interpolate(p1_proj, p2_proj, t1, tp1, tp2), r_inner
|
||||
yield interpolate(p1_proj, p2_proj, t1, tp1, tp2), r_ref
|
||||
if approx_in_range(t2, tp1, tp2):
|
||||
yield interpolate(p1_proj, p2_proj, t2, tp1, tp2), r_inner
|
||||
yield interpolate(p1_proj, p2_proj, t2, tp1, tp2), r_ref
|
||||
elif approx_in_range(tp2, t1, t2):
|
||||
yield p2_proj, r_inner
|
||||
yield p2_proj, r_ref
|
||||
Loading…
Add table
Add a link
Reference in a new issue