chiark / gitweb /
Use socket to communicate polygon data, so it can be done in binary. This also remove...
authordaid <daid303@gmail.com>
Tue, 28 Jan 2014 16:46:32 +0000 (17:46 +0100)
committerdaid <daid303@gmail.com>
Tue, 28 Jan 2014 16:46:32 +0000 (17:46 +0100)
Cura/gui/util/engineResultView.py
Cura/util/sliceEngine.py

index 757af7db5257825d04bc761d23b2c3502852952a..e662ec138683300b5e3e68c212ef8a675e274daf 100644 (file)
@@ -65,11 +65,11 @@ class engineResultView(object):
                lineTypeList = [
                        ('inset0',     'WALL-OUTER', [1,0,0,1]),
                        ('insetx',     'WALL-INNER', [0,1,0,1]),
-                       ('openoutline', None, [1,0,0,1]),
-                       ('skin',       'FILL', [1,1,0,1]),
-                       ('infill',      None, [1,1,0,1]),
-                       ('support',    'SUPPORT',[0,1,1,1]),
-                       ('outline',     None, [0,0,0,1])
+                       ('openoutline', None,        [1,0,0,1]),
+                       ('skin',       'FILL',       [1,1,0,1]),
+                       ('infill',      None,        [1,1,0,1]),
+                       ('support',    'SUPPORT',    [0,1,1,1]),
+                       ('outline',     None,        [0,0,0,1])
                ]
                n = 0
                gcodeLayers = self._result.getGCodeLayers()
@@ -96,10 +96,10 @@ class engineResultView(object):
                                                        layerVBOs[typeName].render()
                                n += 20
                        else:
-                               while len(self._layerVBOs) < n + 1:
-                                       self._layerVBOs.append({})
                                c = 1.0 - ((layerNr - n) - 1) * 0.05
                                c = max(0.5, c)
+                               while len(self._layerVBOs) < n + 1:
+                                       self._layerVBOs.append({})
                                layerVBOs = self._layerVBOs[n]
                                if gcodeLayers is not None and layerNr - 10 < n < len(gcodeLayers):
                                        for _, typeName, color in lineTypeList:
index 3b224cfdfdd837f4fbf196fd79149f21b3cc0e6c..ae7a5be3ec8f9d1f0b9eb7e6930af72c39cf776a 100644 (file)
@@ -12,6 +12,8 @@ import sys
 import urllib
 import urllib2
 import hashlib
+import socket
+import struct
 import cStringIO as StringIO
 
 from Cura.util import profile
@@ -136,21 +138,92 @@ class EngineResult(object):
                        pass
 
 class Engine(object):
+       GUI_CMD_REQUEST_MESH = 0x01
+       GUI_CMD_SEND_POLYGONS = 0x02
+
        def __init__(self, progressCallback):
                self._process = None
                self._thread = None
                self._callback = progressCallback
-               self._binaryStorageFilename = getTempFilename()
                self._progressSteps = ['inset', 'skin', 'export']
                self._objCount = 0
                self._result = None
 
+               self._serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+               self._serverPortNr = 0xC20A
+               while True:
+                       try:
+                               self._serversocket.bind(('127.0.0.1', self._serverPortNr))
+                       except:
+                               print "Failed to listen on port: %d" % (self._serverPortNr)
+                               self._serverPortNr += 1
+                               if self._serverPortNr > 0xFFFF:
+                                       print "Failed to listen on any port..."
+                                       break
+                       else:
+                               break
+               print 'Listening for engine communications on %d' % (self._serverPortNr)
+               self._serversocket.listen(1)
+               thread = threading.Thread(target=self._socketListenThread)
+               thread.daemon = True
+               thread.start()
+
+       def _socketListenThread(self):
+               while True:
+                       sock, _ = self._serversocket.accept()
+                       thread = threading.Thread(target=self._socketConnectionThread, args=(sock,))
+                       thread.daemon = True
+                       thread.start()
+
+       def _socketConnectionThread(self, sock):
+               print "Connection", sock
+               while True:
+                       try:
+                               data = sock.recv(4)
+                       except:
+                               data = ''
+                       if len(data) == 0:
+                               print "Connection closed"
+                               sock.close()
+                               return
+                       cmd = struct.unpack('@i', data)[0]
+                       if cmd == self.GUI_CMD_REQUEST_MESH:
+                               meshInfo = self._modelData[0]
+                               self._modelData = self._modelData[1:]
+                               sock.sendall(struct.pack('@i', meshInfo[0]))
+                               sock.sendall(meshInfo[1].tostring())
+                       elif cmd == self.GUI_CMD_SEND_POLYGONS:
+                               cnt = struct.unpack('@i', sock.recv(4))[0]
+                               layerNr = struct.unpack('@i', sock.recv(4))[0]
+                               z = struct.unpack('@i', sock.recv(4))[0]
+                               z = float(z) / 1000.0
+                               typeNameLen = struct.unpack('@i', sock.recv(4))[0]
+                               typeName = sock.recv(typeNameLen)
+                               while len(self._result._polygons) < layerNr + 1:
+                                       self._result._polygons.append({})
+                               polygons = self._result._polygons[layerNr]
+                               if typeName not in polygons:
+                                       polygons[typeName] = []
+                               for n in xrange(0, cnt):
+                                       length = struct.unpack('@i', sock.recv(4))[0]
+                                       data = ''
+                                       while len(data) < length * 8 * 2:
+                                               recvData = sock.recv(length * 8 * 2 - len(data))
+                                               if len(recvData) < 1:
+                                                       return
+                                               data += recvData
+                                       polygon2d = numpy.array(numpy.fromstring(data, numpy.int64), numpy.float32) / 1000.0
+                                       polygon2d = polygon2d.reshape((len(polygon2d) / 2, 2))
+                                       polygon = numpy.empty((len(polygon2d), 3), numpy.float32)
+                                       polygon[:,:-1] = polygon2d
+                                       polygon[:,2] = z
+                                       polygons[typeName].append(polygon)
+                       else:
+                               print "Unknown command on socket: %x" % (cmd)
+
        def cleanup(self):
                self.abortEngine()
-               try:
-                       os.remove(self._binaryStorageFilename)
-               except:
-                       pass
+               self._serversocket.close()
 
        def abortEngine(self):
                if self._process is not None:
@@ -182,69 +255,69 @@ class Engine(object):
                commandList = [getEngineFilename(), '-vvv']
                for k, v in self._engineSettings(extruderCount).iteritems():
                        commandList += ['-s', '%s=%s' % (k, str(v))]
-               commandList += ['-b', self._binaryStorageFilename]
+               commandList += ['-g', '%d' % self._serverPortNr]
                self._objCount = 0
-               with open(self._binaryStorageFilename, "wb") as f:
-                       hash = hashlib.sha512()
-                       order = scene.printOrder()
-                       if order is None:
-                               pos = numpy.array(profile.getMachineCenterCoords()) * 1000
-                               objMin = None
-                               objMax = None
+               engineModelData = []
+               hash = hashlib.sha512()
+               order = scene.printOrder()
+               if order is None:
+                       pos = numpy.array(profile.getMachineCenterCoords()) * 1000
+                       objMin = None
+                       objMax = None
+                       for obj in scene.objects():
+                               if scene.checkPlatform(obj):
+                                       oMin = obj.getMinimum()[0:2] + obj.getPosition()
+                                       oMax = obj.getMaximum()[0:2] + obj.getPosition()
+                                       if objMin is None:
+                                               objMin = oMin
+                                               objMax = oMax
+                                       else:
+                                               objMin[0] = min(oMin[0], objMin[0])
+                                               objMin[1] = min(oMin[1], objMin[1])
+                                               objMax[0] = max(oMax[0], objMax[0])
+                                               objMax[1] = max(oMax[1], objMax[1])
+                       if objMin is None:
+                               return
+                       pos += (objMin + objMax) / 2.0 * 1000
+                       commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
+
+                       vertexTotal = [0] * 4
+                       meshMax = 1
+                       for obj in scene.objects():
+                               if scene.checkPlatform(obj):
+                                       meshMax = max(meshMax, len(obj._meshList))
+                                       for n in xrange(0, len(obj._meshList)):
+                                               vertexTotal[n] += obj._meshList[n].vertexCount
+
+                       for n in xrange(0, meshMax):
+                               verts = numpy.zeros((0, 3), numpy.float32)
                                for obj in scene.objects():
                                        if scene.checkPlatform(obj):
-                                               oMin = obj.getMinimum()[0:2] + obj.getPosition()
-                                               oMax = obj.getMaximum()[0:2] + obj.getPosition()
-                                               if objMin is None:
-                                                       objMin = oMin
-                                                       objMax = oMax
-                                               else:
-                                                       objMin[0] = min(oMin[0], objMin[0])
-                                                       objMin[1] = min(oMin[1], objMin[1])
-                                                       objMax[0] = max(oMax[0], objMax[0])
-                                                       objMax[1] = max(oMax[1], objMax[1])
-                               if objMin is None:
-                                       return
-                               pos += (objMin + objMax) / 2.0 * 1000
+                                               if n < len(obj._meshList):
+                                                       vertexes = (numpy.matrix(obj._meshList[n].vertexes, copy = False) * numpy.matrix(obj._matrix, numpy.float32)).getA()
+                                                       vertexes -= obj._drawOffset
+                                                       vertexes += numpy.array([obj.getPosition()[0], obj.getPosition()[1], 0.0])
+                                                       verts = numpy.concatenate((verts, vertexes))
+                                                       hash.update(obj._meshList[n].vertexes.tostring())
+                               engineModelData.append((vertexTotal[n], verts))
+
+                       commandList += ['$' * meshMax]
+                       self._objCount = 1
+               else:
+                       for n in order:
+                               obj = scene.objects()[n]
+                               for mesh in obj._meshList:
+                                       engineModelData.append((mesh.vertexCount, mesh.vertexes))
+                                       hash.update(mesh.vertexes.tostring())
+                               pos = obj.getPosition() * 1000
+                               pos += numpy.array(profile.getMachineCenterCoords()) * 1000
+                               commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))]
                                commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
-
-                               vertexTotal = [0] * 4
-                               meshMax = 1
-                               for obj in scene.objects():
-                                       if scene.checkPlatform(obj):
-                                               meshMax = max(meshMax, len(obj._meshList))
-                                               for n in xrange(0, len(obj._meshList)):
-                                                       vertexTotal[n] += obj._meshList[n].vertexCount
-
-                               for n in xrange(0, meshMax):
-                                       f.write(numpy.array([vertexTotal[n]], numpy.int32).tostring())
-                                       for obj in scene.objects():
-                                               if scene.checkPlatform(obj):
-                                                       if n < len(obj._meshList):
-                                                               vertexes = (numpy.matrix(obj._meshList[n].vertexes, copy = False) * numpy.matrix(obj._matrix, numpy.float32)).getA()
-                                                               vertexes -= obj._drawOffset
-                                                               vertexes += numpy.array([obj.getPosition()[0], obj.getPosition()[1], 0.0])
-                                                               f.write(vertexes.tostring())
-                                                               hash.update(obj._meshList[n].vertexes.tostring())
-
-                               commandList += ['#' * meshMax]
-                               self._objCount = 1
-                       else:
-                               for n in order:
-                                       obj = scene.objects()[n]
-                                       for mesh in obj._meshList:
-                                               f.write(numpy.array([mesh.vertexCount], numpy.int32).tostring())
-                                               s = mesh.vertexes.tostring()
-                                               f.write(s)
-                                               hash.update(s)
-                                       pos = obj.getPosition() * 1000
-                                       pos += numpy.array(profile.getMachineCenterCoords()) * 1000
-                                       commandList += ['-m', ','.join(map(str, obj._matrix.getA().flatten()))]
-                                       commandList += ['-s', 'posx=%d' % int(pos[0]), '-s', 'posy=%d' % int(pos[1])]
-                                       commandList += ['#' * len(obj._meshList)]
-                                       self._objCount += 1
-                       modelHash = hash.hexdigest()
+                               commandList += ['$' * len(obj._meshList)]
+                               self._objCount += 1
+               modelHash = hash.hexdigest()
                if self._objCount > 0:
+                       self._modelData = engineModelData
                        self._thread = threading.Thread(target=self._watchProcess, args=(commandList, self._thread, modelHash))
                        self._thread.daemon = True
                        self._thread.start()
@@ -319,27 +392,6 @@ class Engine(object):
                                                self._callback(progressValue)
                                        except:
                                                pass
-                       elif line.startswith('Polygons:'):
-                               line = line.split(':')
-                               typeName = line[1]
-                               layerNr = int(line[2])
-                               size = int(line[3])
-                               z = float(line[4])
-                               while len(self._result._polygons) < layerNr + 1:
-                                       self._result._polygons.append({})
-                               polygons = self._result._polygons[layerNr]
-                               for n in xrange(0, size):
-                                       polygon = stderr.readline().strip()
-                                       if not polygon:
-                                               continue
-                                       polygon2d = numpy.fromstring(polygon, dtype=numpy.float32, sep=' ')
-                                       polygon2d = polygon2d.reshape((len(polygon2d) / 2, 2))
-                                       polygon = numpy.empty((len(polygon2d), 3), numpy.float32)
-                                       polygon[:,:-1] = polygon2d
-                                       polygon[:,2] = z
-                                       if typeName not in polygons:
-                                               polygons[typeName] = []
-                                       polygons[typeName].append(polygon)
                        elif line.startswith('Print time:'):
                                self._result._printTimeSeconds = int(line.split(':')[1].strip())
                        elif line.startswith('Filament:'):
@@ -449,7 +501,7 @@ class Engine(object):
                        settings['gcodeFlavor'] = 1
                if profile.getProfileSetting('spiralize') == 'True':
                        settings['spiralizeMode'] = 1
-               if profile.getProfileSetting('wipe_tower') == 'True':
+               if profile.getProfileSetting('wipe_tower') == 'True' and extruderCount > 1:
                        settings['wipeTowerSize'] = int(math.sqrt(profile.getProfileSettingFloat('wipe_tower_volume') * 1000 * 1000 * 1000 / settings['layerThickness']))
                if profile.getProfileSetting('ooze_shield') == 'True':
                        settings['enableOozeShield'] = 1