From 27247c17b609bb2458415366a58f90456dc67978 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Wed, 28 Dec 2022 11:07:27 -0300 Subject: [PATCH] [Sub-PCBs] Implemented centered PCB - Also added option to disable it, at least for the internal tool - KiKit 1.1.2 is not centering, but using top-left ... but the docs says it should center. --- README.md | 6 ++++++ kibot/gs.py | 8 ++++++++ kibot/var_base.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/README.md b/README.md index e938342c..c4caaac9 100644 --- a/README.md +++ b/README.md @@ -1056,6 +1056,8 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu - *bottom_right_y*: Alias for bry. - `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB. - `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB. + - `center_result`: [boolean=true] Move the resulting PCB to the center of the page. + You can disable it only for the internal tool, KiKit should always do it. - `file_id`: [string=''] Text to use as the replacement for %v expansion. When empty we use the parent `file_id` plus the `name` of the sub-PCB. - `strip_annotation`: [boolean=false] Remove the annotation footprint. Note that KiKit will remove all annotations, @@ -1107,6 +1109,8 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu - *bottom_right_y*: Alias for bry. - `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB. - `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB. + - `center_result`: [boolean=true] Move the resulting PCB to the center of the page. + You can disable it only for the internal tool, KiKit should always do it. - `file_id`: [string=''] Text to use as the replacement for %v expansion. When empty we use the parent `file_id` plus the `name` of the sub-PCB. - `strip_annotation`: [boolean=false] Remove the annotation footprint. Note that KiKit will remove all annotations, @@ -1160,6 +1164,8 @@ Note that the **_kibom_...** filters uses a field named `Config`, but you can cu - *bottom_right_y*: Alias for bry. - `brx`: [number|string] The X position of the bottom right corner for the rectangle that contains the sub-PCB. - `bry`: [number|string] The Y position of the bottom right corner for the rectangle that contains the sub-PCB. + - `center_result`: [boolean=true] Move the resulting PCB to the center of the page. + You can disable it only for the internal tool, KiKit should always do it. - `file_id`: [string=''] Text to use as the replacement for %v expansion. When empty we use the parent `file_id` plus the `name` of the sub-PCB. - `strip_annotation`: [boolean=false] Remove the annotation footprint. Note that KiKit will remove all annotations, diff --git a/kibot/gs.py b/kibot/gs.py index 34c2e7a1..bf36bb18 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -296,6 +296,10 @@ class GS(object): def to_mm(val): return val/pcbnew.IU_PER_MM + @staticmethod + def from_mm(val): + return int(val*pcbnew.IU_PER_MM) + @staticmethod def make_bkp(fname): bkp = fname+'-bak' @@ -460,6 +464,10 @@ class GS(object): def create_eda_rect(tlx, tly, brx, bry): return pcbnew.EDA_RECT(pcbnew.wxPoint(tlx, tly), pcbnew.wxSize(brx-tlx, bry-tly)) + # @staticmethod + # def create_wxpoint(x, y): + # return pcbnew.wxPoint(x, y) + @staticmethod def is_valid_pcb_shape(g): return g.GetShape() != pcbnew.S_SEGMENT or g.GetLength() > 0 diff --git a/kibot/var_base.py b/kibot/var_base.py index 75cc028a..2d997343 100644 --- a/kibot/var_base.py +++ b/kibot/var_base.py @@ -14,6 +14,7 @@ from .error import KiPlotConfigurationError from .misc import KIKIT_UNIT_ALIASES from .gs import GS from .kiplot import run_command +from .kicad.pcb import PCB from .macros import macros, document # noqa: F401 from . import log @@ -107,6 +108,9 @@ class SubPCBOptions(PanelOptions): """ Remove the annotation footprint. Note that KiKit will remove all annotations, but the internal implementation just the one indicated by `ref`. If you need to remove other annotations use an exclude filter """ + self.center_result = True + """ Move the resulting PCB to the center of the page. + You can disable it only for the internal tool, KiKit should always do it """ def is_zero(self, val): return isinstance(val, (int, float)) and val == 0 @@ -281,6 +285,26 @@ class SubPCBOptions(PanelOptions): logger.debug(' - '+str(e)) return bbox + def move_objects(self): + """ Move all objects by self._moved """ + logger.debug('Moving all PCB elements by '+point_str(self._moved)) + any(map(lambda x: x.Move(self._moved), GS.get_modules())) + any(map(lambda x: x.Move(self._moved), GS.board.GetDrawings())) + any(map(lambda x: x.Move(self._moved), GS.board.GetTracks())) + any(map(lambda x: x.Move(self._moved), GS.board.Zones())) + + def center_objects(self): + """ Move all objects in the PCB so it gets centered """ + # Look for the PCB size + pcb = PCB.load(GS.pcb_file) + paper_center_x = GS.from_mm(pcb.paper_w/2) + paper_center_y = GS.from_mm(pcb.paper_h/2) + # Compute the offset to make it centered + self._moved = self.board_rect.GetCenter() + self._moved.x = paper_center_x-self._moved.x + self._moved.y = paper_center_y-self._moved.y + self.move_objects() + def apply(self, comps_hash): """ Apply the sub-PCB selection. """ self._excl_by_sub_pcb = set() @@ -291,6 +315,8 @@ class SubPCBOptions(PanelOptions): self.board_rect.Inflate(int(self._tolerance)) # Using a rectangle self.remove_outside(comps_hash) + # Center the PCB + self.center_objects() else: # Using KiKit: self.separate_board(comps_hash) @@ -304,9 +330,16 @@ class SubPCBOptions(PanelOptions): for o in self._removed: GS.board.Add(o) + def restore_moved(self): + """ Move objects back to their original place """ + self._moved.x = -self._moved.x + self._moved.y = -self._moved.y + self.move_objects() + def revert(self, comps_hash): """ Restore the sub-PCB selection. """ if self.tool == 'internal': + self.restore_moved() self.restore_removed() else: # Using KiKit: