--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/printrun-src/printrun/svg2gcode/shapes.py Fri Jun 03 09:42:44 2016 +0200 @@ -0,0 +1,197 @@ +#!/usr/bin/env python + +import logging +import traceback +import xml.etree.ElementTree as ET +import simplepath +import simpletransform +import cubicsuperpath +import cspsubdiv +from bezmisc import beziersplitatt + + +class svgshape(object): + + def __init__(self, xml_node): + self.xml_node = xml_node + + def d_path(self): + raise NotImplementedError + + def transformation_matrix(self): + t = self.xml_node.get('transform') + return simpletransform.parseTransform(t) if t is not None else None + + def svg_path(self): + return "<path d=\"" + self.d_path() + "\"/>" + + def __str__(self): + return self.xml_node + +class path(svgshape): + def __init__(self, xml_node): + super(path, self).__init__(xml_node) + + if not self.xml_node == None: + path_el = self.xml_node + self.d = path_el.get('d') + else: + self.d = None + logging.error("path: Unable to get the attributes for %s", self.xml_node) + + def d_path(self): + return self.d + +class rect(svgshape): + + def __init__(self, xml_node): + super(rect, self).__init__(xml_node) + + if not self.xml_node == None: + rect_el = self.xml_node + self.x = float(rect_el.get('x')) if rect_el.get('x') else 0 + self.y = float(rect_el.get('y')) if rect_el.get('y') else 0 + self.rx = float(rect_el.get('rx')) if rect_el.get('rx') else 0 + self.ry = float(rect_el.get('ry')) if rect_el.get('ry') else 0 + self.width = float(rect_el.get('width')) if rect_el.get('width') else 0 + self.height = float(rect_el.get('height')) if rect_el.get('height') else 0 + else: + self.x = self.y = self.rx = self.ry = self.width = self.height = 0 + logging.error("rect: Unable to get the attributes for %s", self.xml_node) + + def d_path(self): + a = list() + a.append( ['M ', [self.x, self.y]] ) + a.append( [' l ', [self.width, 0]] ) + a.append( [' l ', [0, self.height]] ) + a.append( [' l ', [-self.width, 0]] ) + #a.append( [' l ', [self.x, self.y]] ) # CLOSE RECTANGLE! + a.append( [' Z', []] ) + return simplepath.formatPath(a) + +class ellipse(svgshape): + + def __init__(self, xml_node): + super(ellipse, self).__init__(xml_node) + + if not self.xml_node == None: + ellipse_el = self.xml_node + self.cx = float(ellipse_el.get('cx')) if ellipse_el.get('cx') else 0 + self.cy = float(ellipse_el.get('cy')) if ellipse_el.get('cy') else 0 + self.rx = float(ellipse_el.get('rx')) if ellipse_el.get('rx') else 0 + self.ry = float(ellipse_el.get('ry')) if ellipse_el.get('ry') else 0 + else: + self.cx = self.cy = self.rx = self.ry = 0 + logging.error("ellipse: Unable to get the attributes for %s", self.xml_node) + + def d_path(self): + x1 = self.cx - self.rx + x2 = self.cx + self.rx + p = 'M %f,%f ' % ( x1, self.cy ) + \ + 'A %f,%f ' % ( self.rx, self.ry ) + \ + '0 1 0 %f,%f ' % ( x2, self.cy ) + \ + 'A %f,%f ' % ( self.rx, self.ry ) + \ + '0 1 0 %f,%f' % ( x1, self.cy ) + return p + +class circle(ellipse): + def __init__(self, xml_node): + super(ellipse, self).__init__(xml_node) + + if not self.xml_node == None: + circle_el = self.xml_node + self.cx = float(circle_el.get('cx')) if circle_el.get('cx') else 0 + self.cy = float(circle_el.get('cy')) if circle_el.get('cy') else 0 + self.rx = float(circle_el.get('r')) if circle_el.get('r') else 0 + self.ry = self.rx + else: + self.cx = self.cy = self.r = 0 + logging.error("Circle: Unable to get the attributes for %s", self.xml_node) + +class line(svgshape): + + def __init__(self, xml_node): + super(line, self).__init__(xml_node) + + if not self.xml_node == None: + line_el = self.xml_node + self.x1 = float(line_el.get('x1')) if line_el.get('x1') else 0 + self.y1 = float(line_el.get('y1')) if line_el.get('y1') else 0 + self.x2 = float(line_el.get('x2')) if line_el.get('x2') else 0 + self.y2 = float(line_el.get('y2')) if line_el.get('y2') else 0 + else: + self.x1 = self.y1 = self.x2 = self.y2 = 0 + logging.error("line: Unable to get the attributes for %s", self.xml_node) + + def d_path(self): + a = [] + a.append( ['M ', [self.x1, self.y1]] ) + a.append( ['L ', [self.x2, self.y2]] ) + return simplepath.formatPath(a) + +class polycommon(svgshape): + + def __init__(self, xml_node, polytype): + super(polycommon, self).__init__(xml_node) + self.points = list() + + if not self.xml_node == None: + polycommon_el = self.xml_node + points = polycommon_el.get('points') if polycommon_el.get('points') else list() + points = points.split() + for pa in points: + self.points.append(pa) + if polycommon_el.get('fill'): + # Append first point to close shape + #self.points.append(points[0]) + print repr(self.points) + else: + logging.error("polycommon: Unable to get the attributes for %s", self.xml_node) + + +class polygon(polycommon): + + def __init__(self, xml_node): + super(polygon, self).__init__(xml_node, 'polygon') + + def d_path(self): + d = "M " + self.points[0] + for i in range( 1, len(self.points) ): + d += " L " + self.points[i] + d += " Z" + return d + +class polyline(polycommon): + + def __init__(self, xml_node): + super(polyline, self).__init__(xml_node, 'polyline') + + def d_path(self): + d = "M " + self.points[0] + for i in range( 1, len(self.points) ): + d += " L " + self.points[i] + return d + +def point_generator(path, mat, flatness): + simple_path = simplepath.parsePath(path) + + if len(simple_path) == 0: + return + + startX,startY = float(simple_path[0][1][0]), float(simple_path[0][1][1]) + yield startX, startY, False + + p = cubicsuperpath.parsePath(path) + + if mat: + simpletransform.applyTransformToPath(mat, p) + + for sp in p: + cspsubdiv.subdiv( sp, flatness) + pen = False + for csp in sp: + ctrl_pt1 = csp[0] + ctrl_pt2 = csp[1] + end_pt = csp[2] + yield end_pt[0], end_pt[1], pen + if not pen: pen = True