def get_area(self): pt1 = ModelData.dictVertices[self.__v[0]] pt2 = ModelData.dictVertices[self.__v[1]] pt3 = ModelData.dictVertices[self.__v[2]] pt1pt2 = SimpleMath.tuple_minus(pt2, pt1) pt1pt3 = SimpleMath.tuple_minus(pt3, pt1) return 0.5 * SimpleMath.vector_length_3(SimpleMath.cross_product_3(pt1pt2, pt1pt3))
def keep_tetrahedron(curTetId, faceIDsInCurTet): #use the tag of the tetrahedron if ModelData.dictTetrahedrons[curTetId].get_tag == ClassFace.FIX: return #set the tag ModelData.dictTetrahedrons[curTetId].set_tag(ClassFace.FIX) #deal with all the known faces for j in faceIDsInCurTet: if ModelData.dictFaces[j].get_tag() != ClassFace.FIX: ModelData.dictFaces[j].set_tag(ClassFace.KEEP) #add the unkown faces and define them as KEEP (in order to seperate KEEP and FIX) if len(faceIDsInCurTet) < 4: vertexList = ModelData.dictTetrahedrons[curTetId].get_vids() faceList = [] faceList.append((vertexList[0], vertexList[1], vertexList[2])) faceList.append((vertexList[0], vertexList[2], vertexList[3])) faceList.append((vertexList[0], vertexList[3], vertexList[1])) faceList.append((vertexList[1], vertexList[2], vertexList[3])) for f in faceList: isDefined = False for i in faceIDsInCurTet: if ModelData.dictFaces[i].is_equal_geometry(ClassFace.Class_face(f)): isDefined = True break if not isDefined : tetNormal = [] for v in vertexList: if v not in f: #facing outwards tetNormal = SimpleMath.tuple_minus(ModelData.dictVertices[f[0]], ModelData.dictVertices[v]) break #do not have to consider semantics at this moment fId = ModelDataFuncs.add_face(ClassFace.Class_face(ModelDataFuncs.create_orientated_vids(f, tetNormal), ClassFace.KEEP))
def constraint_5(curTetId, faceIDsInCurTet): bIsInterior = False for i in faceIDsInCurTet: if ModelData.dictFaces[i].get_tag() == ClassFace.FIX: #normal check vIds = ModelData.dictFaces[i].get_vids() vectorNormal = SimpleMath.get_face_normal([ModelData.dictVertices[vIds[0]], ModelData.dictVertices[vIds[1]], ModelData.dictVertices[vIds[2]]]) for v in ModelData.dictTetrahedrons[curTetId].get_vids(): if v not in vIds: #test whether the tetrahedron is in the interior vectorTest = SimpleMath.tuple_minus(ModelData.dictVertices[v], ModelData.dictVertices[vIds[0]]); if SimpleMath.dot_product_3(vectorNormal , vectorTest) < 0: #find one inside return True return bIsInterior
def reader_obj(FILEPATH): try: f_obj = file(FILEPATH, "r") except: print ("Invalide file: " + MIDFILEPATH) return False # read vertics and ModelData.dictFaces statFace = 0 for line in f_obj: if line.startswith("v") and line[1] == " ": line = line[1:-1].strip() vertList = map(float, line.split(" ")) add_vertexEx([vertList[0], vertList[1], vertList[2]]) elif line.startswith("f") and line[1] == " ": indexList = [] # to filter out the / for index in line[1:-1].strip().split(" "): indexList.append(index.split("/")[0]) statFace = statFace + 1 if len(indexList) > 2: # index - 1 indexList = [int(i) - 1 for i in indexList] add_face(Class_face((indexList[0], indexList[1], indexList[2]), ClassFace.FIX)) # check the content if len(ModelData.dictFaces) == 0 or len(ModelData.dictVertices) == 0: print "Invalid Obj file!\n" return False else: print ("Remove " + str(statFace - len(ModelData.dictFaces)) + " invalid ModelData.dictFaces") print ( "Read " + str(len(ModelData.dictFaces)) + " ModelData.dictFaces and " + str(len(ModelData.dictVertices)) + " ModelData.dictVertices" ) f_obj.close() # optimise the coordinates by translate and scale for key in ModelData.dictVertices: ModelData.centerVertex = SimpleMath.tuple_plus(ModelData.centerVertex, ModelData.dictVertices[key]) ModelData.centerVertex = SimpleMath.tuple_numproduct(1.0 / len(ModelData.dictVertices), ModelData.centerVertex) # maxpt = [-9999999999.0, -9999999999.0, -9999999999.0] # minpt = [9999999999.0, 9999999999.0, 9999999999.0] for key in ModelData.dictVertices: ModelData.dictVertices[key] = SimpleMath.tuple_minus(ModelData.dictVertices[key], ModelData.centerVertex) # if ModelData.dictVertices[key][0] > maxpt[0]: # maxpt[0] = ModelData.dictVertices[key][0] # if ModelData.dictVertices[key][1] > maxpt[1]: # maxpt[1] = ModelData.dictVertices[key][1] # if ModelData.dictVertices[key][2] > maxpt[2]: # maxpt[2] = ModelData.dictVertices[key][2] # if ModelData.dictVertices[key][0] < minpt[0]: # minpt[0] = ModelData.dictVertices[key][0] # if ModelData.dictVertices[key][1] < minpt[1]: # minpt[1] = ModelData.dictVertices[key][1] # if ModelData.dictVertices[key][2] < minpt[2]: # minpt[2] = ModelData.dictVertices[key][2] # ModelData.scaleVertex = ModelData.scaleVertex / SimpleMath.vector_length_3(SimpleMath.tuple_minus(maxpt, minpt)) # for key in ModelData.dictVertices: # ModelData.dictVertices[key] = SimpleMath.tuple_numproduct(ModelData.scaleVertex, ModelData.dictVertices[key]) if ModelData.global_DO_TRUNCATE: truncate_verts(ModelData.global_TOL_TRUNCATE) print (">>>>>>Eliminate degeneracies...") clean_duplicated_vertices() print ("{} illshaped ModelData.dictFaces are removed").format(discard_illshaped_faces()) print ( "After cleaning redundant ModelData.dictVertices there are " + str(len(ModelData.dictFaces)) + " ModelData.dictFaces and " + str(len(ModelData.dictVertices)) + " ModelData.dictVertices" ) return True
def optimise_illshaped_shellfaces(): iCount = 0 for key in ModelData.listShellFaceIDs: if key not in ModelData.dictFaces: continue if ( ModelData.global_OPTIMAL_SHP and ModelData.dictFaces[key].get_tag() != ClassFace.FLIP and ModelData.dictFaces[key].get_area() < ModelData.global_TOL_AREA_DISCARD ): print key vert0 = ModelData.dictVertices[ModelData.dictFaces[key].get_vids()[0]] vert1 = ModelData.dictVertices[ModelData.dictFaces[key].get_vids()[1]] vert2 = ModelData.dictVertices[ModelData.dictFaces[key].get_vids()[2]] # face collapse or flip # calculate vectors vector01 = SimpleMath.tuple_minus(vert0, vert1) length01 = SimpleMath.vector_length_3(vector01) if length01 > SimpleMath.Tol: vector01 = SimpleMath.tuple_numproduct(1.0 / length01, vector01) else: iCount += 1 collapse_edge(ModelData.dictFaces[key].get_vids()[0], ModelData.dictFaces[key].get_vids()[1]) continue vector21 = SimpleMath.tuple_minus(vert2, vert1) length21 = SimpleMath.vector_length_3(vector21) if length21 > SimpleMath.Tol: vector21 = SimpleMath.tuple_numproduct(1.0 / length21, vector21) else: iCount += 1 collapse_edge(ModelData.dictFaces[key].get_vids()[2], ModelData.dictFaces[key].get_vids()[1]) continue vector02 = SimpleMath.tuple_minus(vert0, vert2) length02 = SimpleMath.vector_length_3(vector02) if length02 > SimpleMath.Tol: vector02 = SimpleMath.tuple_numproduct(1.0 / length02, vector02) else: iCount += 1 collapse_edge(ModelData.dictFaces[key].get_vids()[0], ModelData.dictFaces[key].get_vids()[2]) continue # calculate angles Ang012 = SimpleMath.dot_product_3(vector01, vector21) Ang102 = SimpleMath.dot_product_3(vector01, vector02) vector12 = SimpleMath.tuple_numproduct(-1, vector21) Ang021 = SimpleMath.dot_product_3(vector02, vector12) # cos value if Ang012 < ModelData.global_TOL_LARGEST_ANGLE: # flip 20 iCount += 1 flip_edge(ModelData.dictFaces[key].get_vids()[2], ModelData.dictFaces[key].get_vids()[0]) elif Ang102 < ModelData.global_TOL_LARGEST_ANGLE: # flip 12 iCount += 1 flip_edge(ModelData.dictFaces[key].get_vids()[1], ModelData.dictFaces[key].get_vids()[2]) elif Ang021 < ModelData.global_TOL_LARGEST_ANGLE: # flip 01 iCount += 1 flip_edge(ModelData.dictFaces[key].get_vids()[0], ModelData.dictFaces[key].get_vids()[1]) # # clean_unreferenced_vertices() print ("{} illshaped ModelData.dictFaces are optimized").format(iCount) if iCount > 0: return True else: return False
def reader_poly_with_semantics(str_filepath): fin = file(str_filepath, "r") # read the first line and try to extract semantics strFirstLine = fin.readline().split() if strFirstLine[0] == "#": # read the building id ModelData.strModelID = strFirstLine[1] # whether the geometry is a solid:1 or a multisurface:0 ModelData.isSolid = fin.readline().split()[1] # the point information strFirstLine = int(fin.readline().split()[0]) else: # no semanics ModelData.strModelID = "-1" # we assume it is a solid ModelData.isSolid = "1" # the point information strFirstLine = int(strFirstLine[0]) # read all the points for i in range(strFirstLine): vertList = map(float, fin.readline().split()[1:4]) add_vertexEx((vertList[0], vertList[1], vertList[2])) # read each face nof = int(fin.readline().split()[0]) strPolygonid = "" strPolygontype = "" for i in range(nof): strPolygoninfo = fin.readline().split() numRings = int(strPolygoninfo[0]) if numRings != 1: print ("The input has not been tesselated") return False if len(strPolygoninfo) >= 4: strPolygonid = strPolygoninfo[3] if len(strPolygoninfo) >= 6: strPolygontype = strPolygoninfo[5] oring = map(int, fin.readline().split()) if len(oring) > 4: print ("The input has not been tesselated") return False oring.pop(0) if len(oring) == 3: add_face(Class_face((oring[0], oring[1], oring[2]), ClassFace.FIX, strPolygonid, strPolygontype)) # check the content if len(ModelData.dictFaces) == 0 or len(ModelData.dictVertices) == 0: print "Invalid Poly file!\n" return False else: print ("Remove " + str(nof - len(ModelData.dictFaces)) + " invalid Faces") print ("Read " + str(len(ModelData.dictFaces)) + " Faces and " + str(len(ModelData.dictVertices)) + " Vertices") fin.close() # optimise the coordinates by translate and scale for key in ModelData.dictVertices: ModelData.centerVertex = SimpleMath.tuple_plus(ModelData.centerVertex, ModelData.dictVertices[key]) ModelData.centerVertex = SimpleMath.tuple_numproduct(1.0 / len(ModelData.dictVertices), ModelData.centerVertex) for key in ModelData.dictVertices: ModelData.dictVertices[key] = SimpleMath.tuple_minus(ModelData.dictVertices[key], ModelData.centerVertex) if ModelData.global_DO_TRUNCATE: truncate_verts(ModelData.global_TOL_TRUNCATE) print ("--Eliminate degeneracies") clean_duplicated_vertices() print ("{} illshaped ModelData.dictFaces are removed").format(discard_illshaped_faces()) print ( "After cleaning redundant ModelData.dictVertices there are " + str(len(ModelData.dictFaces)) + " Faces and " + str(len(ModelData.dictVertices)) + " Vertices" ) return True