kopia lustrzana https://gitlab.com/gerbolyze/gerbonara
layers: Fix single file handling
rodzic
6231f67139
commit
67dfad8418
|
@ -1,4 +1,21 @@
|
|||
#!/usr/bin/env python3
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2023 Jan Sebastian Götte <gerbonara@jaseg.de>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
|
||||
import math
|
||||
import click
|
||||
|
@ -124,7 +141,7 @@ def cli():
|
|||
@click.option('--force-zip', is_flag=True, help='''Force treating input path as a zip file (default: guess file type
|
||||
from extension and contents)''')
|
||||
@click.option('--top/--bottom', default=True, help='Which side of the board to render')
|
||||
@click.option('--command-line-units', type=Unit(), default=MM, help='''Units for values given in other options. Default:
|
||||
@click.option('--command-line-units', type=Unit(), help='''Units for values given in other options. Default:
|
||||
millimeter''')
|
||||
@click.option('--margin', type=float, default=0.0, help='Add space around the board inside the viewport')
|
||||
@click.option('--force-bounds', help='Force SVG bounding box to value given as "min_x,min_y,max_x,max_y"')
|
||||
|
@ -155,7 +172,8 @@ def render(inpath, outfile, format_warnings, input_map, use_builtin_name_rules,
|
|||
if colorscheme:
|
||||
colorscheme = json.loads(colorscheme.read_text())
|
||||
|
||||
outfile.write(str(stack.to_pretty_svg(side='top' if top else 'bottom', margin=margin, arg_unit=command_line_units,
|
||||
outfile.write(str(stack.to_pretty_svg(side='top' if top else 'bottom', margin=margin,
|
||||
arg_unit=(command_line_units or MM),
|
||||
svg_unit=MM, force_bounds=force_bounds, inkscape=inkscape, colors=colorscheme)))
|
||||
|
||||
|
||||
|
@ -170,7 +188,7 @@ def render(inpath, outfile, format_warnings, input_map, use_builtin_name_rules,
|
|||
move its bottom-left corner to the origin. Coordinates are given in --command-line-units, angles in
|
||||
degrees, and scale as a scale factor (as opposed to a percentage). Example: "translate(-10, 0); rotate(45,
|
||||
0, 5)"''')
|
||||
@click.option('--command-line-units', type=Unit(), default=MM, help='''Units for values given in other options. Default:
|
||||
@click.option('--command-line-units', type=Unit(), help='''Units for values given in other options. Default:
|
||||
millimeter''')
|
||||
@click.option('-n', '--number-format', help='''Override number format to use during export in "[integer digits].[decimal
|
||||
digits]" notation, e.g. "2.6".''')
|
||||
|
@ -212,7 +230,7 @@ def rewrite(transform, command_line_units, number_format, units, zero_suppressio
|
|||
f = GerberFile.open(infile, override_settings=input_settings)
|
||||
|
||||
if transform:
|
||||
apply_transform(transform, command_line_units, f)
|
||||
apply_transform(transform, command_line_units or MM, f)
|
||||
|
||||
output_format = FileSettings() if output_format == 'reuse' else FileSettings.defaults()
|
||||
if number_format:
|
||||
|
@ -238,7 +256,7 @@ def rewrite(transform, command_line_units, number_format, units, zero_suppressio
|
|||
rules and use only rules given by --input-map''')
|
||||
@click.option('--warnings', 'format_warnings', type=click.Choice(['default', 'ignore', 'once']), default='default',
|
||||
help='''Enable or disable file format warnings during parsing (default: on)''')
|
||||
@click.option('--units', type=Unit(), default=MM, help='Units for values given in other options. Default: millimeter')
|
||||
@click.option('--units', type=Unit(), help='Units for values given in other options. Default: millimeter')
|
||||
@click.option('-n', '--number-format', help='''Override number format to use during export in
|
||||
"[integer digits].[decimal digits]" notation, e.g. "2.6".''')
|
||||
@click.option('--reuse-input-settings', 'output_format', flag_value='reuse', help='''Use the same export settings as the
|
||||
|
@ -281,8 +299,8 @@ def transform(transform, units, output_format, inpath, outpath,
|
|||
|
||||
|
||||
@cli.command()
|
||||
@click.option('--command-line-units', type=Unit(), default=MM, help='Units for values given in --transform. Default:
|
||||
millimeter')
|
||||
@click.option('--command-line-units', type=Unit(), help='''Units for values given in --transform. Default:
|
||||
millimeter''')
|
||||
@click.option('--warnings', 'format_warnings', type=click.Choice(['default', 'ignore', 'once']), default='default',
|
||||
help='''Enable or disable file format warnings during parsing (default: on)''')
|
||||
@click.option('--offset', multiple=True, type=Coordinate(), help="""Offset for the n'th file as a "x,y" string in unit
|
||||
|
@ -333,7 +351,7 @@ def merge(inpath, outpath, offset, rotation, input_map, command_line_units, outp
|
|||
stack = LayerStack.open(p, overrides=overrides, autoguess=use_builtin_name_rules)
|
||||
|
||||
if not math.isclose(offset[0], 0, abs_tol=1e-3) and math.isclose(offset[1], 0, abs_tol=1e-3):
|
||||
stack.offset(*offset, command_line_units)
|
||||
stack.offset(*offset, command_line_units or MM)
|
||||
|
||||
if not math.isclose(theta, 0, abs_tol=1e-2):
|
||||
stack.rotate(theta, cx, cy)
|
||||
|
@ -357,7 +375,7 @@ def merge(inpath, outpath, offset, rotation, input_map, command_line_units, outp
|
|||
@click.option('--version', is_flag=True, callback=print_version, expose_value=False, is_eager=True)
|
||||
@click.option('--warnings', 'format_warnings', type=click.Choice(['default', 'ignore', 'once']), default='default',
|
||||
help='''Enable or disable file format warnings during parsing (default: on)''')
|
||||
@click.option('--units', type=Unit(), default=MM, help='Output bounding box in this unit (default: millimeter)')
|
||||
@click.option('--units', type=Unit(), help='Output bounding box in this unit (default: millimeter)')
|
||||
@click.option('--input-number-format', help='Override number format of input file (mostly useful for Excellon files)')
|
||||
@click.option('--input-units', type=Unit(), help='Override units of input file')
|
||||
@click.option('--input-zero-suppression', type=click.Choice(['off', 'leading', 'trailing']), help='Override zero suppression setting of input file')
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from argparse import PARSER
|
||||
|
||||
# Copyright 2015 Garret Fick <garret@ficksworkshop.com>
|
||||
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""
|
||||
Excellon Settings Definition File module
|
||||
====================
|
||||
**Excellon file classes**
|
||||
|
||||
This module provides Excellon file classes and parsing utilities
|
||||
"""
|
||||
|
||||
import re
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
except(ImportError):
|
||||
from io import StringIO
|
||||
|
||||
from .cam import FileSettings
|
||||
|
||||
def loads(data):
|
||||
""" Read settings file information and return an FileSettings
|
||||
Parameters
|
||||
----------
|
||||
data : string
|
||||
string containing Excellon settings file contents
|
||||
|
||||
Returns
|
||||
-------
|
||||
file settings: FileSettings
|
||||
|
||||
"""
|
||||
|
||||
return ExcellonSettingsParser().parse_raw(data)
|
||||
|
||||
def map_coordinates(value):
|
||||
if value == 'ABSOLUTE':
|
||||
return 'absolute'
|
||||
return 'relative'
|
||||
|
||||
def map_units(value):
|
||||
if value == 'ENGLISH':
|
||||
return 'inch'
|
||||
return 'metric'
|
||||
|
||||
def map_boolean(value):
|
||||
return value == 'YES'
|
||||
|
||||
SETTINGS_KEYS = {
|
||||
'INTEGER-PLACES': (int, 'format-int'),
|
||||
'DECIMAL-PLACES': (int, 'format-dec'),
|
||||
'COORDINATES': (map_coordinates, 'notation'),
|
||||
'OUTPUT-UNITS': (map_units, 'units'),
|
||||
}
|
||||
|
||||
class ExcellonSettingsParser(object):
|
||||
"""Excellon Settings PARSER
|
||||
|
||||
Parameters
|
||||
----------
|
||||
None
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.values = {}
|
||||
self.settings = None
|
||||
|
||||
def parse_raw(self, data):
|
||||
for line in StringIO(data):
|
||||
self._parse(line.strip())
|
||||
|
||||
# Create the FileSettings object
|
||||
self.settings = FileSettings(
|
||||
notation=self.values['notation'],
|
||||
units=self.values['units'],
|
||||
format=(self.values['format-int'], self.values['format-dec'])
|
||||
)
|
||||
|
||||
return self.settings
|
||||
|
||||
def _parse(self, line):
|
||||
|
||||
line_items = line.split()
|
||||
if len(line_items) == 2:
|
||||
|
||||
item_type_info = SETTINGS_KEYS.get(line_items[0])
|
||||
if item_type_info:
|
||||
# Convert the value to the expected type
|
||||
item_value = item_type_info[0](line_items[1])
|
||||
|
||||
self.values[item_type_info[1]] = item_value
|
|
@ -2,7 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2014 Hamilton Kibbe <ham@hamiltonkib.be>
|
||||
# Copyright 2022 Jan Götte <code@jaseg.de>
|
||||
# Copyright 2022 Jan Sebastian Götte <gerbonara@jaseg.de>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -258,7 +258,7 @@ class LayerStack:
|
|||
elif path.suffix.lower() == '.zip' or is_zipfile(path):
|
||||
return kls.open_zip(path, board_name=board_name, lazy=lazy, overrides=overrides, autoguess=autoguess)
|
||||
else:
|
||||
return kls.from_files([path], board_name=board_name, lazy=lazy, overrides=overrides, autoguess=autoguess)
|
||||
return kls.from_files([path], board_name=board_name, lazy=lazy, overrides=overrides, autoguess=False)
|
||||
|
||||
@classmethod
|
||||
def open_zip(kls, file, original_path=None, board_name=None, lazy=False, overrides=None, autoguess=True):
|
||||
|
@ -294,7 +294,11 @@ class LayerStack:
|
|||
if autoguess:
|
||||
generator, filemap = best_match(files)
|
||||
else:
|
||||
generator, filemap = 'custom', {}
|
||||
generator = 'custom'
|
||||
if overrides:
|
||||
filemap = {}
|
||||
else:
|
||||
filemap = {'unknown unknown': files}
|
||||
all_generator_hints = set()
|
||||
|
||||
if overrides:
|
||||
|
@ -310,7 +314,7 @@ class LayerStack:
|
|||
filemap[layer].remove(fn)
|
||||
filemap[layer] = filemap.get(layer, []) + [fn]
|
||||
|
||||
if sum(len(files) for files in filemap.values()) < 6:
|
||||
if sum(len(files) for files in filemap.values()) < 6 and autoguess:
|
||||
warnings.warn('Ambiguous gerber filenames. Trying last-resort autoguesser.')
|
||||
generator = None
|
||||
filemap = do_autoguess(files)
|
||||
|
@ -665,18 +669,18 @@ class LayerStack:
|
|||
self.drill_pth = self.drill_npth = self.drill_unknown = None
|
||||
|
||||
def __len__(self):
|
||||
return len(self.layers)
|
||||
return len(self.graphic_layers)
|
||||
|
||||
def get(self, index, default=None):
|
||||
if self.contains(key):
|
||||
return self[key]
|
||||
if index in self:
|
||||
return self[index]
|
||||
else:
|
||||
return default
|
||||
|
||||
def __contains__(self, index):
|
||||
if isinstance(index, str):
|
||||
side, _, use = index.partition(' ')
|
||||
return (side, use) in self.layers
|
||||
return (side, use) in self.graphic_layers
|
||||
|
||||
elif isinstance(index, tuple):
|
||||
return index in self.graphic_layers
|
||||
|
@ -718,7 +722,7 @@ class LayerStack:
|
|||
|
||||
@property
|
||||
def outline(self):
|
||||
return self['mechanical outline']
|
||||
return self.get('mechanical outline')
|
||||
|
||||
def outline_svg_d(self, tol=0.01, unit=MM):
|
||||
chains = self.outline_polygons(tol, unit)
|
||||
|
|
Ładowanie…
Reference in New Issue