chiark / gitweb /
Add object split function. Optimize printing order calculator for shorter runtime.
authordaid303 <daid303@gmail.com>
Tue, 16 Apr 2013 10:20:08 +0000 (12:20 +0200)
committerdaid303 <daid303@gmail.com>
Tue, 16 Apr 2013 10:20:08 +0000 (12:20 +0200)
Cura/gui/sceneView.py
Cura/util/mesh.py
Cura/util/objectScene.py
Cura/util/sliceEngine.py

index b8c882a0cf21f1a01d6fbaa8f4c9552581f7ba10..c9394c79b74d294205f216b28a4d0a3e02ec792f 100644 (file)
@@ -231,6 +231,16 @@ class SceneView(openglGui.glGuiPanel):
                self._scene.centerAll()
                self.sceneUpdated()
 
+       def OnSplitObject(self, e):
+               if self._selectedObj is None:
+                       return
+               self._scene.remove(self._selectedObj)
+               for obj in self._selectedObj.split():
+                       self._scene.add(obj)
+               self._scene.centerAll()
+               self._selectObject(None)
+               self.sceneUpdated()
+
        def OnMergeObjects(self, e):
                if self._selectedObj is None or self._focusObj is None or self._selectedObj == self._focusObj:
                        return
@@ -363,8 +373,9 @@ class SceneView(openglGui.glGuiPanel):
                                        self.Bind(wx.EVT_MENU, lambda e: self._deleteObject(self._selectedObj), menu.Append(-1, 'Delete'))
                                        if self._selectedObj == self._focusObj:
                                                self.Bind(wx.EVT_MENU, self.OnDuplicateObject, menu.Append(-1, 'Duplicate'))
+                                               self.Bind(wx.EVT_MENU, self.OnSplitObject, menu.Append(-1, 'Split'))
                                        if self._selectedObj != self._focusObj and self._focusObj is not None:
-                                               self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Merge'))
+                                               self.Bind(wx.EVT_MENU, self.OnMergeObjects, menu.Append(-1, 'Dual extrusion merge'))
                                        if menu.MenuItemCount > 0:
                                                self.PopupMenu(menu)
                                        menu.Destroy()
index a82f8336ed4ee820c0f38c6a6c0f379684a82e7a..294954a1e433a245da5377d34be6cad0b9172005 100644 (file)
@@ -194,6 +194,16 @@ class printableObject(object):
                if scale > 0:
                        self.applyMatrix(numpy.matrix([[scale,0,0],[0,scale,0],[0,0,scale]], numpy.float64))
 
+       def split(self):
+               ret = []
+               for oriMesh in self._meshList:
+                       for m in oriMesh.split():
+                               obj = printableObject()
+                               obj._meshList.append(m)
+                               obj._postProcessAfterLoad()
+                               ret.append(obj)
+               return ret
+
 class mesh(object):
        def __init__(self):
                self.vertexes = None
@@ -237,87 +247,62 @@ class mesh(object):
                self.normal = n.reshape(self.vertexCount, 3)
                self.invNormal = -self.normal
 
-       def splitToParts(self, callback = None):
-               t0 = time.time()
+       def _vertexHash(self, idx):
+               v = self.vertexes[idx]
+               return int(v[0] * 100) | int(v[1] * 100) << 8 | int(v[2] * 100) << 16
+
+       def _idxFromHash(self, map, idx):
+               vHash = self._vertexHash(idx)
+               for i in map[vHash]:
+                       if numpy.linalg.norm(self.vertexes[i] - self.vertexes[idx]) < 0.001:
+                               return i
+
+       def split(self):
+               vertexMap = {}
 
-               #print "%f: " % (time.time() - t0), "Splitting a model with %d vertexes." % (len(self.vertexes))
-               removeDict = {}
-               tree = util3d.AABBTree()
-               off = numpy.array([0.0001,0.0001,0.0001])
+               vertexToFace = []
                for idx in xrange(0, self.vertexCount):
-                       v = self.vertexes[idx]
-                       e = util3d.AABB(v-off, v+off)
-                       q = tree.query(e)
-                       if len(q) < 1:
-                               e.idx = idx
-                               tree.insert(e)
-                       else:
-                               removeDict[idx] = q[0].idx
-                       if callback is not None and (idx % 100) == 0:
-                               callback(idx)
-               #print "%f: " % (time.time() - t0), "Marked %d duplicate vertexes for removal." % (len(removeDict))
+                       print idx, self.vertexCount
+                       vHash = self._vertexHash(idx)
+                       if vHash not in vertexMap:
+                               vertexMap[vHash] = []
+                       vertexMap[vHash].append(idx)
+                       vertexToFace.append([])
 
                faceList = []
                for idx in xrange(0, self.vertexCount, 3):
-                       f = [idx, idx + 1, idx + 2]
-                       if removeDict.has_key(f[0]):
-                               f[0] = removeDict[f[0]]
-                       if removeDict.has_key(f[1]):
-                               f[1] = removeDict[f[1]]
-                       if removeDict.has_key(f[2]):
-                               f[2] = removeDict[f[2]]
+                       print idx, self.vertexCount
+                       f = [self._idxFromHash(vertexMap, idx), self._idxFromHash(vertexMap, idx+1), self._idxFromHash(vertexMap, idx+2)]
+                       vertexToFace[f[0]].append(idx / 3)
+                       vertexToFace[f[1]].append(idx / 3)
+                       vertexToFace[f[2]].append(idx / 3)
                        faceList.append(f)
-               
-               #print "%f: " % (time.time() - t0), "Building face lists after vertex removal."
-               vertexFaceList = []
-               for idx in xrange(0, self.vertexCount):
-                       vertexFaceList.append([])
-               for idx in xrange(0, len(faceList)):
-                       f = faceList[idx]
-                       vertexFaceList[f[0]].append(idx)
-                       vertexFaceList[f[1]].append(idx)
-                       vertexFaceList[f[2]].append(idx)
-               
-               #print "%f: " % (time.time() - t0), "Building parts."
-               self._vertexFaceList = vertexFaceList
-               self._faceList = faceList
-               partList = []
+
+               ret = []
                doneSet = set()
                for idx in xrange(0, len(faceList)):
-                       if not idx in doneSet:
-                               partList.append(self._createPartFromFacewalk(idx, doneSet))
-               #print "%f: " % (time.time() - t0), "Split into %d parts" % (len(partList))
-               self._vertexFaceList = None
-               self._faceList = None
-               return partList
-
-       def _createPartFromFacewalk(self, startFaceIdx, doneSet):
-               m = mesh()
-               m._prepareVertexCount(self.vertexCount)
-               todoList = [startFaceIdx]
-               doneSet.add(startFaceIdx)
-               while len(todoList) > 0:
-                       faceIdx = todoList.pop()
-                       self._partAddFacewalk(m, faceIdx, doneSet, todoList)
-               return m
-
-       def _partAddFacewalk(self, part, faceIdx, doneSet, todoList):
-               f = self._faceList[faceIdx]
-               v0 = self.vertexes[f[0]]
-               v1 = self.vertexes[f[1]]
-               v2 = self.vertexes[f[2]]
-               part.addVertex(v0[0], v0[1], v0[2])
-               part.addVertex(v1[0], v1[1], v1[2])
-               part.addVertex(v2[0], v2[1], v2[2])
-               for f1 in self._vertexFaceList[f[0]]:
-                       if f1 not in doneSet:
-                               todoList.append(f1)
-                               doneSet.add(f1)
-               for f1 in self._vertexFaceList[f[1]]:
-                       if f1 not in doneSet:
-                               todoList.append(f1)
-                               doneSet.add(f1)
-               for f1 in self._vertexFaceList[f[2]]:
-                       if f1 not in doneSet:
-                               todoList.append(f1)
-                               doneSet.add(f1)
+                       if idx in doneSet:
+                               continue
+                       doneSet.add(idx)
+                       todoList = [idx]
+                       meshFaceList = []
+                       while len(todoList) > 0:
+                               idx = todoList.pop()
+                               meshFaceList.append(idx)
+                               for n in xrange(0, 3):
+                                       for i in vertexToFace[faceList[idx][n]]:
+                                               if not i in doneSet:
+                                                       doneSet.add(i)
+                                                       todoList.append(i)
+
+                       m = mesh()
+                       m._prepareFaceCount(len(meshFaceList))
+                       for idx in meshFaceList:
+                               m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][0]]
+                               m.vertexCount += 1
+                               m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][1]]
+                               m.vertexCount += 1
+                               m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][2]]
+                               m.vertexCount += 1
+                       ret.append(m)
+               return ret
index c2944e2580d4f33f6687af49b9b143d4d4e30269..0338367a3cc1f7f99b0c7c0ffb664cba091e4e20 100644 (file)
@@ -20,9 +20,19 @@ class _objectOrderFinder(object):
                if len(initialList) == 0:
                        self.order = []
                        return
+
+               self._hitMap = [None] * (max(initialList)+1)
+               for a in initialList:
+                       self._hitMap[a] = [False] * (max(initialList)+1)
+                       for b in initialList:
+                               self._hitMap[a][b] = self._checkHit(a, b)
+
+               initialList.sort(self._objIdxCmp)
+
                self._todo = [_objectOrder([], initialList)]
                while len(self._todo) > 0:
                        current = self._todo.pop()
+                       #print len(self._todo), len(current.order), len(initialList)
                        for addIdx in current.todo:
                                if not self._checkHitFor(addIdx, current.order):
                                        todoList = current.todo[:]
@@ -35,9 +45,14 @@ class _objectOrderFinder(object):
                                        self._todo.append(_objectOrder(order, todoList))
                self.order = None
 
+       def _objIdxCmp(self, a, b):
+               scoreA = sum(self._hitMap[a])
+               scoreB = sum(self._hitMap[b])
+               return scoreA - scoreB
+
        def _checkHitFor(self, addIdx, others):
                for idx in others:
-                       if self._checkHit(addIdx, idx):
+                       if self._hitMap[addIdx][idx]:
                                return True
                return False
 
index 4866b4ecbd3416c30ebb2f3d15171f98ebd8210a..9583172b96907dfd1aaa884f81791cdee853536b 100644 (file)
@@ -100,7 +100,8 @@ class Slicer(object):
                                        except:
                                                pass
                        else:
-                               print '#', line.strip()
+                               #print '#', line.strip()
+                               pass
                        line = self._process.stdout.readline()
                for line in self._process.stderr:
                        print line.strip()