Speed up protoboard generation
This commit is contained in:
parent
38f766dc42
commit
958b47ab47
7 changed files with 54 additions and 12 deletions
|
|
@ -20,7 +20,7 @@ import math
|
|||
from dataclasses import dataclass, replace, field, fields, InitVar
|
||||
|
||||
from .aperture_macros.parse import GenericMacros
|
||||
from .utils import MM, Inch
|
||||
from .utils import MM, Inch, sum_bounds
|
||||
|
||||
from . import graphic_primitives as gp
|
||||
|
||||
|
|
@ -118,6 +118,9 @@ class Aperture:
|
|||
"""
|
||||
return self._primitives(x, y, unit, polarity_dark)
|
||||
|
||||
def bounding_box(self, unit=None):
|
||||
return sum_bounds((prim.bounding_box() for prim in self.flash(0, 0, unit, True)))
|
||||
|
||||
def equivalent_width(self, unit=None):
|
||||
""" Get the width of a line interpolated using this aperture in the given :py:class:`~.LengthUnit`.
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,9 @@ from ..primitives import Positioned
|
|||
from ... import graphic_primitives as gp
|
||||
from ... import graphic_objects as go
|
||||
from ... import apertures as ap
|
||||
from ...layers import LayerStack
|
||||
from ...newstroke import Newstroke
|
||||
from ...utils import MM, rotate_point
|
||||
from ...utils import MM, rotate_point, offset_bounds, sum_bounds
|
||||
from ...aperture_macros.parse import GenericMacros, ApertureMacro
|
||||
from ...aperture_macros import primitive as amp
|
||||
|
||||
|
|
@ -591,6 +592,7 @@ class Footprint:
|
|||
models: List(Model) = field(default_factory=list)
|
||||
_ : SEXP_END = None
|
||||
original_filename: str = None
|
||||
_bounding_box: tuple = None
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
|
|
@ -701,6 +703,16 @@ class Footprint:
|
|||
layer_stack.drill_npth.append(fe)
|
||||
else:
|
||||
layer_stack.drill_pth.append(fe)
|
||||
|
||||
def bounding_box(self, unit=MM):
|
||||
if not self._bounding_box:
|
||||
stack = LayerStack()
|
||||
layer_map = {kc_id: gn_id for kc_id, gn_id in LAYER_MAP_K2G.items() if gn_id in stack}
|
||||
self.render(stack, layer_map, x=0, y=0, rotation=0, side='top', text=False, variables={})
|
||||
self._bounding_box = stack.bounding_box(unit)
|
||||
return self._bounding_box
|
||||
|
||||
|
||||
|
||||
LAYER_MAP_K2G = {
|
||||
'F.Cu': ('top', 'copper'),
|
||||
|
|
@ -752,6 +764,9 @@ class FootprintInstance(Positioned):
|
|||
side=self.side,
|
||||
text=(not self.hide_text),
|
||||
variables=variables)
|
||||
|
||||
def bounding_box(self, unit=MM):
|
||||
return offset_bounds(self.sexp.bounding_box(unit), unit(self.x, self.unit), unit(self.y, self.unit))
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from itertools import zip_longest, chain
|
|||
from dataclasses import dataclass, field, KW_ONLY
|
||||
from collections import defaultdict
|
||||
|
||||
from ..utils import LengthUnit, MM, rotate_point, svg_arc, sum_bounds, bbox_intersect, Tag
|
||||
from ..utils import LengthUnit, MM, rotate_point, svg_arc, sum_bounds, bbox_intersect, Tag, offset_bounds
|
||||
from ..layers import LayerStack
|
||||
from ..graphic_objects import Line, Arc, Flash
|
||||
from ..apertures import Aperture, CircleAperture, ObroundAperture, RectangleAperture, ExcellonTool
|
||||
|
|
@ -215,6 +215,24 @@ class ObjectGroup(Positioned):
|
|||
fe.offset(x, y, self.unit)
|
||||
target.objects.append(fe)
|
||||
|
||||
def bounding_box(self, unit=MM):
|
||||
if math.isclose(self.rotation, 0, abs_tol=1e-3):
|
||||
return offset_bounds(sum_bounds((obj.bounding_box(unit=unit) for obj in chain(
|
||||
self.top_copper,
|
||||
self.top_mask,
|
||||
self.top_silk,
|
||||
self.top_paste,
|
||||
self.bottom_copper,
|
||||
self.bottom_mask,
|
||||
self.bottom_silk,
|
||||
self.bottom_paste,
|
||||
self.drill_npth,
|
||||
self.drill_pth,
|
||||
self.objects,
|
||||
))), unit(self.x, self.unit), unit(self.y, self.unit))
|
||||
else:
|
||||
return super().bounding_box(unit)
|
||||
|
||||
@property
|
||||
def single_sided(self):
|
||||
any_top = self.top_copper or self.top_mask or self.top_paste or self.top_silk
|
||||
|
|
|
|||
|
|
@ -549,7 +549,7 @@ def _demo():
|
|||
#pattern = PatternProtoArea(2.54*1.5, obj=THTFlowerProto())
|
||||
#pattern = PatternProtoArea(2.54, obj=THTPad.circle(0, 0, 0.9, 1.8, paste=False))
|
||||
#pattern = PatternProtoArea(2.54, obj=PoweredProto())
|
||||
pb = ProtoBoard(30, 30, pattern1, mounting_hole_dia=3.2, mounting_hole_offset=5)
|
||||
pb = ProtoBoard(50, 50, pattern1, mounting_hole_dia=3.2, mounting_hole_offset=5)
|
||||
print(pb.pretty_svg())
|
||||
pb.layer_stack().save_to_directory('/tmp/testdir')
|
||||
|
||||
|
|
|
|||
|
|
@ -598,7 +598,9 @@ input {
|
|||
<template id="tpl-g-spiky">
|
||||
<div data-type="spiky" class="group spiky">
|
||||
<h4>Spiky hybrid area</h4>
|
||||
Layout by <a href="https://social.treehouse.systems/@electronic_eel">electroniceel</a> (<a href="https://github.com/electroniceel/protoboard">github</a>)
|
||||
<div>
|
||||
Layout by <a href="https://social.treehouse.systems/@electronic_eel">electroniceel</a> (<a href="https://github.com/electroniceel/protoboard">github</a>)
|
||||
</div>
|
||||
<span class="content area-controls">(<a href="#" class="area-remove">Remove</a><a href="#" class="area-move">Move</a>)</span>
|
||||
<label class="proportion">Proportion
|
||||
<input type="text" name="layout_prop" value="1">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import copy
|
|||
from dataclasses import dataclass, astuple, field, fields
|
||||
from itertools import zip_longest
|
||||
|
||||
from .utils import MM, InterpMode, to_unit, rotate_point
|
||||
from .utils import MM, InterpMode, to_unit, rotate_point, sum_bounds
|
||||
from . import graphic_primitives as gp
|
||||
from .aperture_macros import primitive as amp
|
||||
|
||||
|
|
@ -152,12 +152,7 @@ class GraphicObject:
|
|||
:returns: tuple of tuples of floats: ``(min_x, min_y), (max_x, max_y)``
|
||||
"""
|
||||
|
||||
bboxes = [ p.bounding_box() for p in self.to_primitives(unit) ]
|
||||
min_x = min(min_x for (min_x, _min_y), _ in bboxes)
|
||||
min_y = min(min_y for (_min_x, min_y), _ in bboxes)
|
||||
max_x = max(max_x for _, (max_x, _max_y) in bboxes)
|
||||
max_y = max(max_y for _, (_max_x, max_y) in bboxes)
|
||||
return ((min_x, min_y), (max_x, max_y))
|
||||
return sum_bounds(p.bounding_box() for p in self.to_primitives(unit))
|
||||
|
||||
def to_primitives(self, unit=None):
|
||||
""" Render this object into low-level graphical primitives (subclasses of :py:class:`.GraphicPrimitive`). This
|
||||
|
|
@ -219,6 +214,10 @@ class Flash(GraphicObject):
|
|||
def tool(self, value):
|
||||
self.aperture = value
|
||||
|
||||
def bounding_box(self, unit=None):
|
||||
(min_x, min_y), (max_x, max_y) = self.aperture.bounding_box(unit)
|
||||
return (min_x+self.x, min_y+self.y), (max_x+self.x, max_x+self.y)
|
||||
|
||||
@property
|
||||
def plated(self):
|
||||
""" (Excellon only) Returns if this is a plated hole. ``True`` (plated), ``False`` (non-plated) or ``None``
|
||||
|
|
|
|||
|
|
@ -264,6 +264,11 @@ def add_bounds(b1, b2):
|
|||
return sum_bounds((b1, b2))
|
||||
|
||||
|
||||
def offset_bounds(bounds, dx=0, dy=0):
|
||||
(min_x, min_y), (max_x, max_y) = bounds
|
||||
return (min_x+dx, min_y+dy), (max_x+dx, max_y+dy)
|
||||
|
||||
|
||||
def sum_bounds(bounds, *, default=None):
|
||||
""" Add/union multiple bounding boxes.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue