kopia lustrzana https://gitlab.com/gerbolyze/gerbonara
Improve layer stack handling
rodzic
800827b2c5
commit
0295440770
|
@ -444,5 +444,8 @@ class LazyCamFile:
|
|||
|
||||
def save(self, filename, *args, **kwargs):
|
||||
""" Copy this Gerber file to the new path. """
|
||||
shutil.copy(self.original_path, filename)
|
||||
if 'instance' in self.__dict__: # instance has been loaded, and might have been modified
|
||||
self.instance.save(filename, *args, **kwargs)
|
||||
else:
|
||||
shutil.copy(self.original_path, filename)
|
||||
|
||||
|
|
|
@ -245,6 +245,16 @@ class ExcellonFile(CamFile):
|
|||
""" Test if there are multiple plating values used in this file. """
|
||||
return len({obj.plated for obj in self.objects}) > 1
|
||||
|
||||
@property
|
||||
def is_plated_tristate(self):
|
||||
if self.is_plated:
|
||||
return True
|
||||
|
||||
if self.is_nonplated:
|
||||
return False
|
||||
|
||||
return None
|
||||
|
||||
def append(self, obj_or_comment):
|
||||
""" Add a :py:class:`.GraphicObject` or a comment (str) to this file. """
|
||||
if isinstance(obj_or_comment, str):
|
||||
|
@ -252,11 +262,11 @@ class ExcellonFile(CamFile):
|
|||
else:
|
||||
self.objects.append(obj_or_comment)
|
||||
|
||||
def to_excellon(self):
|
||||
def to_excellon(self, plated=None, errors='raise'):
|
||||
""" Counterpart to :py:meth:`~.rs274x.GerberFile.to_excellon`. Does nothing and returns :py:obj:`self`. """
|
||||
return self
|
||||
|
||||
def to_gerber(self):
|
||||
def to_gerber(self, errros='raise'):
|
||||
""" Convert this excellon file into a :py:class:`~.rs274x.GerberFile`. """
|
||||
apertures = {}
|
||||
out = GerberFile()
|
||||
|
@ -274,14 +284,18 @@ class ExcellonFile(CamFile):
|
|||
def generator(self):
|
||||
return self.generator_hints[0] if self.generator_hints else None
|
||||
|
||||
def merge(self, other):
|
||||
def merge(self, other, mode='ignored', keep_settings=False):
|
||||
if other is None:
|
||||
return
|
||||
|
||||
if not isinstance(other, ExcellonFile):
|
||||
other = other.to_excellon(plated=self.is_plated_tristate)
|
||||
|
||||
self.objects += other.objects
|
||||
self.comments += other.comments
|
||||
self.generator_hints = None
|
||||
self.import_settings = None
|
||||
if not keep_settings:
|
||||
self.import_settings = None
|
||||
|
||||
@classmethod
|
||||
def open(kls, filename, plated=None, settings=None, external_tools=None):
|
||||
|
|
|
@ -113,16 +113,22 @@ class NamingScheme:
|
|||
def _match_files(filenames):
|
||||
matches = {}
|
||||
for generator, rules in MATCH_RULES.items():
|
||||
already_matched = set()
|
||||
gen = {}
|
||||
matches[generator] = gen
|
||||
for layer, regex in rules.items():
|
||||
for fn in filenames:
|
||||
if fn in already_matched:
|
||||
continue
|
||||
|
||||
if (m := re.fullmatch(regex, fn.name, re.IGNORECASE)):
|
||||
if layer == 'inner copper':
|
||||
target = 'inner_' + ''.join(e or '' for e in m.groups()) + ' copper'
|
||||
else:
|
||||
target = layer
|
||||
|
||||
gen[target] = gen.get(target, []) + [fn]
|
||||
already_matched.add(fn)
|
||||
return matches
|
||||
|
||||
|
||||
|
@ -615,8 +621,10 @@ class LayerStack:
|
|||
|
||||
if self.drill_pth is not None:
|
||||
yield get_name('plated drill', self.drill_pth), self.drill_pth
|
||||
|
||||
if self.drill_npth is not None:
|
||||
yield get_name('nonplated drill', self.drill_npth), self.drill_npth
|
||||
|
||||
for layer in self._drill_layers:
|
||||
yield get_name('unknown drill', layer), layer
|
||||
|
||||
|
@ -872,8 +880,7 @@ class LayerStack:
|
|||
npth_out.append(obj)
|
||||
|
||||
self.drill_pth, self.drill_npth = pth_out, npth_out
|
||||
self._drill_layers = unknown_out if unknown_out else None
|
||||
self._drill_layers = []
|
||||
self._drill_layers = [unknown_out] if unknown_out else []
|
||||
|
||||
@property
|
||||
def drill_layers(self):
|
||||
|
|
|
@ -73,7 +73,7 @@ class GerberFile(CamFile):
|
|||
self.apertures = [] # FIXME get rid of this? apertures are already in the objects.
|
||||
self.file_attrs = file_attrs or {}
|
||||
|
||||
def to_excellon(self, plated=None):
|
||||
def to_excellon(self, plated=None, errors='raise'):
|
||||
""" Convert this excellon file into a :py:class:`~.excellon.ExcellonFile`. This will convert interpolated lines
|
||||
into slots, and circular aperture flashes into holes. Other features such as ``G36`` polygons or flashes with
|
||||
non-circular apertures will result in a :py:obj:`ValueError`. You can, of course, programmatically remove such
|
||||
|
@ -83,7 +83,15 @@ class GerberFile(CamFile):
|
|||
for obj in self.objects:
|
||||
if not (isinstance(obj, go.Line) or isinstance(obj, go.Arc) or isinstance(obj, go.Flash)) or \
|
||||
not isinstance(obj.aperture, apertures.CircleAperture):
|
||||
raise ValueError(f'Cannot convert {obj} to excellon!')
|
||||
if errors == 'raise':
|
||||
raise ValueError(f'Cannot convert {obj} to excellon.')
|
||||
elif errors == 'warn':
|
||||
warnings.warn(f'Gerber to Excellon conversion: Cannot convert {obj} to excellon.')
|
||||
continue
|
||||
elif errors == 'ignore':
|
||||
continue
|
||||
else:
|
||||
raise ValueError('Invalid "errors" parameter. Allowed values: "raise", "warn" or "ignore".')
|
||||
|
||||
if not (new_tool := new_tools.get(id(obj.aperture))):
|
||||
# TODO plating?
|
||||
|
@ -92,9 +100,9 @@ class GerberFile(CamFile):
|
|||
|
||||
return ExcellonFile(objects=new_objs, comments=self.comments)
|
||||
|
||||
def to_gerber(self):
|
||||
def to_gerber(self, errors='raise'):
|
||||
""" Counterpart to :py:meth:`~.excellon.ExcellonFile.to_gerber`. Does nothing and returns :py:obj:`self`. """
|
||||
return
|
||||
return self
|
||||
|
||||
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
|
||||
|
@ -110,6 +118,8 @@ class GerberFile(CamFile):
|
|||
if other is None:
|
||||
return
|
||||
|
||||
other = other.to_gerber()
|
||||
|
||||
if not keep_settings:
|
||||
self.import_settings = None
|
||||
self.comments += other.comments
|
||||
|
|
Ładowanie…
Reference in New Issue