diff --git a/README.md b/README.md index c3c0d12a..3cf24f07 100644 --- a/README.md +++ b/README.md @@ -895,6 +895,7 @@ Next time you need this list just use an alias, like this: - `ref_id`: [string=''] A prefix to add to all the references from this project. Used for multiple projects. - `ref_separator`: [string=' '] Separator used for the list of references. - `source_by_id`: [boolean=false] Generate the `Source BoM` column using the reference ID instead of the project name. + - `units`: [string='millimeters'] [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns). - `use_alt`: [boolean=false] Print grouped references in the alternate compressed style eg: R1-R7,R18. - `variant`: [string=''] Board variant, used to determine which components are output to the BoM.. diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index ef4586af..7efdcd10 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -242,6 +242,8 @@ outputs: ref_separator: ' ' # [boolean=false] Generate the `Source BoM` column using the reference ID instead of the project name source_by_id: false + # [string='millimeters'] [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns) + units: 'millimeters' # [boolean=false] Print grouped references in the alternate compressed style eg: R1-R7,R18 use_alt: false # [string=''] Board variant, used to determine which components diff --git a/kibot/bom/bom.py b/kibot/bom/bom.py index eaad2bf7..fe39654a 100644 --- a/kibot/bom/bom.py +++ b/kibot/bom/bom.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # Copyright (c) 2016-2020 Oliver Henry Walters (@SchrodingersGat) # License: MIT # Project: KiBot (formerly KiPlot) @@ -302,7 +302,7 @@ class ComponentGroup(object): fld=value, ref=ref)) self.fields[field] += " " + value - def update_fields(self, usealt=False): + def update_fields(self, conv, usealt=False): for c in self.components: for f, v in c.get_user_fields(): self.update_field(f, v, c.ref) @@ -330,6 +330,10 @@ class ComponentGroup(object): self.fields[ColumnList.COL_PART_LIB_L] = comp.lib self.fields[ColumnList.COL_DATASHEET_L] = comp.datasheet self.fields[ColumnList.COL_FP_L] = comp.footprint + self.fields[ColumnList.COL_FP_X_L] = "{:.4f}".format(comp.footprint_x * conv) + self.fields[ColumnList.COL_FP_Y_L] = "{:.4f}".format(comp.footprint_y * conv) + self.fields[ColumnList.COL_FP_ROT_L] = comp.footprint_rot + self.fields[ColumnList.COL_FP_SIDE_L] = "bottom" if comp.bottom else "top" self.fields[ColumnList.COL_FP_LIB_L] = comp.footprint_lib self.fields[ColumnList.COL_SHEETPATH_L] = comp.sheet_path_h if not self.fields[ColumnList.COL_DESCRIPTION_L]: @@ -449,7 +453,7 @@ def group_components(cfg, components): # Sort the references within each group g.sort_components() # Fill the columns - g.update_fields(cfg.use_alt) + g.update_fields(cfg.conv_units, cfg.use_alt) if cfg.normalize_values: g.fields[ColumnList.COL_VALUE_L] = normalize_value(g.components[0], decimal_point) # Sort the groups diff --git a/kibot/bom/columnlist.py b/kibot/bom/columnlist.py index c1422c7c..b30f9550 100644 --- a/kibot/bom/columnlist.py +++ b/kibot/bom/columnlist.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020 Salvador E. Tropea -# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # Copyright (c) 2016-2020 Oliver Henry Walters (@SchrodingersGat) # License: MIT # Project: KiBot (formerly KiPlot) @@ -31,6 +31,14 @@ class ColumnList: COL_FP_L = COL_FP.lower() COL_FP_LIB = 'Footprint Lib' COL_FP_LIB_L = COL_FP_LIB.lower() + COL_FP_X = 'Footprint X' + COL_FP_X_L = COL_FP_X.lower() + COL_FP_Y = 'Footprint Y' + COL_FP_Y_L = COL_FP_Y.lower() + COL_FP_ROT = 'Footprint Rot' + COL_FP_ROT_L = COL_FP_ROT.lower() + COL_FP_SIDE = 'Footprint Side' + COL_FP_SIDE_L = COL_FP_SIDE.lower() COL_PART = 'Part' COL_PART_L = COL_PART.lower() COL_PART_LIB = 'Part Lib' @@ -92,6 +100,10 @@ class ColumnList: COL_DATASHEET_L, COL_SHEETPATH_L, COL_FP_L, + COL_FP_X_L, + COL_FP_Y_L, + COL_FP_ROT_L, + COL_FP_SIDE_L, COL_FP_LIB_L } diff --git a/kibot/gs.py b/kibot/gs.py index 88cca7a4..205db68c 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -180,6 +180,12 @@ class GS(object): return settings.GetAuxOrigin() return GS.board.GetAuxOrigin() + @staticmethod + def get_center(m): + if GS.ki5(): + return m.GetCenter() + return m.GetPosition() + @staticmethod def ki6(): return GS.kicad_version_n >= KICAD_VERSION_5_99 diff --git a/kibot/kicad/v5_sch.py b/kibot/kicad/v5_sch.py index eab20a72..d2bb668b 100644 --- a/kibot/kicad/v5_sch.py +++ b/kibot/kicad/v5_sch.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: GPL-3.0 # Project: KiBot (formerly KiPlot) """ @@ -869,6 +869,8 @@ class SchematicComponent(object): - fixed: means you can't change it by a replacement without authorization Is just a flag and doesn't affect much. - footprint_rot: angle to rotate the part in the pick & place. + - footprint_x: x position of the part in the pick & place. + - footprint_y: y position of the part in the pick & place. - qty: ammount of this part used. """ ref_re = re.compile(r'([^\d]+)([\?\d]+)') @@ -890,6 +892,8 @@ class SchematicComponent(object): self.fixed = False self.bottom = False self.footprint_rot = 0.0 + self.footprint_x = 0 + self.footprint_y = 0 self.qty = 1 self.annotation_error = False # KiCad 5 PCB flags (mutually exclusive) diff --git a/kibot/kiplot.py b/kibot/kiplot.py index e284bc47..eaeec5a9 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -277,6 +277,9 @@ def get_board_comps_data(comps): c = comps_hash[ref] c.bottom = m.IsFlipped() c.footprint_rot = m.GetOrientationDegrees() + center = GS.get_center(m) + c.footprint_x = center.x + c.footprint_y = center.y attrs = m.GetAttributes() if GS.ki5(): # KiCad 5 diff --git a/kibot/out_bom.py b/kibot/out_bom.py index 4eec04fe..8bcc6b8e 100644 --- a/kibot/out_bom.py +++ b/kibot/out_bom.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # License: MIT # Project: KiBot (formerly KiPlot) """ @@ -9,6 +9,7 @@ This is somehow compatible with KiBoM. """ import os import re +from pcbnew import IU_PER_MM, IU_PER_MILS from .gs import GS from .misc import W_BADFIELD, W_NEEDSPCB from .optionable import Optionable, BaseOptions @@ -383,6 +384,8 @@ class BoMOptions(BaseOptions): """ [string|list(string)] Exclude this distributors list. They are removed after computing `distributors` """ self.count_smd_tht = False """ Show the stats about how many of the components are SMD/THT. You must provide the PCB """ + self.units = 'millimeters' + """ [millimeters,inches] Units used for the positions ('Footprint X' and 'Footprint Y' columns) """ self._format_example = 'CSV' super().__init__() @@ -579,6 +582,7 @@ class BoMOptions(BaseOptions): self.revision = GS.sch_rev self.debug_level = GS.debug_level self.kicad_version = GS.kicad_version + self.conv_units = 1.0/IU_PER_MM if self.units == 'millimeters' else 0.001/IU_PER_MILS # Get the components list from the schematic comps = GS.sch.get_components() get_board_comps_data(comps) diff --git a/kibot/out_position.py b/kibot/out_position.py index bc4a4e8f..a39fc15d 100644 --- a/kibot/out_position.py +++ b/kibot/out_position.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2021 Salvador E. Tropea -# Copyright (c) 2020-2021 Instituto Nacional de Tecnología Industrial +# Copyright (c) 2020-2022 Salvador E. Tropea +# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial # Copyright (c) 2019 Romain Deterre (@rdeterre) # License: GPL-3.0 # Project: KiBot (formerly KiPlot) @@ -245,17 +245,18 @@ class PositionOptions(VariantOptions): footprint = c.footprint is_bottom = c.bottom rotation = c.footprint_rot + center_x = c.footprint_x + center_y = c.footprint_y if value is None: value = m.GetValue() footprint = str(m.GetFPID().GetLibItemName()) # pcbnew.UTF8 type is_bottom = m.IsFlipped() rotation = m.GetOrientationDegrees() + center = GS.get_center(m) + center_x = center.x + center_y = center.y # If passed check the position options if (self.only_smd and is_pure_smd(m)) or (not self.only_smd and (is_not_virtual(m) or self.include_virtual)): - if GS.ki5(): - center = m.GetCenter() - else: - center = m.GetPosition() # KiCad: PLACE_FILE_EXPORTER::GenPositionData() in export_footprints_placefile.cpp row = [] for k in self.columns: @@ -266,12 +267,12 @@ class PositionOptions(VariantOptions): elif k == 'Package': row.append(quote_char+footprint+quote_char) elif k == 'PosX': - pos_x = (center.x - x_origin) * conv + pos_x = (center_x - x_origin) * conv if self.bottom_negative_x and is_bottom: pos_x = -pos_x row.append("{:.4f}".format(pos_x)) elif k == 'PosY': - row.append("{:.4f}".format(-(center.y - y_origin) * conv)) + row.append("{:.4f}".format(-(center_y - y_origin) * conv)) elif k == 'Rot': row.append("{:.4f}".format(rotation)) elif k == 'Side':