55
66from __future__ import annotations
77
8+ from abc import ABC
89from collections .abc import Iterable
910from math import isclose
10- from typing import TYPE_CHECKING
11+ from typing import TYPE_CHECKING , override
1112
1213from build123d import (
1314 Align ,
1718 BuildLine ,
1819 BuildPart ,
1920 BuildSketch ,
21+ Edge ,
2022 Line ,
2123 Mode ,
2224 Plane ,
2325 RotationLike ,
24- add ,
26+ Shape ,
27+ add , # pyright: ignore[reportUnknownVariableType]
2528 extrude ,
2629 fillet ,
2730 make_face ,
3437 from gridfinity_build123d .features import Feature
3538
3639
37- class BasePlateBlock (ObjectCreate ):
40+ class BasePlateBlock (ObjectCreate , ABC ):
3841 """Single base plate block used to construct a bigger baseplate."""
3942
4043 def __init__ (
@@ -50,7 +53,7 @@ def __init__(
5053 if not features :
5154 features = []
5255
53- self .features = features if isinstance (features , Iterable ) else [features ]
56+ self .features : list [ Feature ] = features if isinstance (features , Iterable ) else [features ]
5457
5558
5659class BasePlateBlockFrame (BasePlateBlock ):
@@ -61,6 +64,7 @@ class BasePlateBlockFrame(BasePlateBlock):
6164 features. Defaults to None.
6265 """
6366
67+ @override
6468 def create_obj (
6569 self ,
6670 rotation : RotationLike = (0 , 0 , 0 ),
@@ -69,20 +73,28 @@ def create_obj(
6973 ) -> BasePartObject :
7074 """Overwrites BasePlateBlock.create_obj."""
7175 with BuildPart () as block :
72- Utils .create_profile_block (StackProfile .ProfileType .PLATE )
76+ _ = Utils .create_profile_block (StackProfile .ProfileType .PLATE )
77+
78+ if not block .part :
79+ msg = "block is empty"
80+ raise RuntimeError (msg )
7381
7482 with BuildPart () as part :
75- Box (
83+ _ = Box (
7684 42 ,
7785 42 ,
7886 block .part .bounding_box ().size .Z ,
7987 align = (Align .CENTER , Align .CENTER , Align .MIN ),
8088 )
81- add (block .part , mode = Mode .SUBTRACT )
89+ _ = add (block .part , mode = Mode .SUBTRACT )
8290
8391 for feature in self .features :
8492 feature .apply (part )
8593
94+ if not part .part :
95+ msg = "Part is empty"
96+ raise RuntimeError (msg )
97+
8698 return BasePartObject (part .part , rotation , align , mode )
8799
88100
@@ -102,9 +114,10 @@ def __init__(
102114 features. Defaults to None.
103115 """
104116 super ().__init__ (features )
105- self .bottom_height = bottom_height
117+ self .bottom_height : float = bottom_height
106118
107- def create_obj ( # noqa: D102
119+ @override
120+ def create_obj (
108121 self ,
109122 rotation : RotationLike = (0 , 0 , 0 ),
110123 align : Align | tuple [Align , Align , Align ] | None = None ,
@@ -114,21 +127,26 @@ def create_obj( # noqa: D102
114127 frame = BasePlateBlockFrame ().create_obj (mode = Mode .PRIVATE )
115128 with BuildSketch ():
116129 bot_face = frame .faces ().sort_by (Axis .Z )[0 ]
117- make_face (bot_face .outer_wire ())
118- extrude (amount = self .bottom_height , dir = (0 , 0 , - 1 ))
130+ _ = make_face (bot_face .outer_wire (). edges ())
131+ _ = extrude (amount = self .bottom_height , dir = (0 , 0 , - 1 ))
119132
120133 for feature in self .features :
121134 feature .apply (part )
122135
123- add (frame )
136+ _ = add (frame )
137+
138+ if not part .part :
139+ msg = "Part is empty"
140+ raise RuntimeError (msg )
124141
125142 return BasePartObject (part .part , rotation , align , mode )
126143
127144
128145class BasePlateBlockSkeleton (BasePlateBlockFull ):
129146 """Placeholder for future skeletonized baseplate."""
130147
131- def create_obj ( # noqa: D102
148+ @override
149+ def create_obj (
132150 self ,
133151 rotation : RotationLike = (0 , 0 , 0 ),
134152 align : Align | tuple [Align , Align , Align ] | None = None ,
@@ -141,20 +159,25 @@ def create_obj( # noqa: D102
141159 length_l = length / 2
142160
143161 with BuildPart () as part :
144- super ().create_obj ()
162+ _ = super ().create_obj ()
145163 with BuildSketch ():
146164 with BuildLine () as line :
147165 ln1 = Line ((0 , length_l ), (length_s , length_l ))
148166 ln2 = Line (ln1 @ 1 , (length_s , length_s ))
149167 ln3 = Line (ln2 @ 1 , (length_l , length_s ))
150- Line (ln3 @ 1 , (length_l , 0 ))
151- vertex = line .vertices ().sort_by_distance ((length / 4 , length / 4 ))[0 ]
152- fillet (vertex , radius )
153- mirror (about = Plane .XZ )
154- mirror (about = Plane .YZ )
155-
156- make_face ()
157- extrude (amount = - self .bottom_height , mode = Mode .SUBTRACT )
168+ _ = Line (ln3 @ 1 , (length_l , 0 ))
169+ vertex = line .vertices ().sort_by_distance ((length / 4 , length / 4 ))[0 ] # pyright: ignore[reportUnknownMemberType]
170+ _ = fillet (vertex , radius )
171+ _ = mirror (about = Plane .XZ )
172+ _ = mirror (about = Plane .YZ )
173+
174+ _ = make_face ()
175+ _ = extrude (amount = - self .bottom_height , mode = Mode .SUBTRACT )
176+
177+ if not part .part :
178+ msg = "Part is empty"
179+ raise RuntimeError (msg )
180+
158181 return BasePartObject (part .part , rotation , align , mode )
159182
160183
@@ -190,19 +213,27 @@ def __init__(
190213 if not features :
191214 features = []
192215
193- self .features = features if isinstance (features , Iterable ) else [features ]
216+ self .features : list [ Feature ] = features if isinstance (features , Iterable ) else [features ]
194217
195218 with BuildPart () as part :
196- Utils .place_by_grid (baseplate_block .create_obj (mode = Mode .PRIVATE ), grid )
219+ _ = Utils .place_by_grid (baseplate_block .create_obj (mode = Mode .PRIVATE ), grid )
220+
221+ if not part .part :
222+ msg = "Part is empty"
223+ raise RuntimeError (msg )
197224
198225 z_height = part .part .bounding_box ().size .Z
199226
200- wires = (
201- part .edges ()
202- .filter_by (Axis .Z )
203- .filter_by (lambda edge : isclose (edge .length , z_height ))
204- )
205- fillet (wires , 4 )
227+ def edge_filter (shape : Shape [Edge ]) -> bool :
228+ inner_edge = shape .edge ()
229+ if not inner_edge :
230+ msg = "Edge is empty"
231+ raise RuntimeError (msg )
232+
233+ return isclose (inner_edge .length , z_height )
234+
235+ wires = part .edges ().filter_by (Axis .Z ).filter_by (edge_filter )
236+ _ = fillet (wires , 4 )
206237
207238 for feature in self .features :
208239 feature .apply (part )
0 commit comments