From 95e897da25abf80facefbe8637584527b3a20c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Mr=C3=A1zek?= Date: Wed, 28 Dec 2022 19:07:40 +0100 Subject: [PATCH] Implement panel sizing constraints --- kikit/panelize.py | 45 ++++++++++++++++---- kikit/panelize_ui_impl.py | 12 ++++-- kikit/panelize_ui_sections.py | 8 ++++ kikit/resources/panelizePresets/default.json | 2 + 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/kikit/panelize.py b/kikit/panelize.py index 94612163..fb557fb5 100644 --- a/kikit/panelize.py +++ b/kikit/panelize.py @@ -32,6 +32,9 @@ class PanelError(RuntimeError): pass +class TooLargeError(PanelError): + pass + def identity(x): return x @@ -1127,7 +1130,8 @@ def makeGrid(self, boardfile: str, sourceArea: wxRect, rows: int, cols: int, return self.substrates[substrateCount:] def makeFrame(self, width: KiLength, hspace: KiLength, vspace: KiLength, - minWidth: KiLength=0, minHeight: KiLength=0) \ + minWidth: KiLength = 0, minHeight: KiLength = 0, + maxWidth: Optional[KiLength] = None, maxHeight: Optional[KiLength] = None) \ -> Tuple[Iterable[LineString], Iterable[LineString]]: """ Build a frame around the boards. Specify width and spacing between the @@ -1148,9 +1152,21 @@ def makeFrame(self, width: KiLength, hspace: KiLength, vspace: KiLength, minHeight - if the panel doesn't meet this height, it is extended + maxWidth - if the panel doesn't meet this width, TooLargeError is raised + + maxHeight - if the panel doesn't meet this height, TooLargeHeight is raised """ frameInnerRect = expandRect(shpBoxToRect(self.boardsBBox()), hspace, vspace) frameOuterRect = expandRect(frameInnerRect, width) + + sizeErrors = [] + if maxWidth is not None and frameOuterRect.GetWidth() > maxWidth: + sizeErrors.append(f"Panel width {frameOuterRect.GetWidth() / units.mm} mm exceeds the limit {maxWidth / units.mm} mm") + if maxHeight is not None and frameOuterRect.GetHeight() > maxHeight: + sizeErrors.append(f"Panel height {frameOuterRect.GetHeight() / units.mm} mm exceeds the limit {maxHeight / units.mm} mm") + if len(sizeErrors) > 0: + raise TooLargeError(f"Panel doesn't meet size constraints:\n" + "\n".join(f"- {x}" for x in sizeErrors)) + if frameOuterRect.GetWidth() < minWidth: diff = minWidth - frameOuterRect.GetWidth() frameOuterRect.SetX(frameOuterRect.GetX() - diff // 2) @@ -1173,7 +1189,8 @@ def makeFrame(self, width: KiLength, hspace: KiLength, vspace: KiLength, def makeTightFrame(self, width: KiLength, slotwidth: KiLength, hspace: KiLength, vspace: KiLength, minWidth: KiLength=0, - minHeight: KiLength=0) -> None: + minHeight: KiLength=0, maxWidth: Optional[KiLength] = None, + maxHeight: Optional[KiLength] = None) -> None: """ Build a full frame with board perimeter milled out. Add your boards to the panel first using appendBoard or makeGrid. @@ -1192,8 +1209,11 @@ def makeTightFrame(self, width: KiLength, slotwidth: KiLength, minHeight - if the panel doesn't meet this height, it is extended + maxWidth - if the panel doesn't meet this width, TooLargeError is raised + + maxHeight - if the panel doesn't meet this height, TooLargeHeight is raised """ - self.makeFrame(width, hspace, vspace, minWidth, minHeight) + self.makeFrame(width, hspace, vspace, minWidth, minHeight, maxWidth, maxHeight) boardSlot = GeometryCollection() for s in self.substrates: boardSlot = boardSlot.union(s.exterior()) @@ -1201,26 +1221,35 @@ def makeTightFrame(self, width: KiLength, slotwidth: KiLength, frameBody = box(*self.boardSubstrate.bounds()).difference(boardSlot) self.appendSubstrate(frameBody) - def makeRailsTb(self, thickness: KiLength, minHeight: KiLength=0): + def makeRailsTb(self, thickness: KiLength, minHeight: KiLength = 0, + maxHeight: Optional[KiLength] = None) -> None: """ Adds a rail to top and bottom. You can specify minimal height the panel - has to feature. + has to feature. You can also specify maximal height of the panel. If the + height would be exceeded, TooLargeError is raised. """ minx, miny, maxx, maxy = self.panelBBox() - if maxy - miny + 2 * thickness < minHeight: + height = maxy - miny + 2 * thickness + if maxHeight is not None and height > maxHeight: + raise TooLargeError(f"Panel height {height / units.mm} mm exceeds the limit {maxHeight / units.mm} mm") + if height < minHeight: thickness = (minHeight - maxy + miny) // 2 topRail = box(minx, maxy, maxx, maxy + thickness) bottomRail = box(minx, miny, maxx, miny - thickness) self.appendSubstrate(topRail) self.appendSubstrate(bottomRail) - def makeRailsLr(self, thickness: KiLength, minWidth: KiLength=0): + def makeRailsLr(self, thickness: KiLength, minWidth: KiLength = 0, + maxWidth: Optional[KiLength] = None) -> None: """ Adds a rail to left and right. You can specify minimal width the panel has to feature. """ minx, miny, maxx, maxy = self.panelBBox() - if maxx - minx + 2 * thickness < minWidth: + width = maxx - minx + 2 * thickness + if maxWidth is not None and width > maxWidth: + raise TooLargeError(f"Panel width {width / units.mm} mm exceeds the limit {maxWidth / units.mm} mm") + if width < minWidth: thickness = (minWidth - maxx + minx) // 2 leftRail = box(minx - thickness, miny, minx, maxy) rightRail = box(maxx, miny, maxx + thickness, maxy) diff --git a/kikit/panelize_ui_impl.py b/kikit/panelize_ui_impl.py index 09b93d46..28a97ab7 100644 --- a/kikit/panelize_ui_impl.py +++ b/kikit/panelize_ui_impl.py @@ -443,17 +443,20 @@ def buildFraming(preset, panel): if type == "none": return [] if type == "railstb": - panel.makeRailsTb(framingPreset["width"], framingPreset["mintotalheight"]) + panel.makeRailsTb(framingPreset["width"], + framingPreset["mintotalheight"], framingPreset["maxtotalheight"]) addFilletAndChamfer(framingPreset, panel) return [] if type == "railslr": - panel.makeRailsLr(framingPreset["width"], framingPreset["mintotalwidth"]) + panel.makeRailsLr(framingPreset["width"], + framingPreset["mintotalwidth"], framingPreset["maxtotalwidth"]) addFilletAndChamfer(framingPreset, panel) return [] if type == "frame": cuts = panel.makeFrame(framingPreset["width"], framingPreset["hspace"], framingPreset["vspace"], - framingPreset["mintotalwidth"], framingPreset["mintotalheight"]) + framingPreset["mintotalwidth"], framingPreset["mintotalheight"], + framingPreset["maxtotalwidth"], framingPreset["maxtotalheight"]) addFilletAndChamfer(framingPreset, panel) if framingPreset["cuts"] == "both": return chain(*cuts) @@ -465,7 +468,8 @@ def buildFraming(preset, panel): if type == "tightframe": panel.makeTightFrame(framingPreset["width"], framingPreset["slotwidth"], framingPreset["hspace"], framingPreset["vspace"], - framingPreset["mintotalwidth"], framingPreset["mintotalheight"]) + framingPreset["mintotalwidth"], framingPreset["mintotalheight"], + framingPreset["maxtotalwidth"], framingPreset["maxtotalheight"]) panel.boardSubstrate.removeIslands() addFilletAndChamfer(framingPreset, panel) return [] diff --git a/kikit/panelize_ui_sections.py b/kikit/panelize_ui_sections.py index babb3923..443f3fb5 100644 --- a/kikit/panelize_ui_sections.py +++ b/kikit/panelize_ui_sections.py @@ -436,6 +436,14 @@ def ppCuts(section): typeIn(["frame", "raillr", "tightframe"]), "Minimal width of the panel" ), + "maxtotalheight": SLength( + typeIn(["frame", "railstb", "tightframe"]), + "Maximal height of the panel" + ), + "maxtotalwidth": SLength( + typeIn(["frame", "raillr", "tightframe"]), + "Maximal width of the panel" + ), "slotwidth": SLength( typeIn(["tightframe"]), "Width of the milled slot"), diff --git a/kikit/resources/panelizePresets/default.json b/kikit/resources/panelizePresets/default.json index 6a874cad..debeb792 100644 --- a/kikit/resources/panelizePresets/default.json +++ b/kikit/resources/panelizePresets/default.json @@ -67,6 +67,8 @@ "vspace": "2mm", "mintotalheight": "0mm", "mintotalwidth": "0mm", + "maxtotalheight": "10m", + "maxtotalwidth": "10m", "chamfer": "0mm", "fillet": "0mm", "code": "none",