1 from __future__ import absolute_import
4 from xml.etree import ElementTree
11 width = float(e.get('width'))
12 height = float(e.get('height'))
13 return [[complex(x, -y), complex(x+width, -y), complex(x+width, -(y+height)), complex(x, -(y+height)), complex(x, -y)]]
16 d = e.get('d').replace(',', ' ')
24 if c in "-+.0123456789e":
28 param.append(float(num))
30 if c in "MmZzLlHhVvCcSsQqTtAa#":
32 p = complex(param[0], -param[1])
39 p = complex(param[i], -param[i+1])
43 p += complex(param[0], -param[1])
50 p += complex(param[i], -param[i+1])
59 p = complex(param[i], -param[i+1])
68 p += complex(param[i], -param[i+1])
78 addCurve(curPath, p, complex(param[i], -param[i+1]), complex(param[i+2], -param[i+3]), complex(param[i+4], -param[i+5]))
79 p = complex(param[i+4], -param[i+5])
88 addCurve(curPath, p, p + complex(param[i], -param[i+1]), p + complex(param[i+2], -param[i+3]), p + complex(param[i+4], -param[i+5]))
89 p += complex(param[i+4], -param[i+5])
99 endPoint = p + complex(param[i+5], -param[i+6])
100 addArc(curPath, p, endPoint, complex(param[i], param[i+1]), param[i+2], param[i+3], param[i+4])
104 elif cmd == 'Z' or cmd == 'z':
105 curPath.append(curPath[0])
112 def interpolate(p0, p1, f):
113 return complex(p0.real + (p1.real - p0.real) * f, p0.imag + (p1.imag - p0.imag) * f)
115 def addCurve(path, p0, q0, q1, p1):
117 for n in xrange(0, 100):
119 r0 = interpolate(p0, q0, k);
120 r1 = interpolate(q0, q1, k);
121 r2 = interpolate(q1, p1, k);
122 b0 = interpolate(r0, r1, k);
123 b1 = interpolate(r1, r2, k);
124 s = interpolate(b0, b1, k);
125 if abs(s - oldPoint) > 1.0:
129 def addArc(path, begin, end, radius, xAxisRotation, largeArcFlag, sweepFlag):
130 xAxisRotationComplex = complex(math.cos(math.radians(xAxisRotation)), math.sin(math.radians(xAxisRotation)))
131 reverseXAxisRotationComplex = complex(xAxisRotationComplex.real, -xAxisRotationComplex.imag)
132 beginRotated = begin * reverseXAxisRotationComplex
133 endRotated = end * reverseXAxisRotationComplex
134 beginTransformed = complex(beginRotated.real / radius.real, beginRotated.imag / radius.imag)
135 endTransformed = complex(endRotated.real / radius.real, endRotated.imag / radius.imag)
136 midpointTransformed = 0.5 * (beginTransformed + endTransformed)
137 midMinusBeginTransformed = midpointTransformed - beginTransformed
138 midMinusBeginTransformedLength = abs(midMinusBeginTransformed)
140 if midMinusBeginTransformedLength > 1.0:
141 radius *= midMinusBeginTransformedLength
142 beginTransformed /= midMinusBeginTransformedLength
143 endTransformed /= midMinusBeginTransformedLength
144 midpointTransformed /= midMinusBeginTransformedLength
145 midMinusBeginTransformed /= midMinusBeginTransformedLength
146 midMinusBeginTransformedLength = 1.0
147 midWiddershinsTransformed = complex(-midMinusBeginTransformed.imag, midMinusBeginTransformed.real)
148 midWiddershinsLengthSquared = 1.0 - midMinusBeginTransformedLength * midMinusBeginTransformedLength
149 if midWiddershinsLengthSquared < 0.0:
150 midWiddershinsLengthSquared = 0.0
151 midWiddershinsLength = math.sqrt(midWiddershinsLengthSquared)
152 midWiddershinsTransformed *= midWiddershinsLength / abs(midWiddershinsTransformed)
153 centerTransformed = midpointTransformed
154 if largeArcFlag == sweepFlag:
155 centerTransformed -= midWiddershinsTransformed
157 centerTransformed += midWiddershinsTransformed
158 beginMinusCenterTransformed = beginTransformed - centerTransformed
159 beginMinusCenterTransformedLength = abs(beginMinusCenterTransformed)
160 if beginMinusCenterTransformedLength <= 0.0:
162 beginAngle = math.atan2(beginMinusCenterTransformed.imag, beginMinusCenterTransformed.real)
163 endMinusCenterTransformed = endTransformed - centerTransformed
164 angleDifference = getAngleDifferenceByComplex(endMinusCenterTransformed, beginMinusCenterTransformed)
166 if angleDifference < 0.0:
167 angleDifference += 2.0 * math.pi
169 if angleDifference > 0.0:
170 angleDifference -= 2.0 * math.pi
172 center = complex(centerTransformed.real * radius.real, centerTransformed.imag * radius.imag) * xAxisRotationComplex
173 for side in xrange(1, 32):
174 a = beginAngle + float(side) * math.pi * 2 / 32
175 circumferential = complex(math.cos(a) * radius.real, math.sin(a) * radius.imag) * beginMinusCenterTransformedLength
176 point = center + circumferential * xAxisRotationComplex
179 def getAngleDifferenceByComplex( subtractFromComplex, subtractComplex ):
180 subtractComplexMirror = complex( subtractComplex.real , - subtractComplex.imag )
181 differenceComplex = subtractComplexMirror * subtractFromComplex
182 return math.atan2( differenceComplex.imag, differenceComplex.real )
185 def movePath(p, offset):
186 return map(lambda _p: _p - offset, p)
189 def __init__(self, filename):
191 tagProcess['rect'] = processRect
192 tagProcess['path'] = processPath
195 for e in ElementTree.parse(open(filename, "r")).getiterator():
196 tag = e.tag[e.tag.find('}')+1:]
197 if not tag in tagProcess:
198 #print 'unknown tag: %s' % (tag)
200 self.paths.extend(tagProcess[tag](e))
202 def center(self, centerPoint):
203 offset = complex(0, 0)
205 for path in self.paths:
210 offset -= centerPoint
212 self.paths = [movePath(p, offset) for p in self.paths]
214 if __name__ == '__main__':
215 svg = SVG("../logo.svg")
216 f = open("../../test_export.gcode", "w")
218 f.write(';TYPE:CUSTOM\n')
219 f.write(profile.getAlterationFileContents('start.gcode'))
220 svg.center(complex(profile.getPreferenceFloat('machine_width') / 2, profile.getPreferenceFloat('machine_depth') / 2))
223 filamentRadius = profile.getProfileSettingFloat('filament_diameter') / 2
224 filamentArea = math.pi * filamentRadius * filamentRadius
225 lineWidth = profile.getProfileSettingFloat('nozzle_size') * 2
230 for n in xrange(0, 20):
231 f.write("G1 Z%f F%f\n" % (z, profile.getProfileSettingFloat('max_z_speed')*60))
232 for path in svg.paths:
234 extrusionMMperDist = lineWidth * layerThickness / filamentArea
235 f.write("G1 X%f Y%f F%f\n" % (oldPoint.real, oldPoint.imag, profile.getProfileSettingFloat('travel_speed')*60))
236 f.write("G1 F%f\n" % (profile.getProfileSettingFloat('print_speed')*60))
237 for point in path[1:]:
238 dist = abs(oldPoint - point)
239 e += dist * extrusionMMperDist
240 f.write("G1 X%f Y%f E%f\n" % (point.real, point.imag, e))
243 f.write(profile.getAlterationFileContents('end.gcode'))