def create_orientated_vids(vids, normal): if SimpleMath.vector_length_3Ex(normal) < SimpleMath.Tol: print ("Degeneracy!!") return vids fNormal = SimpleMath.get_face_normal( [ModelData.dictVertices[vids[0]], ModelData.dictVertices[vids[1]], ModelData.dictVertices[vids[2]]] ) if SimpleMath.dot_product_3(normal, fNormal) > 0: return vids else: return (vids[1], vids[0], vids[2])
def coplaner_neighbors(fid, fNormal, tag): vertexIds = ModelData.dictFaces[fid].get_vids() for i in range(0, 3): j = 0 if i < 2: j = i + 1 face = CarveFunc.get_neighbor_shellface([vertexIds[i], vertexIds[j]], fid) if face not in tag and face is not None: newVertids = ModelData.dictFaces[face].get_vids() Normal = SimpleMath.get_face_normal([ModelData.dictVertices[newVertids[0]], ModelData.dictVertices[newVertids[1]], ModelData.dictVertices[newVertids[2]]]) if SimpleMath.vector_length_3(Normal) > SimpleMath.Tol and SimpleMath.dot_product_3(fNormal, Normal) > SimpleMath.NeighborAngle: tag.append(face) #only select the adjacent neighbors #coplaner_neighbors(face, Normal, tag)
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 deduce_semantics_of_face(fid): #detect coplaner neighbours vertexList = ModelData.dictFaces[fid].get_vids() curNormal = SimpleMath.get_face_normal([ModelData.dictVertices[vertexList[0]], ModelData.dictVertices[vertexList[1]], ModelData.dictVertices[vertexList[2]]]) if SimpleMath.vector_length_3(curNormal) > SimpleMath.Tol: #Get the normals of neighbors of this face tag = [fid] coplaner_neighbors(fid, curNormal, tag) #statistic of dominant semantics within tagged faces counterSemantics = Counter() for fid in tag: counterSemantics[(ModelData.dictFaces[fid].get_id(), ModelData.dictFaces[fid].get_type())] += 1 res = counterSemantics.most_common(2) #get the semantics strId = '' strType = '' if len(res) == 1 and res[0][0] == ('', ''): #deduce the semantics based on direction strId = ModelDataFuncs.generate_uuid() angle = SimpleMath.dot_product_3(curNormal, (0.0, 0.0, 1.0)) if angle <= 1 and angle > 0.087: #roof 0 to 85 strType = 'BUILDING_ROOF_SURFACE' elif angle < -0.999: #ground -0 to -1 strType = 'BUILDING_GROUND_SURFACE' else: #wall strType = 'BUILDING_WALL_SURFACE' else: if res[0][0] != ('', ''): strId = res[0][0][0] strType = res[0][0][1] elif res[1][0] != ('', ''): strId = res[1][0][0] strType = res[1][0][1] #assign the semantics to all the raw face in tag for f in tag: if ModelData.dictFaces[f].get_id() == '' : ModelData.dictFaces[f].set_id(strId) if ModelData.dictFaces[f].get_type() == '' : ModelData.dictFaces[f].set_type(strType) else: ModelData.dictFaces[fid].set_id(ModelDataFuncs.generate_uuid()) ModelData.dictFaces[fid].set_type('BUILDING_WALL_SURFACE')
def boundary_of_coplaner_neighbors(fid, fNormal, fVisited, listUnbounded, listSeedFace): vertexIds = ModelData.dictFaces[fid].get_vids() for i in range(0, 3): j = 0 if i < 2: j = i + 1 #test the adjacent face face = get_neighbor_shellface((vertexIds[i], vertexIds[j]), fid) #test the edge code = is_edge_open_fix_boundary((vertexIds[i], vertexIds[j]), fid, face) if code == 1: #is a open fixed boundary then get one unvisited face as a seed if ModelData.dictFaces[face].get_tag() != ClassFace.FIX and face not in fVisited: if TetraFunc.get_dihedral_cos_angle(ModelData.dictFaces[face].get_vids(), ModelData.dictFaces[fid].get_vids()) > SimpleMath.NeighborAngle: if face not in listSeedFace: listSeedFace.append(face) elif code == 2: #is a close fixed boundary if not globalSealConcave: return False else: #not a boundary newVertids = ModelData.dictFaces[face].get_vids() Normal = SimpleMath.get_face_normal((ModelData.dictVertices[newVertids[0]], ModelData.dictVertices[newVertids[1]], ModelData.dictVertices[newVertids[2]])) if (SimpleMath.vector_length_3(Normal) > SimpleMath.Tol and abs(SimpleMath.dot_product_3(fNormal, Normal)) > SimpleMath.NeighborAngle) or \ SimpleMath.vector_length_3(Normal) < SimpleMath.Tol: if face not in fVisited: fVisited.append(face) if SimpleMath.vector_length_3(Normal) < SimpleMath.Tol: if not boundary_of_coplaner_neighbors(face, fNormal, fVisited, listUnbounded, listSeedFace): return False else: #note: False should be not be modified to not if False == boundary_of_coplaner_neighbors(face, Normal, fVisited, listUnbounded, listSeedFace): return False else: if face in listUnbounded: #if in, test if it is connected to an unbounded face return False else: if face not in fVisited: fVisited.append(face) return False
def discard_illshaped_faces(): iCount = 0 for key in ModelData.dictFaces: if ModelData.global_DISCARD_TINY: if ModelData.dictFaces[key].get_area() < ModelData.global_TOL_AREA_DISCARD: pre_remove_face_by_faceids([key]) iCount = iCount + 1 continue if ModelData.global_DISCARD_DEG: 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]] if SimpleMath.vector_length_3(SimpleMath.get_face_normal([vert0, vert1, vert2])) < SimpleMath.Tol: pre_remove_face_by_faceids([key]) iCount = iCount + 1 # remove_faces() clean_unreferenced_vertices() return iCount
def get_dihedral_cos_angle(vids1, vids2): fNormal1 = SimpleMath.get_face_normal((ModelData.dictVertices[vids1[0]], ModelData.dictVertices[vids1[1]], ModelData.dictVertices[vids1[2]])) fNormal2 = SimpleMath.get_face_normal((ModelData.dictVertices[vids2[0]], ModelData.dictVertices[vids2[1]], ModelData.dictVertices[vids2[2]])) return SimpleMath.dot_product_3(fNormal1, fNormal2)
def constraint_3(fid): #Get the normal of vertexList vertexList = ModelData.dictFaces[fid].get_vids() curNormal = SimpleMath.get_face_normal((ModelData.dictVertices[vertexList[0]], ModelData.dictVertices[vertexList[1]], ModelData.dictVertices[vertexList[2]])) if SimpleMath.vector_length_3(curNormal) > SimpleMath.Tol: #the list of lists of bounded faces listBoundedFaceGroup = [] #all the visited faces listAllVisitedFids = [] #the seed faces listSeedFace = [] #the previously visited faces listLastVisitedFace = [] #the Unbounded faces listUnboundedFaces = [] while (fid >= 0): listAllVisitedFids.append(fid) #note: False should be not be modified to not if False == boundary_of_coplaner_neighbors(fid, curNormal, listAllVisitedFids, listUnboundedFaces, listSeedFace): #extracted the unbounded faces for f in listAllVisitedFids: if f not in listLastVisitedFace: listUnboundedFaces.append(f) # for f in listAllVisitedFids: if f not in listLastVisitedFace: listLastVisitedFace.append(f) else: #extracted the bounded faces fGrouped = [] for f in listAllVisitedFids: if f not in listLastVisitedFace: fGrouped.append(f) listBoundedFaceGroup.append(fGrouped) # for f in listAllVisitedFids: if f not in listLastVisitedFace: listLastVisitedFace.append(f) # for f in listSeedFace: if f in listLastVisitedFace: listSeedFace.remove(f) # if len(listSeedFace) > 0: fid = listSeedFace.pop(0) else: fid = -1 #check the outer neigbour faces if fid != -1: vertexList = ModelData.dictFaces[fid].get_vids() curNormal = SimpleMath.get_face_normal((ModelData.dictVertices[vertexList[0]], ModelData.dictVertices[vertexList[1]], ModelData.dictVertices[vertexList[2]])) if len(listBoundedFaceGroup) > 1: #TODO: find the nesting order of groups #now keep them all listKeepFace = [] for iGroup in listBoundedFaceGroup: listKeepFace += iGroup #reporder the group by nesting order #listFaceGroup = sort_facesgroup_by_size(listFaceGroup) ##extact the faces to be kept #listKeepFace = [] #if len(listFaceGroup) % 2 == 0: # #the odd groups should be kept # listFaceGroup = listFaceGroup[1::2] # for iGroup in listFaceGroup: # listKeepFace += listFaceGroup[iGroup] #else: # #the even groups should be kept # listFaceGroup = listFaceGroup[0::2] # for iGroup in listFaceGroup: # listKeepFace += listFaceGroup[iGroup] #keep all the tetrahedra return True, listKeepFace, listUnboundedFaces elif len(listBoundedFaceGroup) == 1: #keep all the tetrahedra return True, listBoundedFaceGroup[0], listUnboundedFaces else: return False, [], listUnboundedFaces else: print ('Degeneracy!') return False, [], []