From: daid Date: Fri, 18 Oct 2013 08:06:25 +0000 (+0200) Subject: Updates to the SVG class (still unused), fixed some minor things. X-Git-Tag: 13.11.2~48 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=e84bb7d834a89bdb362167099b95d90d51285484;p=cura.git Updates to the SVG class (still unused), fixed some minor things. --- diff --git a/Cura/gui/sceneView.py b/Cura/gui/sceneView.py index ead30869..d9956f4e 100644 --- a/Cura/gui/sceneView.py +++ b/Cura/gui/sceneView.py @@ -565,7 +565,7 @@ class SceneView(openglGui.glGuiPanel): self.updateProfileToControls() self.updateToolButtons() if zoom and obj is not None: - newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getMaximum()[2] / 2]) + newViewPos = numpy.array([obj.getPosition()[0], obj.getPosition()[1], obj.getSize()[2] / 2]) self._animView = openglGui.animation(self, self._viewTarget.copy(), newViewPos, 0.5) newZoom = obj.getBoundaryCircle() * 6 if newZoom > numpy.max(self._machineSize) * 3: @@ -897,7 +897,7 @@ void main(void) gl_FragColor = vec4(gl_Color.xyz * light_amount, 1.0-intensity); } """) - if self._objectShader == None or not self._objectShader.isValid(): + if self._objectShader is None or not self._objectShader.isValid(): self._objectShader = opengl.GLFakeShader() self._objectOverhangShader = opengl.GLFakeShader() self._objectLoadShader = None diff --git a/Cura/util/drawingLoader/drawing.py b/Cura/util/drawingLoader/drawing.py index 66dedf58..509aeffa 100644 --- a/Cura/util/drawingLoader/drawing.py +++ b/Cura/util/drawingLoader/drawing.py @@ -4,66 +4,28 @@ __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AG import math import numpy -class Drawing(object): - def __init__(self): - self.paths = [] - - def addPath(self, x, y, matrix=numpy.matrix(numpy.identity(3, numpy.float64))): - p = Path(x, y, matrix) - self.paths.append(p) - return p - - def _postProcessPaths(self): - for path in self.paths: - if not path.isClosed(): - if abs(self._nodes[-1]['p'] - self._startPoint) < 0.001: - self._isClosed = True - - def saveAsHtml(self, filename): - f = open(filename, "w") - - posMax = complex(-1000, -1000) - posMin = complex( 1000, 1000) - for path in self.paths: - points = path.getPoints() - for p in points: - if p.real > posMax.real: - posMax = complex(p.real, posMax.imag) - if p.imag > posMax.imag: - posMax = complex(posMax.real, p.imag) - if p.real < posMin.real: - posMin = complex(p.real, posMin.imag) - if p.imag < posMin.imag: - posMin = complex(posMin.real, p.imag) +class Node(object): + LINE = 0 + ARC = 1 + CURVE = 2 - f.write("\n") - f.write("\n" % ((posMax - posMin).real, (posMax - posMin).imag)) - f.write("\n") - f.write("") - f.write("\n") + def __init__(self, type, position): + self.type = type + self.position = position - f.write("\n") - f.write("") - f.write("\n") +class LineNode(Node): + def __init__(self, position): + super(LineNode, self).__init__(Node.LINE, position) - f.write("\n") - f.write("") - f.close() +class ArcNode(Node): + def __init__(self, position, rotation, radius, large, sweep): + super(ArcNode, self).__init__(Node.ARC, position) + self.rotation = rotation + self.radius = radius + self.large = large + self.sweep = sweep class Path(object): - LINE = 0 - ARC = 1 - CURVE = 2 - def __init__(self, x, y, matrix=numpy.matrix(numpy.identity(3, numpy.float64))): self._matrix = matrix self._relMatrix = numpy.matrix([[matrix[0,0],matrix[1,0]],[matrix[0,1],matrix[1,1]]], numpy.float64) @@ -72,89 +34,97 @@ class Path(object): self._isClosed = False def addLineTo(self, x, y): - self._nodes.append({'type': Path.LINE, 'p': self._m(complex(x, y))}) - - def addArcTo(self, x, y, rot, rx, ry, large, sweep): - self._nodes.append({ - 'type': Path.ARC, - 'p': self._m(complex(x, y)), - 'rot': rot, - 'radius': self._r(complex(rx, ry)), - 'large': large, - 'sweep': sweep - }) + self._nodes.append(LineNode(self._m(complex(x, y)))) + + def addArcTo(self, x, y, rotation, rx, ry, large, sweep): + self._nodes.append(ArcNode(self._m(complex(x, y)), rotation, self._r(complex(rx, ry)), large, sweep)) def addCurveTo(self, x, y, cp1x, cp1y, cp2x, cp2y): - self._nodes.append({ - 'type': Path.CURVE, - 'p': self._m(complex(x, y)), - 'cp1': self._m(complex(cp1x, cp1y)), - 'cp2': self._m(complex(cp2x, cp2y)) - }) + node = Node(Node.CURVE, self._m(complex(x, y))) + node.cp1 = self._m(complex(cp1x, cp1y)) + node.cp2 = self._m(complex(cp2x, cp2y)) + self._nodes.append(node) def isClosed(self): return self._isClosed def closePath(self): - self._nodes.append({'type': Path.LINE, 'p': self._startPoint}) + if abs(self._nodes[-1].position - self._startPoint) > 0.01: + self._nodes.append(Node(Node.LINE, self._startPoint)) self._isClosed = True - def getPoints(self, accuracy = 1): - pointList = [self._startPoint] + def getArcInfo(self, node): + p1 = self._startPoint + if self._nodes[0] != node: + p1 = self._nodes[self._nodes.index(node) - 1].position + + p2 = node.position + rot = math.radians(node.rotation) + r = node.radius + + #http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter + diff = (p1 - p2) / 2 + p1alt = diff #TODO: apply rot + p2alt = -diff #TODO: apply rot + rx2 = r.real*r.real + ry2 = r.imag*r.imag + x1alt2 = p1alt.real*p1alt.real + y1alt2 = p1alt.imag*p1alt.imag + + f = x1alt2 / rx2 + y1alt2 / ry2 + if f >= 1.0: + r *= math.sqrt(f+0.000001) + rx2 = r.real*r.real + ry2 = r.imag*r.imag + + if rx2*y1alt2+ry2*x1alt2 == 0.0: + f = 0 + else: + f = math.sqrt((rx2*ry2 - rx2*y1alt2 - ry2*x1alt2) / (rx2*y1alt2+ry2*x1alt2)) + if node.large == node.sweep: + f = -f + cAlt = f * complex(r.real*p1alt.imag/r.imag, -r.imag*p1alt.real/r.real) + + c = cAlt + (p1 + p2) / 2 #TODO: apply rot + + a1 = math.atan2((p1alt.imag - cAlt.imag) / r.imag, (p1alt.real - cAlt.real) / r.real) + a2 = math.atan2((p2alt.imag - cAlt.imag) / r.imag, (p2alt.real - cAlt.real) / r.real) + + large = abs(a2 - a1) > math.pi + if large != node.large: + if a1 < a2: + a1 += math.pi * 2 + else: + a2 += math.pi * 2 + + return c, a1, a2, r + + def getPoints(self, accuracy = 1.0): + pointList = [(self._startPoint, -1)] p1 = self._startPoint - for p in self._nodes: - if p['type'] == Path.LINE: - p1 = p['p'] - pointList.append(p1) - elif p['type'] == Path.ARC: - p2 = p['p'] - rot = math.radians(p['rot']) - r = p['radius'] - - #http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter - diff = (p1 - p2) / 2 - p1alt = diff #TODO: apply rot - p2alt = -diff #TODO: apply rot - rx2 = r.real*r.real - ry2 = r.imag*r.imag - x1alt2 = p1alt.real*p1alt.real - y1alt2 = p1alt.imag*p1alt.imag - - f = x1alt2 / rx2 + y1alt2 / ry2 - if f >= 1.0: - r *= math.sqrt(f+0.000001) - rx2 = r.real*r.real - ry2 = r.imag*r.imag - - f = math.sqrt((rx2*ry2 - rx2*y1alt2 - ry2*x1alt2) / (rx2*y1alt2+ry2*x1alt2)) - if p['large'] == p['sweep']: - f = -f - cAlt = f * complex(r.real*p1alt.imag/r.imag, -r.imag*p1alt.real/r.real) - - c = cAlt + (p1 + p2) / 2 #TODO: apply rot - - a1 = math.atan2((p1alt.imag - cAlt.imag) / r.imag, (p1alt.real - cAlt.real) / r.real) - a2 = math.atan2((p2alt.imag - cAlt.imag) / r.imag, (p2alt.real - cAlt.real) / r.real) - - large = abs(a2 - a1) > math.pi - if large != p['large']: - if a1 < a2: - a1 += math.pi * 2 - else: - a2 += math.pi * 2 + idx = -1 + for node in self._nodes: + idx += 1 + if node.type == Node.LINE: + p1 = node.position + pointList.append((p1, idx)) + elif node.type == Node.ARC: + p2 = node.position + c, a1, a2, r = self.getArcInfo(node) pCenter = c + complex(math.cos(a1 + 0.5*(a2-a1)) * r.real, math.sin(a1 + 0.5*(a2-a1)) * r.imag) dist = abs(pCenter - p1) + abs(pCenter - p2) segments = int(dist / accuracy) + 1 for n in xrange(1, segments): - pointList.append(c + complex(math.cos(a1 + n*(a2-a1)/segments) * r.real, math.sin(a1 + n*(a2-a1)/segments) * r.imag)) + p = c + complex(math.cos(a1 + n*(a2-a1)/segments) * r.real, math.sin(a1 + n*(a2-a1)/segments) * r.imag) + pointList.append((p, idx)) - pointList.append(p2) + pointList.append((p2, idx)) p1 = p2 - elif p['type'] == Path.CURVE: - p2 = p['p'] - cp1 = p['cp1'] - cp2 = p['cp2'] + elif node.type == Node.CURVE: + p2 = node.position + cp1 = node.cp1 + cp2 = node.cp2 pCenter = p1*0.5*0.5*0.5 + cp1*3.0*0.5*0.5*0.5 + cp2*3.0*0.5*0.5*0.5 + p2*0.5*0.5*0.5 dist = abs(pCenter - p1) + abs(pCenter - p2) @@ -163,10 +133,10 @@ class Path(object): f = n / float(segments) g = 1.0-f point = p1*g*g*g + cp1*3.0*g*g*f + cp2*3.0*g*f*f + p2*f*f*f - pointList.append(point) + pointList.append((point, idx)) - pointList.append(p2) - p1 = p['p'] + pointList.append((p2, idx)) + p1 = p2 return pointList @@ -174,22 +144,33 @@ class Path(object): def getSVGPath(self): p0 = self._startPoint ret = 'M %f %f ' % (p0.real, p0.imag) - for p in self._nodes: - if p['type'] == Path.LINE: - p0 = p['p'] + for node in self._nodes: + if node.type == Node.LINE: + p0 = node.position ret += 'L %f %f' % (p0.real, p0.imag) - elif p['type'] == Path.ARC: - p0 = p['p'] - radius = p['radius'] - ret += 'A %f %f 0 %d %d %f %f' % (radius.real, radius.imag, 1 if p['large'] else 0, 1 if p['sweep'] else 0, p0.real, p0.imag) - elif p['type'] == Path.CURVE: - p0 = p['p'] - cp1 = p['cp1'] - cp2 = p['cp2'] + elif node.type == Node.ARC: + p0 = node.position + radius = node.radius + ret += 'A %f %f 0 %d %d %f %f' % (radius.real, radius.imag, 1 if node.large else 0, 1 if node.sweep else 0, p0.real, p0.imag) + elif node.type == Node.CURVE: + p0 = node.position + cp1 = node.cp1 + cp2 = node.cp2 ret += 'C %f %f %f %f %f %f' % (cp1.real, cp1.imag, cp2.real, cp2.imag, p0.real, p0.imag) return ret + def getPathString(self): + ret = '%f %f' % (self._startPoint.real, self._startPoint.imag) + for node in self._nodes: + if node.type == Node.LINE: + ret += '|L %f %f' % (node.position.real, node.position.imag) + elif node.type == Node.ARC: + ret += '|A %f %f %f %f %d %d' % (node.position.real, node.position.imag, node.radius.real, node.radius.imag, 1 if node.large else 0, 1 if node.sweep else 0) + elif node.type == Node.CURVE: + ret += '|C %f %f %f %f %f %f' % (node.position.real, node.position.imag, node.cp1.real, node.cp1.imag, node.cp2.real, node.cp2.imag) + return ret + def _m(self, p): tmp = numpy.matrix([p.real, p.imag, 1], numpy.float64) * self._matrix return complex(tmp[0,0], tmp[0,1]) @@ -197,3 +178,83 @@ class Path(object): def _r(self, p): tmp = numpy.matrix([p.real, p.imag], numpy.float64) * self._relMatrix return complex(tmp[0,0], tmp[0,1]) + +class Drawing(object): + def __init__(self): + self.paths = [] + + def addPath(self, x, y, matrix=numpy.matrix(numpy.identity(3, numpy.float64))): + p = Path(x, y, matrix) + self.paths.append(p) + return p + + def _postProcessPaths(self): + for path in self.paths: + if not path.isClosed(): + if abs(path._nodes[-1].position - path._startPoint) < 0.001: + path._isClosed = True + if path.isClosed() and len(path._nodes) == 2 and path._nodes[0].type == Node.ARC and path._nodes[1].type == Node.ARC: + if abs(path._nodes[0].radius - path._nodes[1].radius) < 0.001: + pass + #path._nodes = [] + + def dumpToFile(self, file): + file.write("%d\n" % (len(self.paths))) + for path in self.paths: + file.write("%s\n" % (path.getPathString())) + + def readFromFile(self, file): + self.paths = [] + pathCount = int(file.readline()) + for n in xrange(0, pathCount): + line = map(str.split, file.readline().strip().split('|')) + path = Path(float(line[0][0]), float(line[0][1])) + for item in line[1:]: + if item[0] == 'L': + path.addLineTo(float(item[1]), float(item[2])) + elif item[0] == 'A': + path.addArcTo(float(item[1]), float(item[2]), 0, float(item[3]), float(item[4]), int(item[5]) != 0, int(item[6]) != 0) + elif item[0] == 'C': + path.addCurveTo(float(item[1]), float(item[2]), float(item[3]), float(item[4]), float(item[5]), float(item[6])) + self.paths.append(path) + self._postProcessPaths() + + def saveAsHtml(self, filename): + f = open(filename, "w") + + posMax = complex(-1000, -1000) + posMin = complex( 1000, 1000) + for path in self.paths: + points = path.getPoints() + for p in points: + if p.real > posMax.real: + posMax = complex(p.real, posMax.imag) + if p.imag > posMax.imag: + posMax = complex(posMax.real, p.imag) + if p.real < posMin.real: + posMin = complex(p.real, posMin.imag) + if p.imag < posMin.imag: + posMin = complex(posMin.real, p.imag) + + f.write("\n") + f.write("\n" % ((posMax - posMin).real, (posMax - posMin).imag)) + f.write("\n") + f.write("") + f.write("\n") + + f.write("\n") + f.write("") + f.write("\n") + + f.write("\n") + f.write("") + f.close() diff --git a/Cura/util/mesh.py b/Cura/util/mesh.py index eacc7076..c4594dbd 100644 --- a/Cura/util/mesh.py +++ b/Cura/util/mesh.py @@ -31,7 +31,7 @@ class printableObject(object): ret = printableObject(self._originFilename) ret._matrix = self._matrix.copy() ret._transformedMin = self._transformedMin.copy() - ret._transformedMax = self._transformedMin.copy() + ret._transformedMax = self._transformedMax.copy() ret._transformedSize = self._transformedSize.copy() ret._boundaryCircleSize = self._boundaryCircleSize ret._drawOffset = self._drawOffset.copy()