def extract_mesh_from_tet(bIsSemantics = False): print("----Extract the output mesh----") #check if len(ModelData.dictTetrahedrons) == 0: print("invalid call extract Mesh") return #deletion and deduce semantics for fkey in ModelData.dictFaces: if fkey not in ModelData.listShellFaceIDs: ModelDataFuncs.pre_remove_face_by_faceids([fkey]) #clearup if ModelDataFuncs.remove_faces() > 0: print ("Mesh extracted") #optimisazation if ModelDataFuncs.optimise_illshaped_shellfaces(): ModelDataFuncs.remove_faces() ModelDataFuncs.clean_duplicated_vertices() ModelDataFuncs.clean_unreferenced_vertices() ModelDataFuncs.restore_normals() #deduce semantics deduce_semantics_of_poly(bIsSemantics)
def CDT(): print("Start tetrahedralization....") curDirBefore = os.getcwd() path = os.path.dirname(os.path.realpath(__file__)) if sizeof(c_voidp) == 4: #win32 path = os.path.join(path, '..\\tetgendll\\Release') os.chdir(path) if not os.path.exists("tetgendll.dll"): print("DLL missing: " + path + "tetgendll.dll") Tetrahedralator = CDLL("tetgendll.dll") elif sizeof(c_voidp) == 8: #x64 path = os.path.join(path, '..\\tetgendll\\x64\\Release') os.chdir(path) if not os.path.exists("tetgendll.dll"): print("DLL missing: " + path + "tetgendll.dll") Tetrahedralator = CDLL("tetgendll.dll") os.chdir(curDirBefore) #be careful with the indices #record the indices of inserted dictVertices and map the indices in the dictFaces and tetrahedron to the finally added indices mapVertTet = {} iCount = 0 cVertices = (c_double * (len(ModelData.dictVertices) * 3))() #the size of dictVertices *3 for key in ModelData.dictVertices: cVertices[3*iCount] = c_double(ModelData.dictVertices[key][0]) cVertices[3*iCount+1] = c_double(ModelData.dictVertices[key][1]) cVertices[3*iCount+2] = c_double(ModelData.dictVertices[key][2]) mapVertTet[iCount] = key iCount += 1 iCount = 0 cFaces = (c_int * (len(ModelData.dictFaces) * 3))() #the size of dictFaces * 3 for key in ModelData.dictFaces: #be careful with the indices cFaces[3*iCount] = c_int(ModelDataFuncs.find_key_from_dict_by_exact_value(mapVertTet, ModelData.dictFaces[key].get_vids()[0])) cFaces[3*iCount+1] = c_int(ModelDataFuncs.find_key_from_dict_by_exact_value(mapVertTet, ModelData.dictFaces[key].get_vids()[1])) cFaces[3*iCount+2] = c_int(ModelDataFuncs.find_key_from_dict_by_exact_value(mapVertTet, ModelData.dictFaces[key].get_vids()[2])) iCount += 1 numberOfOutputVerts = c_int(0); numberOfOutputTriangles = c_int(0); numberOfOutputTetrahedrons = c_int(0); try: Tetrahedralator.simpleTetrahedralize(byref(cVertices), c_int(len(ModelData.dictVertices)), byref(cFaces), c_int(len(ModelData.dictFaces)), byref(numberOfOutputVerts), byref(numberOfOutputTriangles), byref(numberOfOutputTetrahedrons)) except ValueError: print("CDT failed") return False #check if numberOfOutputTetrahedrons.value == 0: print("tetrahedralization failed") return False #Get the results outputVerts = (c_double * (numberOfOutputVerts.value *3))() outputConvexhullTris = (c_int * (numberOfOutputTriangles.value *3))() outputTetrahedrons = (c_int * (numberOfOutputTetrahedrons.value *4))() Tetrahedralator.getResults(pointer(outputVerts), pointer(outputConvexhullTris), pointer(outputTetrahedrons)) #update the ModelData #dictVertices if numberOfOutputVerts.value > len(ModelData.dictVertices): print("{} steiner points inserted (at the back of the original list)").format(numberOfOutputVerts.value - len(ModelData.dictVertices)) for i in range(len(ModelData.dictVertices) * 3, numberOfOutputVerts.value * 3, 3): #be carefull with the indices (start with 0) mapVertTet[len(mapVertTet)] = ModelDataFuncs.add_vertex((outputVerts[i], outputVerts[i+1], outputVerts[i+2])) #dictTetrahedrons for i in range(0, numberOfOutputTetrahedrons.value * 4, 4): ModelData.dictTetrahedrons[i/4] = Class_tetrahedron((mapVertTet[outputTetrahedrons[i]], mapVertTet[outputTetrahedrons[i+1]], mapVertTet[outputTetrahedrons[i+2]], mapVertTet[outputTetrahedrons[i+3]])) #record the the triangles on the shell isFaceDeleted = False for i in range(0, numberOfOutputTriangles.value*3, 3): tris = (mapVertTet[outputConvexhullTris[i]], mapVertTet[outputConvexhullTris[i+1]], mapVertTet[outputConvexhullTris[i+2]]) isExt = False for f in ModelData.dictFaces: if ModelData.dictFaces[f].is_equal_geometry(ClassFace.Class_face(tris)): #found the existing face isExt = True #add to the list of shell face ModelData.listShellFaceIDs.append(f) break if isExt == False: #distance mapping in case this geometry is produced by flipping the coplanar triangle fId = ModelDataFuncs.find_face_by_mapping(tris) if fId: ModelData.listShellFaceIDs.append(ModelDataFuncs.add_face(ClassFace.Class_face(tris, ClassFace.FIX, ModelData.dictFaces[fId].get_id(), ModelData.dictFaces[fId].get_type()))) ModelDataFuncs.pre_remove_face_by_faceids([fId]) isFaceDeleted = True else: #add the new face and add the face to the list of shell face ModelData.listShellFaceIDs.append(ModelDataFuncs.add_face(ClassFace.Class_face(tris))) #remove faces if isFaceDeleted: ModelDataFuncs.remove_faces() # print ("After CDT: " + str(len(ModelData.dictTetrahedrons)) + " tetrahedra and " + str(len(ModelData.dictFaces)) + " dictFaces and " + str(len(ModelData.dictVertices)) + " dictVertices") return True
def heuristic_tet_carving(): print("----Heuristic shrinking-wrapping----") #keep all the tetrahedra that have fix facets on the shell #in update_stack() this step is not needed because it has already been handled in carving for fId in ModelData.listShellFaceIDs: if ModelData.dictFaces[fId].get_tag() == ClassFace.FIX: tetId = TetraFunc.find_tetids_by_faceid(fId, 1) keep_tetrahedron(tetId[0], TetraFunc.get_faceids_from_tetid(tetId[0])) #count numCount = 0 #initiate Stack and lists sortedTetIDStack = update_stack() #heruistic carving while len(sortedTetIDStack) > 0: #pop the first not fix element of stack if possible curTet = sortedTetIDStack.pop(0) curTetId = curTet[0] print curTetId #fetch all the shellFaces (indices) from a given Tet shellFaceIDsInCurTet = curTet[1] #fetch all the dictFaces (indices) from a given Tet faceIDsInCurTet = curTet[2] #classify the tetrahedron numTMP = len(shellFaceIDsInCurTet)#equal to the no. of faces on the shell numFIX = 0 for fid in faceIDsInCurTet: if ModelData.dictFaces[fid].get_tag() == ClassFace.FIX: numFIX += 1 numKEEP = len(faceIDsInCurTet) - numTMP - numFIX#keep face is not constrainted as fixed ones numPRESERV = numFIX + numKEEP #test by a set of constraints bStop = False bPostponed = False carveTetList = [] #for infinite tetehedra keepFaceList = [] #for coplanar bounded facets unboundFaceList = [] #for coplanar unbouned facets # new code #if numFIX == 0 and numTMP == 1: # #constraint3 # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) #elif numFIX == 1 and numTMP == 3: # #constraint5 # if constraintsCtrl['Constraint5'] and not bStop: # bStop = constraint_5(curTetId, faceIDsInCurTet) # #check all faces with constraint 3 not needed in theory (flat tetrahedra) # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[1]) # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[2]) #elif numFIX in (1, 2) and numTMP == 2: # #c1 5 # if constraintsCtrl['Constraint5'] and not bStop: # bStop = constraint_5(curTetId, faceIDsInCurTet) # if constraintsCtrl['Constraint1'] and not bStop: # #extract the opposite edge # eList = [] # for i in shellFaceIDsInCurTet: # for j in range(0, 3): # if ModelData.dictFaces[i].get_vids()[j] not in eList: # eList.append(ModelData.dictFaces[i].get_vids()[j]) # else: # eList.remove(ModelData.dictFaces[i].get_vids()[j]) # # if not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList) # # #check all faces with constraint 3 not needed in theory (flat tetrahedra) # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[1]) #elif numFIX in (1, 2, 3) and numTMP == 1: # #c1 2 3 5 # #constraint5 # if constraintsCtrl['Constraint5'] and not bStop: # bStop = constraint_5(curTetId, faceIDsInCurTet) # # #constraint3 # if constraintsCtrl['Constraint3'] and not bStop: # bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) # if (constraintsCtrl['Constraint2'] or constraintsCtrl['Constraint1']) and not bStop: # #extract the candidate face, the opposite edge list (three) the and opposite vert # tmpFace = shellFaceIDsInCurTet[0] # #the opposite vertex # oppVert = -1 # #the opposite edge list # eList = [] # for v in ModelData.dictTetrahedrons[curTetId].get_vids(): # if v not in ModelData.dictFaces[tmpFace].get_vids(): # oppVert = v # if numFIX == 1: # #only two edges # fixFace = list(set(faceIDsInCurTet) - set(shellFaceIDsInCurTet)) # for v_1 in ModelData.dictFaces[fixFace[0]].get_vids(): # if v_1 != oppVert: # eList.append((v, v_1)) # else: # #three edges # for n in ModelData.dictFaces[tmpFace].get_vids(): # eList.append((v, n)) # break # #check with constraints 1 2 # #2 # if constraintsCtrl['Constraint2'] and not bStop: # bStop, bPostponed, carveTetList = constraint_2(curTetId, oppVert) # #1 # if numFIX == 1: # #two edges # if constraintsCtrl['Constraint1'] and not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[0]) # if constraintsCtrl['Constraint1'] and not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[1]) # else: # #three edges # if constraintsCtrl['Constraint1'] and not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[0]) # if constraintsCtrl['Constraint1'] and not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[1]) # if constraintsCtrl['Constraint1'] and not bStop: # bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[2]) #elif numFIX == 0: # #check all faces with constraint 3 not needed in theory (flat tetrahedra) # if constraintsCtrl['Constraint3'] and not bStop: # for fID in shellFaceIDsInCurTet: # bStop, keepFaceList, unboundFaceList = constraint_3(fID) #old code #every carving step is constrainted, esp. those without fixed faces if numTMP == 4: print('Isolated tetrahedron') pass #check all faces with constraint 3 not needed in theory if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[1]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[2]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[3]) elif numTMP == 3: #check with constraints 5 if numFIX == 1: if constraintsCtrl['Constraint5'] and not bStop: bStop = constraint_5(curTetId, faceIDsInCurTet) #check all faces with constraint 3 not needed in theory if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[1]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[2]) elif numTMP == 2: if constraintsCtrl['Constraint1']: #extract the opposite edge eList = [] for i in shellFaceIDsInCurTet: for j in range(0, 3): if ModelData.dictFaces[i].get_vids()[j] not in eList: eList.append(ModelData.dictFaces[i].get_vids()[j]) else: eList.remove(ModelData.dictFaces[i].get_vids()[j]) #1 different with new code if constraintsCtrl['Constraint1'] and not bStop: bStop, bPostponed, carveTetList = constraint_1(curTetId, eList) #5 if numFIX != 0: if constraintsCtrl['Constraint5'] and not bStop: bStop = constraint_5(curTetId, faceIDsInCurTet) #check both faces with constraint 3 not needed in theory if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[0]) if constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(shellFaceIDsInCurTet[1]) elif numTMP == 1: if constraintsCtrl['Constraint2'] or constraintsCtrl['Constraint1']: #extract the candidate face, the opposite edge list (three) the and opposite vert tmpFace = shellFaceIDsInCurTet[0] #the opposite vertex oppVert = -1 #the opposite edge list eList = [] for v in ModelData.dictTetrahedrons[curTetId].get_vids(): if v not in ModelData.dictFaces[tmpFace].get_vids(): oppVert = v for n in ModelData.dictFaces[tmpFace].get_vids(): eList.append((v, n)) break #check with constraints 1 2 3 5 #2 different with new code if constraintsCtrl['Constraint2'] and not bStop: bStop, bPostponed, carveTetList = constraint_2(curTetId, oppVert) #1 different with new code if constraintsCtrl['Constraint1'] and not bStop: bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[0]) if constraintsCtrl['Constraint1'] and not bStop: bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[1]) if constraintsCtrl['Constraint1'] and not bStop: bStop, bPostponed, carveTetList = constraint_1(curTetId, eList[2]) if numFIX != 0 and constraintsCtrl['Constraint5'] and not bStop: #5 bStop = constraint_5(curTetId, faceIDsInCurTet) #3 if numFIX != 3 and constraintsCtrl['Constraint3'] and not bStop: bStop, keepFaceList, unboundFaceList = constraint_3(tmpFace) else: print("Isolated Tetrahedron!", numTMP, numKNOWN) #raise Exception #manipulate the tetrahedron numTet = len(ModelData.dictTetrahedrons) if bStop: #keep if len(keepFaceList) != 0: #keep a bunch of "coplanar" tetrehedra for faceId in keepFaceList: tetId = TetraFunc.find_tetids_by_faceid(faceId, 1) if tetId != []: keep_tetrahedron(tetId[0], TetraFunc.get_faceids_from_tetid(tetId[0])) #carve a bunch of "coplanar" unbouned tetrehedra if len(unboundFaceList) != 0: for faceId in unboundFaceList: tetId = TetraFunc.find_tetids_by_faceid(faceId, 1) if tetId != []: carve_tetrahedron(tetId[0], TetraFunc.get_faceids_from_tetid(tetId[0])) else: #keep keep_tetrahedron(curTetId, faceIDsInCurTet) else: #carve or postpone if not bPostponed: #Carve bIsCarved = True carve_tetrahedron(curTetId, faceIDsInCurTet) else: #postpone if ModelData.dictTetrahedrons[curTetId].get_tag() == ClassFace.INF: #all the tetrehedra are infinite (INF) for tetId in carveTetList: #carve a bunch of tetrahedra carve_tetrahedron(tetId, TetraFunc.get_faceids_from_tetid(tetId)) else: #postphone the tetrahedron ModelData.dictTetrahedrons[curTetId].set_tag(ClassFace.INF) #Update the dictFaces ModelDataFuncs.remove_faces() #Update the stack and lists sortedTetIDStack = update_stack() #Output intermediate results if globalOutputCarve and numTet > len(ModelData.dictTetrahedrons) and len(ModelData.dictTetrahedrons) % globalOutputFreq == 0: ModelDataFuncs.writer_obj(ModelData.strInputFileName + '_' + str(len(ModelData.dictTetrahedrons)) + "_CARVE_.obj")