Added SVG importing support to the GUI menu. See issue #179.

This commit is contained in:
Juan Pablo Caram 2015-12-18 16:43:47 -05:00
parent fdf809774f
commit d3ed12e5de
4 changed files with 76 additions and 4 deletions

View File

@ -430,6 +430,7 @@ class App(QtCore.QObject):
self.ui.menufileopenexcellon.triggered.connect(self.on_fileopenexcellon)
self.ui.menufileopengcode.triggered.connect(self.on_fileopengcode)
self.ui.menufileopenproject.triggered.connect(self.on_file_openproject)
self.ui.menufileimportsvg.triggered.connect(self.on_file_importsvg)
self.ui.menufilesaveproject.triggered.connect(self.on_file_saveproject)
self.ui.menufilesaveprojectas.triggered.connect(self.on_file_saveprojectas)
self.ui.menufilesaveprojectcopy.triggered.connect(lambda: self.on_file_saveprojectas(make_copy=True))
@ -1543,6 +1544,29 @@ class App(QtCore.QObject):
# thread safe. The new_project()
self.open_project(filename)
def on_file_importsvg(self):
"""
Callback for menu item File->Import SVG.
:return: None
"""
self.report_usage("on_file_importsvg")
App.log.debug("on_file_importsvg()")
try:
filename = QtGui.QFileDialog.getOpenFileName(caption="Import SVG",
directory=self.get_last_folder())
except TypeError:
filename = QtGui.QFileDialog.getOpenFileName(caption="Import SVG")
filename = str(filename)
if str(filename) == "":
self.inform.emit("Open cancelled.")
else:
self.worker_task.emit({'fcn': self.import_svg,
'params': [filename]})
def on_file_saveproject(self):
"""
Callback for menu item File->Save Project. Saves the project to

View File

@ -28,7 +28,7 @@ class FlatCAMGUI(QtGui.QMainWindow):
# Recent
self.recent = self.menufile.addMenu(QtGui.QIcon('share/folder16.png'), "Open recent ...")
# Open gerber
# Open gerber ...
self.menufileopengerber = QtGui.QAction(QtGui.QIcon('share/folder16.png'), 'Open &Gerber ...', self)
self.menufile.addAction(self.menufileopengerber)
@ -40,6 +40,10 @@ class FlatCAMGUI(QtGui.QMainWindow):
self.menufileopengcode = QtGui.QAction(QtGui.QIcon('share/folder16.png'), 'Open G-&Code ...', self)
self.menufile.addAction(self.menufileopengcode)
# Import SVG ...
self.menufileimportsvg = QtGui.QAction(QtGui.QIcon('share/folder16.png'), 'Import &SVG ...', self)
self.menufile.addAction(self.menufileimportsvg)
# Open Project ...
self.menufileopenproject = QtGui.QAction(QtGui.QIcon('share/folder16.png'), 'Open &Project ...', self)
self.menufile.addAction(self.menufileopenproject)

View File

@ -358,6 +358,7 @@ class Geometry(object):
Imports shapes from an SVG file into the object's geometry.
:param filename: Path to the SVG file.
:type filename: str
:return: None
"""

View File

@ -2,15 +2,24 @@
# FlatCAM: 2D Post-processing for Manufacturing #
# http://flatcam.org #
# Author: Juan Pablo Caram (c) #
# Date: 12/18/2015 #
# Date: 12/18/2015 #
# MIT Licence #
# #
# SVG Features supported: #
# * Groups #
# * Rectangles #
# * Circles #
# * Paths #
# * All transformations #
# #
# Reference: www.w3.org/TR/SVG/Overview.html #
############################################################
import xml.etree.ElementTree as ET
import re
import itertools
from svg.path import Path, Line, Arc, CubicBezier, QuadraticBezier, parse_path
from shapely.geometry import LinearRing, LineString
from shapely.geometry import LinearRing, LineString, Point
from shapely.affinity import translate, rotate, scale, skew, affine_transform
@ -43,10 +52,13 @@ def path2shapely(path, res=1.0):
if isinstance(component, Arc) or \
isinstance(component, CubicBezier) or \
isinstance(component, QuadraticBezier):
# How many points to use in the dicrete representation.
length = component.length(res / 10.0)
steps = int(length / res + 0.5)
frac = 1.0 / steps
print length, steps, frac
# print length, steps, frac
for i in range(steps):
point = component.point(i * frac)
x, y = point.real, point.imag
@ -66,6 +78,16 @@ def path2shapely(path, res=1.0):
def svgrect2shapely(rect):
"""
Converts an SVG rect into Shapely geometry.
:param rect: Rect Element
:type rect: xml.etree.ElementTree.Element
:return: shapely.geometry.polygon.LinearRing
:param rect:
:return:
"""
w = float(rect.get('width'))
h = float(rect.get('height'))
x = float(rect.get('x'))
@ -76,6 +98,22 @@ def svgrect2shapely(rect):
return LinearRing(pts)
def svgcircle2shapely(circle):
"""
Converts an SVG circle into Shapely geometry.
:param circle: Circle Element
:type circle: xml.etree.ElementTree.Element
:return: shapely.geometry.polygon.LinearRing
"""
cx = float(circle.get('cx'))
cy = float(circle.get('cy'))
r = float(circle.get('r'))
# TODO: No resolution specified.
return Point(cx, cy).buffer(r)
def getsvggeo(node):
"""
Extracts and flattens all geometry from an SVG node
@ -106,6 +144,11 @@ def getsvggeo(node):
R = svgrect2shapely(node)
geo = [R]
elif kind == 'circle':
print "***CIRCLE***"
C = svgcircle2shapely(node)
geo = [C]
else:
print "Unknown kind:", kind
geo = None