[Any Layer] Enabled scaling for most plot outputs
- Only the gerber is excluded - The new `individual_page_scaling` option is also available - Now unknown options are treated as errors
This commit is contained in:
parent
eaa9569e71
commit
bb475ad75a
|
|
@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `cache_3d_resistors` to avoid generating them all the time.
|
||||
- 3D: colored 3D models for THT resistors
|
||||
- Datasheet download: now the warnings mention which reference failed.
|
||||
- Plot related outputs and PCB_Print:
|
||||
- `individual_page_scaling`: to control if the center of the page is computed
|
||||
using all pages or individually.
|
||||
- Plot related outputs:
|
||||
- All outputs now support scaling.
|
||||
|
||||
### Fixed
|
||||
- Makefile: don't skip all preflights on each run, just the ones we generate
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020-2022 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
|
||||
# Copyright (c) 2020-2023 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
""" Miscellaneous definitions """
|
||||
|
|
@ -271,6 +271,7 @@ W_BADTOL = '(W122) '
|
|||
W_BADRES = '(W123) '
|
||||
W_RESVALISSUE = '(W124) '
|
||||
W_RES3DNAME = '(W125) '
|
||||
W_ESCINV = '(W126) '
|
||||
# Somehow arbitrary, the colors are real, but can be different
|
||||
PCB_MAT_COLORS = {'fr1': "937042", 'fr2': "949d70", 'fr3': "adacb4", 'fr4': "332B16", 'fr5': "6cc290"}
|
||||
PCB_FINISH_COLORS = {'hal': "8b898c", 'hasl': "8b898c", 'imag': "8b898c", 'enig': "cfb96e", 'enepig': "cfb96e",
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
import os
|
||||
import re
|
||||
from pcbnew import (GERBER_JOBFILE_WRITER, PLOT_CONTROLLER, IsCopperLayer, F_Cu, B_Cu, Edge_Cuts, PLOT_FORMAT_HPGL,
|
||||
PLOT_FORMAT_GERBER, PLOT_FORMAT_POST, PLOT_FORMAT_DXF, PLOT_FORMAT_PDF, PLOT_FORMAT_SVG, LSEQ)
|
||||
PLOT_FORMAT_GERBER, PLOT_FORMAT_POST, PLOT_FORMAT_DXF, PLOT_FORMAT_PDF, PLOT_FORMAT_SVG, LSEQ, LSET)
|
||||
from .optionable import Optionable
|
||||
from .out_base import BaseOutput, VariantOptions
|
||||
from .error import PlotError, KiPlotConfigurationError
|
||||
from .layer import Layer
|
||||
from .gs import GS
|
||||
from .misc import W_NOLAYER, KICAD_VERSION_7_0_1, MISSING_TOOL
|
||||
from .misc import W_NOLAYER, KICAD_VERSION_7_0_1, MISSING_TOOL, AUTO_SCALE
|
||||
from .macros import macros, document # noqa: F401
|
||||
from . import log
|
||||
|
||||
|
|
@ -80,7 +80,13 @@ class AnyLayerOptions(VariantOptions):
|
|||
self.sketch_pad_line_width = 0.1
|
||||
""" Line width for the sketched pads [mm], see `sketch_pads_on_fab_layers` (KiCad 6+)
|
||||
Note that this value is currently ignored by KiCad (6.0.9) """
|
||||
self.scaling = 1
|
||||
""" *Scale factor (0 means autoscaling) """
|
||||
self.individual_page_scaling = True
|
||||
""" Tell KiCad to apply the scaling for each layer as a separated entity.
|
||||
Disabling it the pages are coherent and can be superposed """
|
||||
super().__init__()
|
||||
self._unkown_is_error = True
|
||||
|
||||
def config(self, parent):
|
||||
super().config(parent)
|
||||
|
|
@ -107,6 +113,14 @@ class AnyLayerOptions(VariantOptions):
|
|||
po.SetCreateGerberJobFile(False)
|
||||
# We'll come back to this on a per-layer basis
|
||||
po.SetSkipPlotNPTH_Pads(False)
|
||||
# Scaling/Autoscale
|
||||
if self._plot_format != PLOT_FORMAT_GERBER:
|
||||
if self.scaling == AUTO_SCALE:
|
||||
po.SetAutoScale(True)
|
||||
po.SetScale(1)
|
||||
else:
|
||||
po.SetAutoScale(False)
|
||||
po.SetScale(self.scaling)
|
||||
|
||||
def compute_name(self, k_filename, output_dir, output, id, suffix):
|
||||
if output:
|
||||
|
|
@ -141,6 +155,8 @@ class AnyLayerOptions(VariantOptions):
|
|||
logger.error("Plotting the edge layer is not supported by KiCad 7.0.0\n"
|
||||
"Please upgrade KiCad to 7.0.1 or newer")
|
||||
exit(MISSING_TOOL)
|
||||
# Memorize the list of visible layers
|
||||
old_visible = GS.board.GetVisibleLayers()
|
||||
# Apply the variants and filters
|
||||
exclude = self.filter_pcb_components()
|
||||
# fresh plot controller
|
||||
|
|
@ -157,6 +173,13 @@ class AnyLayerOptions(VariantOptions):
|
|||
# Plot every layer in the output
|
||||
generated = {}
|
||||
layers = Layer.solve(layers)
|
||||
# Make visible only the layers we need
|
||||
# This is very important when scaling, otherwise the results are controlled by the .kicad_prl (See #407)
|
||||
if self._plot_format != PLOT_FORMAT_GERBER and not self.individual_page_scaling:
|
||||
vis_layers = LSET()
|
||||
for la in layers:
|
||||
vis_layers.addLayer(la._id)
|
||||
GS.board.SetVisibleLayers(vis_layers)
|
||||
for la in layers:
|
||||
suffix = la.suffix
|
||||
desc = la.description
|
||||
|
|
@ -164,6 +187,11 @@ class AnyLayerOptions(VariantOptions):
|
|||
if not GS.board.IsLayerEnabled(id):
|
||||
logger.warning(W_NOLAYER+'Layer "{}" isn\'t used'.format(desc))
|
||||
continue
|
||||
if self._plot_format != PLOT_FORMAT_GERBER and self.individual_page_scaling:
|
||||
# Only this layer is visible
|
||||
vis_layers = LSET()
|
||||
vis_layers.addLayer(la._id)
|
||||
GS.board.SetVisibleLayers(vis_layers)
|
||||
# Set current layer
|
||||
plot_ctrl.SetLayer(id)
|
||||
# Skipping NPTH is controlled by whether or not this is
|
||||
|
|
@ -211,6 +239,8 @@ class AnyLayerOptions(VariantOptions):
|
|||
# Restore the eliminated layers
|
||||
if exclude:
|
||||
self.unfilter_pcb_components()
|
||||
# Restore the list of visible layers
|
||||
GS.board.SetVisibleLayers(old_visible)
|
||||
self._generated_files = generated
|
||||
|
||||
def solve_extension(self, layer):
|
||||
|
|
@ -258,6 +288,11 @@ class AnyLayerOptions(VariantOptions):
|
|||
else:
|
||||
self.sketch_pads_on_fab_layers = po.GetSketchPadsOnFabLayers()
|
||||
self.sketch_pad_line_width = po.GetSketchPadLineWidth()
|
||||
# scaleselection
|
||||
if self._plot_format != PLOT_FORMAT_GERBER:
|
||||
sel = po.GetScaleSelection()
|
||||
sel = sel if sel < 0 or sel > 4 else 4
|
||||
self.scaling = (AUTO_SCALE, 1.0, 1.5, 2.0, 3.0)[sel]
|
||||
|
||||
|
||||
class AnyLayer(BaseOutput):
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@ class GerberOptions(AnyLayerOptions):
|
|||
self.disable_aperture_macros = False
|
||||
""" Disable aperture macros (workaround for buggy CAM software) (KiCad 6) """
|
||||
super().__init__()
|
||||
# Gerbers are always 1:1
|
||||
del(self.scaling)
|
||||
del(self.individual_page_scaling)
|
||||
self._plot_format = PLOT_FORMAT_GERBER
|
||||
if GS.global_output is not None:
|
||||
self.gerber_job_file = GS.global_output
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020 Salvador E. Tropea
|
||||
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
|
||||
# Copyright (c) 2020-2023 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
from pcbnew import PLOT_FORMAT_HPGL, SKETCH, FILLED
|
||||
from .misc import AUTO_SCALE
|
||||
from .out_any_layer import AnyLayer
|
||||
from .drill_marks import DrillMarks
|
||||
from .macros import macros, document, output_class # noqa: F401
|
||||
|
|
@ -35,13 +34,6 @@ class HPGLOptions(DrillMarks):
|
|||
po.SetHPGLPenSpeed(self.pen_speed)
|
||||
po.SetPlotMode(SKETCH if self.sketch_plot else FILLED)
|
||||
po.SetMirror(self.mirror_plot)
|
||||
# Scaling/Autoscale
|
||||
if self.scaling == AUTO_SCALE:
|
||||
po.SetAutoScale(True)
|
||||
po.SetScale(1)
|
||||
else:
|
||||
po.SetAutoScale(False)
|
||||
po.SetScale(self.scaling)
|
||||
|
||||
def read_vals_from_po(self, po):
|
||||
super().read_vals_from_po(po)
|
||||
|
|
@ -50,10 +42,6 @@ class HPGLOptions(DrillMarks):
|
|||
self.pen_speed = po.GetHPGLPenSpeed()
|
||||
self.sketch_plot = po.GetPlotMode() == SKETCH
|
||||
self.mirror_plot = po.GetMirror()
|
||||
# scaleselection
|
||||
sel = po.GetScaleSelection()
|
||||
sel = sel if sel < 0 or sel > 4 else 4
|
||||
self.scaling = (AUTO_SCALE, 1.0, 1.5, 2.0, 3.0)[sel]
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020 Salvador E. Tropea
|
||||
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
|
||||
# Copyright (c) 2020-2023 Salvador E. Tropea
|
||||
# Copyright (c) 2020-2023 Instituto Nacional de Tecnología Industrial
|
||||
# Copyright (c) 2018 John Beard
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
# Adapted from: https://github.com/johnbeard/kiplot
|
||||
from pcbnew import PLOT_FORMAT_POST, FromMM, ToMM, SKETCH, FILLED
|
||||
from .misc import AUTO_SCALE
|
||||
from .out_any_layer import AnyLayer
|
||||
from .drill_marks import DrillMarks
|
||||
from .gs import GS
|
||||
|
|
@ -25,8 +24,6 @@ class PSOptions(DrillMarks):
|
|||
""" Invert black and white """
|
||||
self.sketch_plot = False
|
||||
""" Don't fill objects, just draw the outline """
|
||||
self.scaling = 1
|
||||
""" *Scale factor (0 means autoscaling)"""
|
||||
self.scale_adjust_x = 1.0
|
||||
""" Fine grain adjust for the X scale (floating point multiplier) """
|
||||
self.scale_adjust_y = 1.0
|
||||
|
|
@ -49,13 +46,6 @@ class PSOptions(DrillMarks):
|
|||
po.SetLineWidth(FromMM(self.line_width))
|
||||
po.SetNegative(self.negative_plot)
|
||||
po.SetMirror(self.mirror_plot)
|
||||
# Scaling/Autoscale
|
||||
if self.scaling == AUTO_SCALE:
|
||||
po.SetAutoScale(True)
|
||||
po.SetScale(1)
|
||||
else:
|
||||
po.SetAutoScale(False)
|
||||
po.SetScale(self.scaling)
|
||||
|
||||
def read_vals_from_po(self, po):
|
||||
super().read_vals_from_po(po)
|
||||
|
|
@ -68,10 +58,6 @@ class PSOptions(DrillMarks):
|
|||
self.line_width = ToMM(po.GetLineWidth())
|
||||
self.negative_plot = po.GetNegative()
|
||||
self.mirror_plot = po.GetMirror()
|
||||
# scaleselection
|
||||
sel = po.GetScaleSelection()
|
||||
sel = sel if sel < 0 or sel > 4 else 4
|
||||
self.scaling = (AUTO_SCALE, 1.0, 1.5, 2.0, 3.0)[sel]
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from pcbnew import PLOT_FORMAT_SVG, FromMM, ToMM
|
|||
from .drill_marks import DrillMarks
|
||||
from .gs import GS
|
||||
from .kicad.patch_svg import change_svg_viewbox
|
||||
from .misc import W_ESCINV
|
||||
from .out_base import PcbMargin
|
||||
from .out_any_layer import AnyLayer
|
||||
from .macros import macros, document, output_class # noqa: F401
|
||||
|
|
@ -33,7 +34,8 @@ class SVGOptions(DrillMarks):
|
|||
The value is how much zeros has the multiplier (1 mm = 10 power `svg_precision` units).
|
||||
Note that for an A4 paper Firefox 91 and Chrome 105 can't handle more than 5 """
|
||||
self.limit_viewbox = False
|
||||
""" When enabled the view box is limited to a selected area """
|
||||
""" When enabled the view box is limited to a selected area.
|
||||
This option can't be enabled when using a scale """
|
||||
self.size_detection = 'kicad_edge'
|
||||
""" [kicad_edge,kicad_all] Method used to detect the size of the view box.
|
||||
The `kicad_edge` method uses the size of the board as reported by KiCad,
|
||||
|
|
@ -71,6 +73,9 @@ class SVGOptions(DrillMarks):
|
|||
super().run(output_dir, layers)
|
||||
if not self.limit_viewbox:
|
||||
return
|
||||
if self.scaling != 1:
|
||||
logger.warning(W_ESCINV+"Scaling and view port limit can't be mixed")
|
||||
return
|
||||
# Limit the view box of the SVG
|
||||
bbox = GS.get_rect_for(GS.board.ComputeBoundingBox(self.size_detection == 'kicad_edge'))
|
||||
# Apply the margin (left right top bottom)
|
||||
|
|
|
|||
Loading…
Reference in New Issue