Beispiel #1
0
 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))
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
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')
Beispiel #5
0
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
Beispiel #6
0
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, [], []
Beispiel #7
0
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