diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bfb937d..e80952cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta ================================================= +21.01.2021 + +- added ability to see the verbose log when importing SVG's (if set in preferences) +- added some more logs to the SVG import + 19.01.2021 - fixed the Gerber export to convert all the aperture macros to regions and therefore export also the data from aperture macros diff --git a/appParsers/ParseGerber.py b/appParsers/ParseGerber.py index e820ef50..d667773a 100644 --- a/appParsers/ParseGerber.py +++ b/appParsers/ParseGerber.py @@ -73,15 +73,17 @@ class Gerber(Geometry): def __init__(self, steps_per_circle=None): """ - The constructor takes no parameters. Use ``gerber.parse_files()`` - or ``gerber.parse_lines()`` to populate the object from Gerber source. + Use ``gerber.parse_files()`` or ``gerber.parse_lines()`` to populate the object from Gerber source. :return: Gerber object :rtype: Gerber """ # How to approximate a circle with lines. - self.steps_per_circle = int(self.app.defaults["gerber_circle_steps"]) + if steps_per_circle is None: + self.steps_per_circle = int(self.app.defaults["gerber_circle_steps"]) + else: + self.steps_per_circle = steps_per_circle self.decimals = self.app.decimals # Initialize parent @@ -1905,9 +1907,13 @@ class Gerber(Geometry): units = self.app.defaults['units'] if units is None else units res = self.app.defaults['gerber_circle_steps'] factor = svgparse_viewbox(svg_root) - geos = getsvggeo(svg_root, 'gerber', units=units, res=res, factor=factor) + geos = getsvggeo(svg_root, 'gerber', units=units, res=res, factor=factor, app=self.app) + + self.app.log.debug("appParsers.ParseGerber.Gerber.import_svg(). Finished parsing the SVG geometry.") + if flip: geos = [translate(scale(g, 1.0, -1.0, origin=(0, 0)), yoff=h) for g in geos] + self.app.log.debug("appParsers.ParseGerber.Gerber.import_svg(). SVG geometry was flipped.") # Add to object if self.solid_geometry is None: diff --git a/appParsers/ParseSVG.py b/appParsers/ParseSVG.py index e0b9c4c4..4b4b83aa 100644 --- a/appParsers/ParseSVG.py +++ b/appParsers/ParseSVG.py @@ -393,7 +393,7 @@ def svgpolygon2shapely(polygon, n_points=64, factor=1.0): # return LinearRing(points) -def getsvggeo(node, object_type, root=None, units='MM', res=64, factor=1.0): +def getsvggeo(node, object_type, root=None, units='MM', res=64, factor=1.0, app=None): """ Extracts and flattens all geometry from an SVG node into a list of Shapely geometry. @@ -405,19 +405,26 @@ def getsvggeo(node, object_type, root=None, units='MM', res=64, factor=1.0): :param res: resolution to be used for circles buffering :param factor: correction factor due of virtual units :type factor: float + :param app: Application reference + :return: List of Shapely geometry :rtype: list """ if root is None: root = node + if app is not None: + log = app.log + else: + log = logging.getLogger('base2') + kind = re.search('(?:\{.*\})?(.*)$', node.tag).group(1) geo = [] # Recurse if len(node) > 0: for child in node: - subgeo = getsvggeo(child, object_type, root=root, units=units, res=res, factor=factor) + subgeo = getsvggeo(child, object_type, root=root, units=units, res=res, factor=factor, app=app) if subgeo is not None: geo += subgeo # Parse @@ -465,7 +472,10 @@ def getsvggeo(node, object_type, root=None, units='MM', res=64, factor=1.0): href = node.attrib['href'] if 'href' in node.attrib else node.attrib['{http://www.w3.org/1999/xlink}href'] ref = root.find(".//*[@id='%s']" % href.replace('#', '')) if ref is not None: - geo = getsvggeo(ref, object_type, root=root, units=units, res=res, factor=factor) + geo = getsvggeo(ref, object_type, root=root, units=units, res=res, factor=factor, app=app) + + elif kind in ['defs', 'namedview', 'format', 'type', 'title']: + log.warning('SVG Element not supported: %s. Skipping to next.' % kind) else: log.warning("Unknown kind: " + kind) @@ -568,11 +578,12 @@ def getsvgtext(node, object_type, app, units='MM'): geo = [(scale(g, 1.0, -1.0)) for g in geo] except Exception as e: log.error(str(e)) + geo = None else: geo = None # ignore transformation for unknown kind - if geo is not None: + if geo and geo is not None: # Transformations if 'transform' in node.attrib: trstr = node.get('transform') @@ -597,6 +608,9 @@ def getsvgtext(node, object_type, app, units='MM'): else: raise Exception('Unknown transformation: %s', tr) + if not geo: + geo = None + return geo diff --git a/appTools/ToolQRCode.py b/appTools/ToolQRCode.py index c859958f..5271a061 100644 --- a/appTools/ToolQRCode.py +++ b/appTools/ToolQRCode.py @@ -486,6 +486,8 @@ class QRCode(AppTool): :return: None """ + self.app.log.debug("QRCode.import_svg()") + # Parse into list of shapely objects svg_tree = ET.parse(filename) svg_root = svg_tree.getroot() @@ -497,16 +499,21 @@ class QRCode(AppTool): units = self.app.defaults['units'] if units is None else units res = self.app.defaults['geometry_circle_steps'] factor = svgparse_viewbox(svg_root) - geos = getsvggeo(svg_root, object_type, units=units, res=res, factor=factor) + geos = getsvggeo(svg_root, object_type, units=units, res=res, factor=factor, app=self.app) + + self.app.log.debug("QRCode.import_svg(). Finished parsing the SVG geometry.") if flip: geos = [translate(scale(g, 1.0, -1.0, origin=(0, 0)), yoff=h) for g in geos] + self.app.log.debug("QRCode.import_svg(). SVG geometry was flipped.") # flatten the svg geometry for the case when the QRCode SVG is added into a Gerber object solid_geometry = list(self.flatten_list(geos)) geos_text = getsvgtext(svg_root, object_type, app=self.app, units=units) if geos_text is not None: + self.app.log.debug("QRCode.import_svg(). Processing SVG text.") + geos_text_f = [] if flip: # Change origin to bottom left diff --git a/camlib.py b/camlib.py index 6fac92d8..7bcf6184 100644 --- a/camlib.py +++ b/camlib.py @@ -1151,7 +1151,7 @@ class Geometry(object): :return: None """ - log.debug("camlib.Geometry.import_svg()") + self.app.log.debug("camlib.Geometry.import_svg()") # Parse into list of shapely objects svg_tree = ET.parse(filename) @@ -1166,9 +1166,13 @@ class Geometry(object): res = self.app.defaults['geometry_circle_steps'] factor = svgparse_viewbox(svg_root) - geos = getsvggeo(svg_root, object_type, units=units, res=res, factor=factor) + geos = getsvggeo(svg_root, object_type, units=units, res=res, factor=factor, app=self.app) + + self.app.log.debug("camlib.Geometry.import_svg(). Finished parsing the SVG geometry.") + if flip: geos = [translate(scale(g, 1.0, -1.0, origin=(0, 0)), yoff=h) for g in geos] + self.app.log.debug("camlib.Geometry.import_svg(). SVG geometry was flipped.") # trying to optimize the resulting geometry by merging contiguous lines geos = list(self.flatten_list(geos)) @@ -1180,7 +1184,13 @@ class Geometry(object): else: geos_lines.append(g) - merged_lines = linemerge(geos_lines) + try: + merged_lines = linemerge(geos_lines) + except Exception: + merged_lines = geos_lines + self.app.log.error( + 'camlib.Geometry.import_svg(). Could not merge the lines, working with the original SVG geometry.') + geos = geos_polys try: for ml in merged_lines: @@ -1204,7 +1214,9 @@ class Geometry(object): self.solid_geometry = list(self.flatten_list(self.solid_geometry)) geos_text = getsvgtext(svg_root, object_type, app=self.app, units=units) + if geos_text is not None: + self.app.log.debug("camlib.Geometry.import_svg(). Processing SVG text.") geos_text_f = [] if flip: # Change origin to bottom left