Fixed the part splitter

This commit is contained in:
daid 2012-07-27 11:02:23 +02:00
parent 44c38bf924
commit c0ff43a221
3 changed files with 58 additions and 57 deletions

View File

@ -84,7 +84,6 @@ class mesh(object):
removeDict = {} removeDict = {}
tree = util3d.AABBTree() tree = util3d.AABBTree()
off = numpy.array([0.0001,0.0001,0.0001]) off = numpy.array([0.0001,0.0001,0.0001])
newVertexList = []
for idx in xrange(0, self.vertexCount): for idx in xrange(0, self.vertexCount):
v = self.vertexes[idx] v = self.vertexes[idx]
e = util3d.AABB(v-off, v+off) e = util3d.AABB(v-off, v+off)
@ -92,67 +91,71 @@ class mesh(object):
if len(q) < 1: if len(q) < 1:
e.idx = idx e.idx = idx
tree.insert(e) tree.insert(e)
newVertexList.append(v)
else: else:
removeDict[idx] = q[0].idx removeDict[idx] = q[0].idx
print "%f: " % (time.time() - t0), "Marked %d duplicate vertexes for removal." % (len(removeDict)) print "%f: " % (time.time() - t0), "Marked %d duplicate vertexes for removal." % (len(removeDict))
#Make facelists so we can quickly remove all the vertexes. 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]]
faceList.append(f)
print "%f: " % (time.time() - t0), "Building face lists after vertex removal."
vertexFaceList = [] vertexFaceList = []
for idx in xrange(0, self.vertexCount): for idx in xrange(0, self.vertexCount):
vertexFaceList.append([]) vertexFaceList.append([])
for f in self.faces: for idx in xrange(0, len(faceList)):
f.v[0].faceList.append(f) f = faceList[idx]
f.v[1].faceList.append(f) vertexFaceList[f[0]].append(idx)
f.v[2].faceList.append(f) vertexFaceList[f[1]].append(idx)
vertexFaceList[f[2]].append(idx)
self.vertexes = newVertexList
for v1 in removeDict.iterkeys():
v0 = removeDict[v1]
for f in v1.faceList:
if f.v[0] == v1:
f.v[0] = v0
if f.v[1] == v1:
f.v[1] = v0
if f.v[2] == v1:
f.v[2] = v0
print "%f: " % (time.time() - t0), "Building face lists after vertex removal."
for v in self.vertexes:
v.faceList = []
for f in self.faces:
f.v[0].faceList.append(f)
f.v[1].faceList.append(f)
f.v[2].faceList.append(f)
print "%f: " % (time.time() - t0), "Building parts." print "%f: " % (time.time() - t0), "Building parts."
self._vertexFaceList = vertexFaceList
self._faceList = faceList
partList = [] partList = []
doneSet = set() doneSet = set()
for f in self.faces: for idx in xrange(0, len(faceList)):
if not f in doneSet: if not idx in doneSet:
partList.append(self._createPartFromFacewalk(f, doneSet)) partList.append(self._createPartFromFacewalk(idx, doneSet))
print "%f: " % (time.time() - t0), "Split into %d parts" % (len(partList)) print "%f: " % (time.time() - t0), "Split into %d parts" % (len(partList))
self._vertexFaceList = None
self._faceList = None
return partList return partList
def _createPartFromFacewalk(self, startFace, doneSet): def _createPartFromFacewalk(self, startFaceIdx, doneSet):
m = mesh() m = mesh()
todoList = [startFace] m._prepareVertexCount(self.vertexCount)
doneSet.add(startFace) todoList = [startFaceIdx]
doneSet.add(startFaceIdx)
while len(todoList) > 0: while len(todoList) > 0:
f = todoList.pop() faceIdx = todoList.pop()
m._partAddFacewalk(f, doneSet, todoList) self._partAddFacewalk(m, faceIdx, doneSet, todoList)
return m return m
def _partAddFacewalk(self, f, doneSet, todoList): def _partAddFacewalk(self, part, faceIdx, doneSet, todoList):
self.addFace(f.v[0], f.v[1], f.v[2]) f = self._faceList[faceIdx]
for f1 in f.v[0].faceList: v0 = self.vertexes[f[0]]
v1 = self.vertexes[f[0]]
v2 = self.vertexes[f[0]]
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: if f1 not in doneSet:
todoList.append(f1) todoList.append(f1)
doneSet.add(f1) doneSet.add(f1)
for f1 in f.v[1].faceList: for f1 in self._vertexFaceList[f[1]]:
if f1 not in doneSet: if f1 not in doneSet:
todoList.append(f1) todoList.append(f1)
doneSet.add(f1) doneSet.add(f1)
for f1 in f.v[2].faceList: for f1 in self._vertexFaceList[f[2]]:
if f1 not in doneSet: if f1 not in doneSet:
todoList.append(f1) todoList.append(f1)
doneSet.add(f1) doneSet.add(f1)

View File

@ -66,6 +66,6 @@ if __name__ == '__main__':
m = stlModel().load(filename) m = stlModel().load(filename)
print("Loaded %d faces" % (m.vertexCount / 3)) print("Loaded %d faces" % (m.vertexCount / 3))
parts = m.splitToParts() parts = m.splitToParts()
# for p in parts: for p in parts:
# saveAsSTL(p, "export_%i.stl" % parts.index(p)) saveAsSTL(p, "export_%i.stl" % parts.index(p))

View File

@ -82,9 +82,7 @@ class AABB(object):
def __init__(self, vMin, vMax): def __init__(self, vMin, vMax):
self.vMin = vMin self.vMin = vMin
self.vMax = vMax self.vMax = vMax
self.perimeter = numpy.sum(self.vMax - self.vMin)
def getPerimeter(self):
return (self.vMax[0] - self.vMax[0]) + (self.vMax[1] - self.vMax[1]) + (self.vMax[2] - self.vMax[2])
def combine(self, aabb): def combine(self, aabb):
return AABB(numpy.minimum(self.vMin, aabb.vMin), numpy.maximum(self.vMax, aabb.vMax)) return AABB(numpy.minimum(self.vMin, aabb.vMin), numpy.maximum(self.vMax, aabb.vMax))
@ -125,25 +123,25 @@ class AABBTree(object):
child1 = node.child1 child1 = node.child1
child2 = node.child2 child2 = node.child2
area = node.aabb.getPerimeter() area = node.aabb.perimeter
combinedAABB = node.aabb.combine(aabb) combinedAABB = node.aabb.combine(aabb)
combinedArea = combinedAABB.getPerimeter() combinedArea = combinedAABB.perimeter
cost = 2.0 * combinedArea cost = 2.0 * combinedArea
inheritanceCost = 2.0 * (combinedArea - area) inheritanceCost = 2.0 * (combinedArea - area)
if child1.isLeaf(): if child1.isLeaf():
cost1 = aabb.combine(child1.aabb).getPerimeter() + inheritanceCost cost1 = aabb.combine(child1.aabb).perimeter + inheritanceCost
else: else:
oldArea = child1.aabb.getPerimeter() oldArea = child1.aabb.perimeter
newArea = aabb.combine(child1.aabb).getPerimeter() newArea = aabb.combine(child1.aabb).perimeter
cost1 = (newArea - oldArea) + inheritanceCost cost1 = (newArea - oldArea) + inheritanceCost
if child2.isLeaf(): if child2.isLeaf():
cost2 = aabb.combine(child1.aabb).getPerimeter() + inheritanceCost cost2 = aabb.combine(child1.aabb).perimeter + inheritanceCost
else: else:
oldArea = child2.aabb.getPerimeter() oldArea = child2.aabb.perimeter
newArea = aabb.combine(child2.aabb).getPerimeter() newArea = aabb.combine(child2.aabb).perimeter
cost2 = (newArea - oldArea) + inheritanceCost cost2 = (newArea - oldArea) + inheritanceCost
if cost < cost1 and cost < cost2: if cost < cost1 and cost < cost2:
@ -230,8 +228,8 @@ class AABBTree(object):
A.aabb = B.aabb.combine(G.aabb) A.aabb = B.aabb.combine(G.aabb)
C.aabb = A.aabb.combine(F.aabb) C.aabb = A.aabb.combine(F.aabb)
A.height = 1 + Math.max(B.height, G.height) A.height = 1 + max(B.height, G.height)
C.height = 1 + Math.max(A.height, F.height) C.height = 1 + max(A.height, F.height)
else: else:
C.child2 = G C.child2 = G
A.child2 = F A.child2 = F
@ -309,9 +307,9 @@ class AABBTree(object):
if __name__ == '__main__': if __name__ == '__main__':
tree = AABBTree() tree = AABBTree()
tree.insert(AABB(numpy.array([0,0,0]), numpy.array([0,0,0]))) tree.insert(AABB(Vector3(0,0,0), Vector3(0,0,0)))
tree.insert(AABB(numpy.array([1,1,1]), numpy.array([1,1,1]))) tree.insert(AABB(Vector3(1,1,1), Vector3(1,1,1)))
tree.insert(AABB(numpy.array([0.5,0.5,0.5]), numpy.array([0.5,0.5,0.5]))) tree.insert(AABB(Vector3(0.5,0.5,0.5), Vector3(0.5,0.5,0.5)))
print(tree) print(tree)
print(tree.query(AABB(numpy.array([0,0,0]), numpy.array([0,0,0])))) print(tree.query(AABB(Vector3(0,0,0), Vector3(0,0,0))))