Add sector support
This commit is contained in:
parent
f452167914
commit
760013eecd
2 changed files with 51 additions and 3 deletions
|
|
@ -21,11 +21,12 @@ import os
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import warnings
|
import warnings
|
||||||
|
import math
|
||||||
|
|
||||||
import click
|
import click
|
||||||
from gerbonara.layers import LayerStack
|
from gerbonara.layers import LayerStack
|
||||||
|
|
||||||
from .geometry import PlanarInductor, divisors, CircleShape, TrapezoidShape
|
from .geometry import PlanarInductor, divisors, CircleShape, SectorShape
|
||||||
from .kicad import footprint_to_board
|
from .kicad import footprint_to_board
|
||||||
from .svg import make_transparent_svg
|
from .svg import make_transparent_svg
|
||||||
|
|
||||||
|
|
@ -87,8 +88,10 @@ def cli(ctx, footprint_name, clipboard, single_layer, arc_tolerance, circle_segm
|
||||||
footprint = model.render_footprint(footprint_name, arc_tolerance, circle_segments)
|
footprint = model.render_footprint(footprint_name, arc_tolerance, circle_segments)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise
|
|
||||||
raise click.ClickException(*e.args)
|
raise click.ClickException(*e.args)
|
||||||
|
except:
|
||||||
|
import pdb
|
||||||
|
pdb.post_mortem()
|
||||||
|
|
||||||
data = None
|
data = None
|
||||||
if format == 'kicad-footprint':
|
if format == 'kicad-footprint':
|
||||||
|
|
@ -164,4 +167,18 @@ def circle(ctx, inner_diameter, outer_diameter, outfile):
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def trapezoid(ctx, outfile, **kwargs):
|
def trapezoid(ctx, outfile, **kwargs):
|
||||||
shape = TrapezoidShape(**kwargs)
|
shape = TrapezoidShape(**kwargs)
|
||||||
ctx.obj['write'](shape, outfile)
|
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('--angle', type=float, default=45, help='Sector angle [deg]')
|
||||||
|
@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 sector(ctx, outfile, angle, **kwargs):
|
||||||
|
angle = math.radians(angle)
|
||||||
|
shape = SectorShape(angle=angle, **kwargs)
|
||||||
|
ctx.obj['write'](shape, outfile)
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,8 @@ class OffsetShape(Shape):
|
||||||
def compute_spiral(self, a1, a2, fn=None):
|
def compute_spiral(self, a1, a2, fn=None):
|
||||||
# Skeletonator uses a t coordinate from 0 - 1 per revolution instead of a radian angle.
|
# Skeletonator uses a t coordinate from 0 - 1 per revolution instead of a radian angle.
|
||||||
points = list(self.sk.do_spiral(a1/(2*pi), a2/(2*pi), self.outer_radius, self.inner_radius))
|
points = list(self.sk.do_spiral(a1/(2*pi), a2/(2*pi), self.outer_radius, self.inner_radius))
|
||||||
|
if a2 < a1:
|
||||||
|
points = points[::-1]
|
||||||
arm_length = sum(dist(p1, p2) for p1, p2 in zip(points, points[1:]))
|
arm_length = sum(dist(p1, p2) for p1, p2 in zip(points, points[1:]))
|
||||||
return points, arm_length
|
return points, arm_length
|
||||||
|
|
||||||
|
|
@ -204,6 +206,35 @@ class TrapezoidShape(OffsetShape):
|
||||||
return f'{self.width:.2f} x {self.height:.2f} mm, {self.offset:.2f} mm offset isosceles trapezoidal'
|
return f'{self.width:.2f} x {self.height:.2f} mm, {self.offset:.2f} mm offset isosceles trapezoidal'
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SectorShape(OffsetShape):
|
||||||
|
inner_diameter: float
|
||||||
|
outer_diameter: float
|
||||||
|
angle: float
|
||||||
|
annular_width: float
|
||||||
|
arc_tolerance: float = 0.05 # mm
|
||||||
|
polygon: list = field(init=False)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
# Careful: The inner/outer radius properties are relative to the polygon center and are very different from these!
|
||||||
|
r1, r2 = self.inner_diameter / 2, self.outer_diameter/2
|
||||||
|
n1 = ceil(pi / acos(1 - self.arc_tolerance/self.inner_diameter) * self.angle / (2*pi))
|
||||||
|
n2 = ceil(pi / acos(1 - self.arc_tolerance/self.outer_diameter) * self.angle / (2*pi))
|
||||||
|
# center on y axis
|
||||||
|
pt = lambda r, a: (r*sin(a), r*cos(a))
|
||||||
|
self.polygon = [pt(r2, self.angle/2 - i/n1 * self.angle) for i in range(n1+1)]
|
||||||
|
self.polygon += [pt(r1, i/n1 * self.angle - self.angle/2) for i in range(n1+1)]
|
||||||
|
super().__post_init__()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def slug(self):
|
||||||
|
return f'sector_{self.outer_diameter:.2f}x{self.inner_diameter:.2f}_{degrees(self.angle):.0f}deg'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def desc(self):
|
||||||
|
return f'{self.outer_diameter:.2f} x {self.inner_diameter:.2f} mm {degrees(self.angle):.0f} deg sector'
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PlanarInductor():
|
class PlanarInductor():
|
||||||
shape: Shape
|
shape: Shape
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue