code refactoring - more cleanup

Sat, 07 Nov 2015 20:31:30 +0100

author
mbayer
date
Sat, 07 Nov 2015 20:31:30 +0100
changeset 9
89d724cfd8c3
parent 8
86f90bddac0f
child 10
92835c3f171a

code refactoring - more cleanup

svg2gcode/svg2gcode.py file | annotate | diff | comparison | revisions
--- a/svg2gcode/svg2gcode.py	Sat Nov 07 19:30:27 2015 +0100
+++ b/svg2gcode/svg2gcode.py	Sat Nov 07 20:31:30 2015 +0100
@@ -74,87 +74,105 @@
         kv[obj.name] = obj.value[0].value
     return kv
 
-
-def svg2gcode(options, gcode):
+class Image(object):
+    def __init__(self, filename, options, gcoder):
+        self.gcoder = gcoder
+        self.options = options
+        self.svg = svg.parse(filename)
+        self.bb1, self.bb2 = self.svg.bbox()
+        self.width, self.height = self.bb2.coord()
+        self.infill = None
 
-    def normalize(coord):
-        x = coord[0]
-        y = coord[1]
-        # flip y
-        y = (b2.coord()[1] - y)
-        return (x, y)
+        self._check_dimensions()
+        self._generate_infill()
+
+    def _check_dimensions(self):
+        msg = "Original dimension: %.2f x %.2f" % (self.width, self.height)
+        print msg
+        self.gcoder.comment(msg)
+        width = self.width * self.gcoder.mm_pixel * self.options.scale
+        height = self.height * self.gcoder.mm_pixel * self.options.scale
+        msg = "Print dimension: %.2fmm x %.2fmm" % (width, height)
+        print msg
+        self.gcoder.comment(msg)
 
-    im = svg.parse(options.filename)
-    b1, b2 = im.bbox()
-    width, height = b2.coord()
-    msg = "Original dimension: %.2f x %.2f" % (width, height)
-    print msg
-    gcode.comment(msg)
-    width *= gcode.mm_pixel * options.scale
-    height *= gcode.mm_pixel * options.scale
-    msg = "Print dimension: %.2fmm x %.2fmm" % (width, height)
-    print msg
-    gcode.comment(msg)
+    def _generate_infill(self):
+        b1x, b1y = self.bb1.coord()
+        b2x, b2y = self.bb2.coord()
+        page = box(b1x, b1y, b2x, b2y)
+        # TODO: Infill spacing needs to be calculated with proper scaling and gcode MM dimensions
+        # TODO: Make infill angle 0, 45 or 90 degrees configurable to options parser (0° = X, 90° = Y, 45° = X and Y but half the speed/accel needed!)
+        self.infill = hatchbox(page, 0, 2)
 
-    x1, y1 = b1.coord()
-    x2, y2 = b2.coord()
-    page = box(x1, y1, x2, y2)
-    # TODO: Infill spacing needs to be calculated with proper scaling and gcode MM dimensions
-    # TODO: Make infill angle 0, 45 or 90 degrees configurable to options parser (0° = X, 90° = Y, 45° = X and Y but half the speed/accel needed!)
-    INFILL = hatchbox(page, 0, 2)
+    def normalize(self, coord):
+        c_x = coord[0]
+        c_y = coord[1]
+        # flip y
+        c_y = (self.height - c_y)
+        return (c_x, c_y)
 
-    data = im.flatten()
-    for d in data:
-        if hasattr(d, "segments"):
-            for l in d.segments(1):
-                # THE OUTLINE
-                x, y = normalize(l[0].coord())
-                gcode.move(x, y)
-                for pt in l[1:]:
-                    x, y = normalize(pt.coord())
-                    gcode.engrave(x, y)
+    def get_drawings(self):
+        """
+        Returns a list of all svg drawings with segments attribute
+        """
+        data = []
+        for dwg in self.svg.flatten():
+            if hasattr(dwg, "segments"):
+                data.append(dwg)
+        return data
+
+def svg2gcode(options, gcoder):
+    image = Image(options.filename, options, gcoder)
 
-                if options.outline:
-                    continue
+    for dwg in image.get_drawings():
+        for l in dwg.segments(1):
+            # THE OUTLINE
+            coord = image.normalize(l[0].coord())
+            gcoder.move(coord[0], coord[1])
+            for pt in l[1:]:
+                coord = image.normalize(pt.coord())
+                gcoder.engrave(coord[0], coord[1])
 
-            if isinstance(d, svg.Polygon) or isinstance(d, svg.Path):
-                #check if we should infill?
-                style = parse_style(d.style)
-                if not style:
-                    continue
-                if not 'fill' in style.keys():
-                    continue
-                if style['fill'] == 'none':
-                    continue
+            if options.outline:
+                continue
+
+        if isinstance(dwg, svg.Polygon) or isinstance(dwg, svg.Path):
+            #check if we should infill?
+            style = parse_style(dwg.style)
+            if not style:
+                continue
+            if not 'fill' in style.keys():
+                continue
+            if style['fill'] == 'none':
+                continue
 
-                # try to generate the infill poly complex
-                poly = None
-                for l in d.segments(1):
-                    segments = []
-                    for pnt in l:
-                        x, y = pnt.coord()
-                        segments.append((x, y))
-                    shape = Polygon(segments)
-                    if shape.is_valid:
-                        if not poly:
-                            poly = shape
+            # try to generate the infill poly complex
+            poly = None
+            for l in dwg.segments(1):
+                segments = []
+                for pnt in l:
+                    segments.append(pnt.coord())
+                shape = Polygon(segments)
+                if shape.is_valid:
+                    if not poly:
+                        poly = shape
+                    else:
+                        if shape.within(poly):
+                            poly = poly.difference(shape)
                         else:
-                            if shape.within(poly):
-                                poly = poly.difference(shape)
-                            else:
-                                poly = poly.union(shape)
+                            poly = poly.union(shape)
 
-                lines = poly.intersection(INFILL)
-                if lines:
-                    # THE INFILL
-                    for line in lines:
-                        # TODO: swap start/end to nearest move!
-                        start = normalize((line.coords[0][0], line.coords[0][1]))
-                        end = normalize((line.coords[1][0], line.coords[1][1]))
-                        gcode.move(start[0], start[1])
-                        gcode.engrave(end[0], end[1])
+            lines = poly.intersection(image.infill)
+            if lines:
+                # THE INFILL
+                for line in lines:
+                    # TODO: swap start/end to nearest move!
+                    start = image.normalize((line.coords[0][0], line.coords[0][1]))
+                    end = image.normalize((line.coords[1][0], line.coords[1][1]))
+                    gcoder.move(start[0], start[1])
+                    gcoder.engrave(end[0], end[1])
 
-if __name__ == "__main__":
+def init_options():
     parser = OptionParser()
     parser.add_option("-f", "--file", dest="filename", default=None,
                       help="Load SVG file", metavar="FILE")
@@ -170,18 +188,19 @@
     parser.add_option("-o", "--outline", action="store_true",
                       dest="outline", default=False,
                       help="no infill, only outlines")
+    return parser.parse_args()
 
-    (options, args) = parser.parse_args()
-
-    if not options.filename:
+if __name__ == "__main__":
+    (OPTIONS, ARGS) = init_options()
+    if not OPTIONS.filename:
         print "no filename given!"
         sys.exit(1)
 
     # initialize gcode worker
-    gcode = Gcode(scale=options.scale, travel_speed=options.travel_speed, engrave_speed=options.engrave_speed)
+    GCODER = Gcode(scale=OPTIONS.scale, travel_speed=OPTIONS.travel_speed, engrave_speed=OPTIONS.engrave_speed)
 
     # processing
-    svg2gcode(options, gcode)
+    svg2gcode(OPTIONS, GCODER)
 
     # write gcode file
-    gcode.write(options.filename + ".g")
+    GCODER.write(OPTIONS.filename + ".g")

mercurial