kopia lustrzana https://gitlab.com/gerbolyze/gerbonara
Still more doc
rodzic
8b40d15dab
commit
1aaac3936f
237
docs/cli.rst
237
docs/cli.rst
|
@ -115,21 +115,258 @@ Modification
|
|||
``gerbonara rewrite``
|
||||
*********************
|
||||
|
||||
.. program:: gerbonara rewrite
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
gerbonara rewrite [OPTIONS] INFILE OUTFILE
|
||||
|
||||
Parse a single gerber file, apply transformations, and re-serialize it into a new gerber file. Without transformations,
|
||||
this command can be used to convert a gerber file to use different settings (e.g. units, precision), but can also be
|
||||
used to "normalize" gerber files in a weird format into a more standards-compatible one as gerbonara's gerber parser is
|
||||
significantly more robust for weird inputs than others.
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: -t, --transform <code>
|
||||
|
||||
Execute python transformation script on input. You have access to the functions ``translate(x, y)``,
|
||||
``scale(factor)`` and ``rotate(angle, center_x?, center_y?)``, the bounding box variables ``x_min``, ``y_min``,
|
||||
``x_max``, ``y_max``, ``width`` and ``height``, and everything from python's built-in math module (e.g. ``pi``,
|
||||
``sqrt``, ``sin``). As convenience methods, ``center()`` and ``origin()`` are provided to center the board
|
||||
respectively 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)``
|
||||
|
||||
.. option:: --command-line-units <metric|us-customary>
|
||||
|
||||
Units for values given in other options. Default: millimeter
|
||||
|
||||
.. option:: -n, --number-format <decimal.fractional>
|
||||
|
||||
Override number format to use during export in ``[integer digits].[decimal digits]`` notation, e.g. ``2.6``.
|
||||
|
||||
.. option:: -u, --units <metric|us-customary>
|
||||
|
||||
Override export file units
|
||||
|
||||
.. option:: -z, --zero-suppression <off|leading|trailing>
|
||||
|
||||
Override export zero suppression setting. Note: The meaning of this value is like in the Gerber spec for both Gerber
|
||||
and Excellon files!
|
||||
|
||||
.. option:: --keep-comments, --drop-comments
|
||||
|
||||
Keep gerber comments. Note: Comments will be prepended to the start of file, and will not occur in their old
|
||||
position.
|
||||
|
||||
.. option:: --default-settings, --reuse-input-settings
|
||||
|
||||
Use sensible defaults for the output file format settings (default) or use the same export settings as the input file
|
||||
instead of sensible defaults.
|
||||
|
||||
.. option:: --input-number-format <decimal.fractional>
|
||||
|
||||
Override number format of input file (mostly useful for Excellon files)
|
||||
|
||||
.. option:: --input-units <metric|us-customary>
|
||||
|
||||
Override units of input file
|
||||
|
||||
.. option:: --input-zero-suppression <off|leading|trailing>
|
||||
|
||||
Override zero suppression setting of input file
|
||||
|
||||
|
||||
``gerbonara transform``
|
||||
***********************
|
||||
|
||||
.. program:: gerbonara transform
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
gerbonara transform [OPTIONS] TRANSFORM INPATH OUTPATH
|
||||
|
||||
Transform all gerber files in a given directory or zip file using the given python transformation script.
|
||||
|
||||
In the python transformation script you have access to the functions ``translate(x, y)``, ``scale(factor)`` and
|
||||
``rotate(angle, center_x?, center_y?)``, the bounding box variables ``x_min``, ``y_min``, ``x_max``, ``y_max``,
|
||||
``width`` and ``height``, and everything from python's built-in math module (e.g. ``pi``, ``sqrt``, ``sin``). As
|
||||
convenience methods, ``center()`` and ``origin()`` are provided to center the board resp. 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)``
|
||||
|
||||
.. option:: -m, --input-map <json_file>
|
||||
|
||||
Extend or override layer name mapping with name map from JSON file. The JSON file must contain a single JSON dict
|
||||
with an arbitrary number of string: string entries. The keys are interpreted as regexes applied to the filenames via
|
||||
re.fullmatch, and each value must either be the string ``ignore`` to remove this layer from previous automatic
|
||||
guesses, or a gerbonara layer name such as ``top copper``, ``inner_2 copper`` or ``bottom silk``.
|
||||
|
||||
.. option:: --use-builtin-name-rules, --no-builtin-name-rules
|
||||
|
||||
Disable built-in layer name rules and use only rules given by ``--input-map``
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: --units <metric|us-customary>
|
||||
|
||||
Units for values given in other options. Default: millimeter
|
||||
|
||||
.. option:: -n, --number-format <decimal.fractional>
|
||||
|
||||
Override number format to use during export in ``[integer digits].[decimal digits]`` notation, e.g. ``2.6``.
|
||||
|
||||
.. option:: --default-settings, --reuse-input-settings
|
||||
|
||||
Use sensible defaults for the output file format settings (default) or use the same export settings as the input file
|
||||
instead of sensible defaults.
|
||||
|
||||
.. option:: --force-zip
|
||||
|
||||
Force treating input path as a zip file (default: guess file type from extension and contents)
|
||||
|
||||
.. option:: --output-naming-scheme <altium|kicad>
|
||||
|
||||
Name output files according to the selected naming scheme instead of keeping the old file names.
|
||||
|
||||
|
||||
``gerbonara merge``
|
||||
*******************
|
||||
|
||||
.. program:: gerbonara merge
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ gerbonara merge [OPTIONS] [INPATH]... OUTPATH
|
||||
|
||||
Merge multiple single Gerber or Excellon files, or multiple stacks of Gerber files, into one.
|
||||
|
||||
.. note::
|
||||
When used with only one input, this command *normalizes* the input, converting all files to a well-defined, widely
|
||||
supported Gerber subset with sane settings. When a ``--output-naming-scheme`` is given, it additionally renames all
|
||||
files to a standardized naming convention.
|
||||
|
||||
.. option:: --command-line-units <metric|us-customary>
|
||||
|
||||
Units for values given in --transform. Default: millimeter
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: --offset <COORDINATE>
|
||||
|
||||
Offset for the n'th file as a ``x,y`` string in unit given by ``--command-line-units`` (default: millimeter). Can be
|
||||
given multiple times, and the first option affects the first input, the second option affects the second input, and
|
||||
so on.
|
||||
|
||||
.. option:: --rotation <ROTATION>
|
||||
|
||||
Rotation for the n'th file in degrees clockwise, optionally followed by comma- separated rotation center X and Y
|
||||
coordinates. Can be given multiple times, and the first option affects the first input, the second option affects the
|
||||
second input, and so on.
|
||||
|
||||
.. option:: -m, --input-map <json_file>
|
||||
|
||||
Extend or override layer name mapping with name map from JSON file. This option can be given multiple times, in which
|
||||
case the n'th option affects only the n'th input, like with ``--offset`` and ``--rotation``. The JSON file must
|
||||
contain a single JSON dict with an arbitrary number of string: string entries. The keys are interpreted as regexes
|
||||
applied to the filenames via re.fullmatch, and each value must either be the string "ignore" to remove this layer
|
||||
from previous automatic guesses, or a gerbonara layer name such as ``top copper``, ``inner_2 copper`` or ``bottom
|
||||
silk``.
|
||||
|
||||
.. option:: --default-settings, --reuse-input-settings
|
||||
|
||||
Use sensible defaults for the output file format settings (default) or use the same export settings as the input file
|
||||
instead of sensible defaults.
|
||||
|
||||
.. option:: --output-naming-scheme <altium|kicad>
|
||||
|
||||
Name output files according to the selected naming scheme instead of keeping the old file names of the first input.
|
||||
|
||||
.. option:: --output-board-name <TEXT>
|
||||
|
||||
Override board name used with ``--output-naming-scheme``
|
||||
|
||||
.. option:: --use-builtin-name-rules, --no-builtin-name-rules
|
||||
|
||||
Disable built-in layer name rules and use only rules given by --input-map
|
||||
|
||||
File analysis
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
``gerbonara bounding-box``
|
||||
**************************
|
||||
|
||||
.. program:: gerbonara bounding-box
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
gerbonara bounding-box [OPTIONS] INFILE
|
||||
|
||||
Print the bounding box of a gerber file in ``[x_min] [y_min] [x_max] [y_max]`` format. The bounding box contains all
|
||||
graphic objects in this file, so e.g. a 100 mm by 100 mm square drawn with a 1mm width circular aperture will result in
|
||||
an 101 mm by 101 mm bounding box.
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: --units <metric|us-customary>
|
||||
|
||||
Output bounding box in this unit (default: millimeter)
|
||||
|
||||
.. option:: --input-number-format <decimal.fractional>
|
||||
|
||||
Override number format of input file (mostly useful for Excellon files)
|
||||
|
||||
.. option:: --input-units <metric|us-customary>
|
||||
|
||||
Override units of input file
|
||||
|
||||
.. option:: --input-zero-suppression <off|leading|trailing>
|
||||
|
||||
Override zero suppression setting of input file
|
||||
|
||||
|
||||
``gerbonara meta``
|
||||
******************
|
||||
.. program:: gerbonara meta
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
gerbonara meta [OPTIONS] PATH
|
||||
|
||||
Read a board from a folder or zip, and print the found layer mapping along with layer metadata as JSON to stdout. A
|
||||
machine-readable variant of the :program:`gerbonara render` command. All lengths in the JSON are given in millimeter.
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: --force-zip
|
||||
|
||||
Force treating input path as zip file (default: guess file type from extension and contents)
|
||||
|
||||
|
||||
``gerbonara layers``
|
||||
********************
|
||||
.. program:: gerbonara render
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ gerbonara layers [OPTIONS] PATH
|
||||
|
||||
Prints a layer-by-layer description of the board found under the given path. The path can be a directory or zip file.
|
||||
|
||||
.. option:: --warnings <default|ignore|once>
|
||||
|
||||
Enable or disable file format warnings during parsing (default: on)
|
||||
|
||||
.. option:: --force-zip
|
||||
|
||||
Force treating input path as zip file (default: guess file type from extension and contents)
|
||||
|
|
|
@ -357,7 +357,7 @@ class CamFile:
|
|||
def merge(self, other):
|
||||
""" Merge ``other`` into ``self``, i.e. add all objects that are in ``other`` to ``self``. This resets
|
||||
:py:attr:`.import_settings` and :py:attr:`~.CamFile.generator`. Units and other file-specific settings are
|
||||
automatically handled.
|
||||
handled automatically.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
|
|
@ -247,9 +247,10 @@ class LayerStack:
|
|||
""" :py:class:`LayerStack` represents a set of Gerber files that describe different layers of the same board.
|
||||
|
||||
:ivar graphic_layers: :py:obj:`dict` mapping :py:obj:`(side, use)` tuples to the Gerber layers of the board.
|
||||
:py:obj:`side` can be one of :py:obj:`"top"` or :py:obj:`"bottom"`, or a numbered internal
|
||||
layer such as :py:obj:`"inner2"`. :py:obj:`use` can be one of :py:obj:`"silk", :py:obj:`mask`,
|
||||
:py:obj:`paste` or :py:obj:`copper`. For internal layers, only :py:obj:`copper` is valid.
|
||||
:py:obj:`side` can be one of :py:obj:`"top"`, :py:obj:`"bottom"`, :py:obj:`"mechanical"`, or a
|
||||
numbered internal layer such as :py:obj:`"inner2"`. :py:obj:`use` can be one of
|
||||
:py:obj:`"silk", :py:obj:`mask`, :py:obj:`paste` or :py:obj:`copper`. For internal layers,
|
||||
only :py:obj:`copper` is valid.
|
||||
:ivar board_name: Name of this board as parse from the input filenames, as a :py:obj:`str`. You can overwrite this
|
||||
attribute with a different name, which will then be used during saving with the built-in file
|
||||
naming rules.
|
||||
|
@ -664,10 +665,10 @@ class LayerStack:
|
|||
color scheme. When given, must be a dict mapping semantic :py:obj:`"side use"` layer names such
|
||||
as :py:obj:`"top copper"` to a HTML-like hex color code such as :py:obj:`#ff00ea`. Transparency
|
||||
is supported through 8-digit color codes. When 8 digits are given, the last two digits are used
|
||||
as the layer's alpha channel. Valid side values in the layer name strings are :py:obj:`"top"` and
|
||||
:py:obj:`"bottom"` as well as :py:obj:`"inner1"`, :py:obj:`"inner2"` etc. for internal layers.
|
||||
Valid use values are :py:obj:`"mask"`, :py:obj:`"silk"`, :py:obj:`"paste"`, and
|
||||
:py:obj:`"copper"`. For internal layers, only :py:obj:`"copper"` is valid.
|
||||
as the layer's alpha channel. Valid side values in the layer name strings are :py:obj:`"top"`,
|
||||
:py:obj:`"bottom"`, and :py:obj:`"mechanical"` as well as :py:obj:`"inner1"`, :py:obj:`"inner2"`
|
||||
etc. for internal layers. Valid use values are :py:obj:`"mask"`, :py:obj:`"silk"`,
|
||||
:py:obj:`"paste"`, and :py:obj:`"copper"`. For internal layers, only :py:obj:`"copper"` is valid.
|
||||
:rtype: :py:obj:`str`
|
||||
"""
|
||||
if colors is None:
|
||||
|
@ -798,6 +799,9 @@ class LayerStack:
|
|||
layer.scale(factor)
|
||||
|
||||
def merge_drill_layers(self):
|
||||
""" Merge all drill layers of this board into a single drill layer containing all objetcs. You can access this
|
||||
drill layer under the :py:attr:`.LayerStack.drill_unknown` attribute. The original layers are removed from the
|
||||
board. """
|
||||
target = ExcellonFile(comments=['Drill files merged by gerbonara'])
|
||||
|
||||
for layer in self.drill_layers:
|
||||
|
@ -810,6 +814,9 @@ class LayerStack:
|
|||
self.drill_unknown = target
|
||||
|
||||
def normalize_drill_layers(self):
|
||||
""" Take everything from all drill layers of this board, and sort it into three new drill layers: One with all
|
||||
non-plated objects, one with all plated objects, and one for all leftover objects with unknown plating. This
|
||||
method replaces the board's drill layers with these three sorted ones. """
|
||||
# TODO: maybe also separate into drill and route?
|
||||
drill_pth, drill_npth, drill_aux = [], [], []
|
||||
|
||||
|
@ -848,6 +855,8 @@ class LayerStack:
|
|||
|
||||
@property
|
||||
def drill_layers(self):
|
||||
""" Return all of this board's drill layers as a list. Returns an empty list if the board does not have any
|
||||
drill layers. """
|
||||
if self._drill_layers:
|
||||
return self._drill_layers
|
||||
if self.drill_pth or self.drill_npth or self.drill_unknown:
|
||||
|
@ -890,6 +899,8 @@ class LayerStack:
|
|||
|
||||
@property
|
||||
def copper_layers(self):
|
||||
""" Return all copper layers of this board as a list. Returns an empty list if the board does not have any
|
||||
copper layers. """
|
||||
copper_layers = [ ((side, use), layer) for (side, use), layer in self.graphic_layers.items() if use == 'copper' ]
|
||||
|
||||
def sort_layername(val):
|
||||
|
@ -905,17 +916,27 @@ class LayerStack:
|
|||
|
||||
@property
|
||||
def top_side(self):
|
||||
""" Return a dict containing the subset of layers from :py:meth:`~.layers.LayerStack.graphic_layers` that are on
|
||||
the board's top side. Includes the board outline layer, if available. """
|
||||
return { key: self[key] for key in ('top copper', 'top mask', 'top silk', 'top paste', 'mechanical outline') }
|
||||
|
||||
@property
|
||||
def bottom_side(self):
|
||||
""" Return a dict containing the subset of layers from :py:meth:`~.layers.LayerStack.graphic_layers` that are on
|
||||
the board's bottom side. Includes the board outline layer, if available. """
|
||||
return { key: self[key] for key in ('bottom copper', 'bottom mask', 'bottom silk', 'bottom paste', 'mechanical outline') }
|
||||
|
||||
@property
|
||||
def outline(self):
|
||||
""" Return this board's outline layer if available, or :py:obj:`None`. """
|
||||
return self.get('mechanical outline')
|
||||
|
||||
def outline_svg_d(self, tol=0.01, unit=MM):
|
||||
""" Return this board's outline as SVG path data.
|
||||
|
||||
:param tol: :py:obj:`float` setting the tolerance below which two points are considered equal
|
||||
:param unit: :py:class:`.LengthUnit` or str (``'mm'`` or ``'inch'``). SVG document unit. Default: mm
|
||||
"""
|
||||
chains = self.outline_polygons(tol, unit)
|
||||
polys = []
|
||||
for chain in chains:
|
||||
|
@ -926,6 +947,19 @@ class LayerStack:
|
|||
return ' '.join(polys)
|
||||
|
||||
def outline_polygons(self, tol=0.01, unit=MM):
|
||||
""" Iterator yielding this boards outline as a list of ordered :py:class:`~.graphic_objects.Arc` and
|
||||
:py:class:`~.graphic_objects.Line` objects. This method first sorts all lines and arcs on the outline layer into
|
||||
connected components, then orders them such that one object's end point is the next object's start point,
|
||||
flipping them where necessary. It yields one list of (likely mixed) :py:class:`~.graphic_objects.Arc` and
|
||||
:py:class:`~.graphic_objects.Line` objects per connected component.
|
||||
|
||||
This method exists because the only convention in Gerber or Excellon outline files is that the outline segments
|
||||
are *visually contiguous*, but that does not necessarily mean that they will be in any particular order inside
|
||||
the G-code.
|
||||
|
||||
:param tol: :py:obj:`float` setting the tolerance below which two points are considered equal
|
||||
:param unit: :py:class:`.LengthUnit` or str (``'mm'`` or ``'inch'``). SVG document unit. Default: mm
|
||||
"""
|
||||
polygons = []
|
||||
lines = [ obj.as_primitive(unit) for obj in self.outline.instance.objects if isinstance(obj, (go.Line, go.Arc)) ]
|
||||
|
||||
|
@ -975,7 +1009,7 @@ class LayerStack:
|
|||
yield l
|
||||
|
||||
|
||||
def _merge_layer(self, target, source):
|
||||
def _merge_layer(self, target, source, mode='above'):
|
||||
if source is None:
|
||||
return
|
||||
|
||||
|
@ -983,9 +1017,18 @@ class LayerStack:
|
|||
self[target] = source
|
||||
|
||||
else:
|
||||
self[target].merge(source)
|
||||
self[target].merge(source, mode)
|
||||
|
||||
def merge(self, other):
|
||||
def merge(self, other, mode='above'):
|
||||
""" Merge ``other`` into ``self``, i.e. for all layers, add all objects that are in ``other`` to ``self``. This
|
||||
resets :py:attr:`.import_settings` and :py:attr:`~.CamFile.generator` on all layers. Units and other
|
||||
file-specific settings are handled automatically. For the meaning of the ``mode`` parameter, see
|
||||
:py:meth:`.GerberFile.merge`.
|
||||
|
||||
Layers are matched by their logical side and function as they are found in
|
||||
:py:meth:`.LayerStack.graphic_layers`. Drill layers are normalized before merging, which splits them into
|
||||
exactly three drill layers: An non-plated one, a plated one, and a (hopefully empty) unknown plating one.
|
||||
"""
|
||||
all_keys = set(self.graphic_layers.keys()) | set(other.graphic_layers.keys())
|
||||
exclude = { tuple(key.split()) for key in STANDARD_LAYERS }
|
||||
all_keys = { key for key in all_keys if key not in exclude }
|
||||
|
@ -995,7 +1038,7 @@ class LayerStack:
|
|||
for side in 'top', 'bottom':
|
||||
for use in 'copper', 'mask', 'silk', 'paste':
|
||||
if (side, use) in other:
|
||||
self._merge_layer((side, use), other[side, use])
|
||||
self._merge_layer((side, use), other[side, use], mode)
|
||||
|
||||
our_inner, their_inner = self.copper_layers[1:-1], other.copper_layers[1:-1]
|
||||
|
||||
|
|
|
@ -46,6 +46,20 @@ def points_close(a, b):
|
|||
|
||||
class GerberFile(CamFile):
|
||||
""" A single gerber file.
|
||||
|
||||
:ivar objects: List of objects in this Gerber file. All elements must be subclasses of :py:class:`.GraphicObject`.
|
||||
:ivar comments: List of string with textual comments in the source Gerber file. These are not saved by default, but
|
||||
when you call :py:meth:`.GerberFile.save` with ``drop_comments=False``, the contents of this list
|
||||
will be included as comments at the top of the output file.
|
||||
:ivar generator_hints: List of strings indicating which EDA tool generated this file. Hints are added to this list
|
||||
during file parsing whenever the parser encounters an idiosyncratic file format variation.
|
||||
:ivar import_settings: File format settings used in the original file. This can be empty if this
|
||||
:py:class:`.GerberFile` was generated programatically.
|
||||
:ivar layer_hints: Similar to ``generator_hints``, this is a list containing hints which layer type this file could
|
||||
belong to. Usually, this will be empty, but some EDA tools automatically include layer
|
||||
information inside tool-specific comments in the Gerber files they generate.
|
||||
:ivar apertures: List of apertures used in this file. Make sure you keep this in sync when adding new objects.
|
||||
:ivar file_attrs: List of strings with Gerber X3 file attributes. Each list item corresponds to one file attribute.
|
||||
"""
|
||||
|
||||
def __init__(self, objects=None, comments=None, import_settings=None, original_path=None, generator_hints=None,
|
||||
|
@ -83,6 +97,16 @@ class GerberFile(CamFile):
|
|||
return
|
||||
|
||||
def merge(self, other, mode='above', keep_settings=False):
|
||||
""" Merge ``other`` into ``self``, i.e. add all objects that are in ``other`` to ``self``. This resets
|
||||
:py:attr:`.import_settings` and :py:attr:`~.GerberFile.generator`. Units and other file-specific settings are
|
||||
handled automatically.
|
||||
|
||||
:param mode: One of the strings :py:obj:`"above"` (default) or :py:obj:`"below"`, specifying whether the other
|
||||
layer's objects will be placed above this layer's objects (placing them towards the end of the file), or
|
||||
below this layer's objects (placing them towards the beginning of the file). This setting is only relevant
|
||||
when there are overlapping objects of different polarity, otherwise the rendered result will be the same
|
||||
either way.
|
||||
"""
|
||||
if other is None:
|
||||
return
|
||||
|
||||
|
@ -109,6 +133,7 @@ class GerberFile(CamFile):
|
|||
self.objects += other.objects
|
||||
else:
|
||||
raise ValueError(f'Invalid mode "{mode}", must be one of "above" or "below".')
|
||||
|
||||
for obj in self.objects:
|
||||
# If object has an aperture attribute, replace that aperture.
|
||||
if (ap := replace_apertures.get(id(getattr(obj, 'aperture', None)))):
|
||||
|
@ -316,7 +341,8 @@ class GerberFile(CamFile):
|
|||
|
||||
|
||||
class GraphicsState:
|
||||
""" Internal class used to track Gerber processing state during import and export. """
|
||||
""" Internal class used to track Gerber processing state during import and export.
|
||||
"""
|
||||
|
||||
def __init__(self, warn, file_settings=None, aperture_map=None):
|
||||
self.image_polarity = 'positive' # IP image polarity; deprecated
|
||||
|
@ -527,7 +553,8 @@ class GraphicsState:
|
|||
|
||||
|
||||
class GerberParser:
|
||||
""" Internal class that contains all of the actual Gerber parsing magic. """
|
||||
""" Internal class that contains all of the actual Gerber parsing magic.
|
||||
"""
|
||||
|
||||
NUMBER = r"[\+-]?\d+"
|
||||
DECIMAL = r"[\+-]?\d+([.]?\d+)?"
|
||||
|
|
Ładowanie…
Reference in New Issue