Skip to content

Commit

Permalink
Merge pull request #136 from LibrePCB/update-dfn
Browse files Browse the repository at this point in the history
dfn: Migrate to entity classes, improve, generate 3D models
  • Loading branch information
ubruhin authored Nov 17, 2024
2 parents 4dd71a9 + bd4be12 commit 81256d5
Show file tree
Hide file tree
Showing 5 changed files with 1,716 additions and 204 deletions.
37 changes: 0 additions & 37 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,43 +97,6 @@ def indent(level: int, lines: Iterable[str]) -> List[str]:
return [' ' * level + line for line in lines]


def generate_courtyard(
uuid: str,
max_x: float,
max_y: float,
excess_x: float,
excess_y: float,
) -> List[str]:
"""
Generate a rectangular courtyard polygon.
Args:
uuid:
The polygon UUID
max_x:
The half width (x) of the maximum boundary
max_y:
The half height (y) of the maximum boundary
excess_x:
Courtyard excess in x direction
excess_y:
Courtyard excess in y direction
"""
dx = format_float(max_x + excess_x)
dy = format_float(max_y + excess_y)
return [
'(polygon {} (layer {})'.format(uuid, 'top_courtyard'),
' (width {}) (fill false) (grab_area false)'.format(0.0),
' (vertex (position -{} {}) (angle 0.0))'.format(dx, dy), # NW
' (vertex (position {} {}) (angle 0.0))'.format(dx, dy), # NE
' (vertex (position {} -{}) (angle 0.0))'.format(dx, dy), # SE
' (vertex (position -{} -{}) (angle 0.0))'.format(dx, dy), # SW
' (vertex (position -{} {}) (angle 0.0))'.format(dx, dy), # NW
')',
]


def sign(val: Union[int, float]) -> int:
"""
Return 1 for positive or zero values, -1 otherwise.
Expand Down
76 changes: 67 additions & 9 deletions dfn_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"""

from typing import Callable, List, Optional
from typing import Any, Callable, Optional, Tuple

from common import format_float as ff
from entities.common import Angle, Circle, Diameter, Fill, GrabArea, Layer, Polygon, Position, Vertex, Width
from entities.package import Footprint

# Maximal lead width as a function of pitch, Table 4 in the JEDEC
# standard MO-229F, available (with registration!) from
Expand All @@ -31,6 +32,9 @@
0.35: 0.25
}

# The real CadQuery types are not known statically, thus allowing any type.
StepModificationFn = Callable[[Any, Any, Any], Tuple[Any, Any]]


class DfnConfig:
def __init__(self,
Expand All @@ -51,7 +55,8 @@ def __init__(self,
create_date: Optional[str] = None,
library: Optional[str] = None,
pin1_corner_dx_dy: Optional[float] = None, # Some parts have a triangular pin1 marking
extended_doc_fn: Optional[Callable[['DfnConfig', Callable[[str], str], List[str]], None]] = None,
extended_doc_fn: Optional[Callable[['DfnConfig', Callable[[str], str], Footprint], None]] = None,
step_modification_fn: Optional[StepModificationFn] = None,
):
self.length = length
self.width = width
Expand Down Expand Up @@ -83,6 +88,7 @@ def __init__(self,
self.library = library or "LibrePCB_Base.lplib"

self.extended_doc_fn = extended_doc_fn
self.step_modification_fn = step_modification_fn


JEDEC_CONFIGS = [
Expand Down Expand Up @@ -270,14 +276,60 @@ def __init__(self,
]


def draw_circle(diameter: float) -> Callable[[DfnConfig, Callable[[str], str], List[str]], None]:
def _draw(config: DfnConfig, uuid: Callable[[str], str], lines: List[str]) -> None:
lines.append(' (circle {} (layer top_documentation)'.format(uuid('hole-circle-doc')))
lines.append(' (width 0.1) (fill false) (grab_area false) (diameter {}) (position 0.0 0.0)'.format(ff(diameter)))
lines.append(' )')
def draw_circle(diameter: float) -> Callable[[DfnConfig, Callable[[str], str], Footprint], None]:
def _draw(config: DfnConfig, uuid: Callable[[str], str], footprint: Footprint) -> None:
footprint.add_circle(Circle(
uuid('hole-circle-doc'),
Layer('top_documentation'),
Width(0.1),
Fill(False),
GrabArea(False),
Diameter(diameter),
Position(0, 0),
))
return _draw


def draw_rect(x: float, y: float, width: float, height: float) -> Callable[[DfnConfig, Callable[[str], str], Footprint], None]:
def _draw(config: DfnConfig, uuid: Callable[[str], str], footprint: Footprint) -> None:
footprint.add_polygon(Polygon(
uuid=uuid('hole-polygon-doc'),
layer=Layer('top_documentation'),
width=Width(0),
fill=Fill(True),
grab_area=GrabArea(False),
vertices=[
Vertex(Position(x - width / 2, y + height / 2), Angle(0)),
Vertex(Position(x + width / 2, y + height / 2), Angle(0)),
Vertex(Position(x + width / 2, y - height / 2), Angle(0)),
Vertex(Position(x - width / 2, y - height / 2), Angle(0)),
Vertex(Position(x - width / 2, y + height / 2), Angle(0)),
],
))
return _draw


def step_modification_sphere(diameter: float) -> StepModificationFn:
def _fn(body: Any, dot: Any, workplane: Any) -> Tuple[Any, Any]:
return body.cut(workplane.sphere(diameter / 2, centered=True)), dot
return _fn


def step_modification_cylinder(x: float, y: float, diameter: float, length: float) -> StepModificationFn:
def _fn(body: Any, dot: Any, workplane: Any) -> Tuple[Any, Any]:
cutout = workplane.transformed(offset=(x, y, 0), rotate=(0, 90, 0)) \
.cylinder(length, diameter / 2, centered=True)
return body.cut(cutout), dot
return _fn


def step_modification_sgp3x(body: Any, dot: Any, workplane: Any) -> Tuple[Any, Any]:
dot = workplane.cylinder(0.2, 0.6, centered=[True, True, False]) \
.transformed(offset=(0.5, 0.5, 0), rotate=(0, 0, 45)) \
.box(0.3, 0.3, 0.3, centered=[True, True, False])
return body, dot


THIRD_CONFIGS = [
# length, width, pitch, pin_count, height_nominal, height_max, lead_length, exposed_width, exposed_length, keywords

Expand All @@ -300,6 +352,7 @@ def _draw(config: DfnConfig, uuid: Callable[[str], str], lines: List[str]) -> No
no_exp=False,
pin1_corner_dx_dy=0.2,
extended_doc_fn=draw_circle(diameter=0.9),
step_modification_fn=step_modification_sphere(0.9),
),
DfnConfig(
length=3.0,
Expand All @@ -318,6 +371,8 @@ def _draw(config: DfnConfig, uuid: Callable[[str], str], lines: List[str]) -> No
library="Sensirion.lplib",
no_exp=False,
pin1_corner_dx_dy=0.2,
extended_doc_fn=draw_rect(x=0, y=-0.7, width=2.2, height=0.6),
step_modification_fn=step_modification_cylinder(x=0, y=-0.7, diameter=0.6, length=2.2),
),
DfnConfig(
length=2.45,
Expand All @@ -331,11 +386,13 @@ def _draw(config: DfnConfig, uuid: Callable[[str], str], lines: List[str]) -> No
exposed_width=1.7,
exposed_length=1.25,
keywords='sensirion,sgp,sgp30,sgpc3',
name='SENSIRION_SGPxx',
name='SENSIRION_SGP30_SGPC3', # SGP4x needs different 3D model
create_date='2019-12-27T19:39:48Z',
library="Sensirion.lplib",
no_exp=False,
pin1_corner_dx_dy=0.3,
extended_doc_fn=draw_circle(diameter=1.1),
step_modification_fn=step_modification_sgp3x,
),

# Microchip
Expand All @@ -350,6 +407,7 @@ def _draw(config: DfnConfig, uuid: Callable[[str], str], lines: List[str]) -> No
exposed_width=1.45,
exposed_length=1.75,
keywords='microchip mc',
create_date='2020-11-01T17:32:01Z',
no_exp=False,
),
]
2 changes: 1 addition & 1 deletion entities/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def generate_courtyard(
Vertex(Position(dx, dy), Angle(0)), # NE
Vertex(Position(dx, -dy), Angle(0)), # SE
Vertex(Position(-dx, -dy), Angle(0)), # SW
Vertex(Position(-dx, dy), Angle(0)), # NW
# Note: Coultyards are implicitly closed, no 5th vertex needed.
],
)

Expand Down
Loading

0 comments on commit 81256d5

Please sign in to comment.