3dtiles getFloorsNodes9.py

本文介绍了一种从BIM模型中提取分层数据的方法,通过解析sceneTree.json文件,能够获取各楼层节点信息及子节点ID,并将数据整理为易于处理的格式。
"""
代码前提:            
此模块用于,获取指定目录下的所有scenetree.json文件,并生成分层数据,
最后一级子目录下,只有一个scenetree.json文件。

启动代码:
1.
python getFloorsNodes9.py


1.
获取BIM模型的sceneTree.json文件的每一分层的所有节点名及其子节点id,
并写到文件(sceneTree.json目录/floorsNodes/下)。
每一个文件名是分层名,文件内容包含分层名及其子节点id,文件格式是json格式。
文件数据结构类似这样:
{"floorName": "-0.45", "childrenNodesIds": {"289": 0, "13381": 0, "5893179": 0, "40908": 0, "5985307": 0, "68078": 0, "6078149": 0}}

2.
获取所有分层的名字写到文件floorsNames.json。
文件数据结构类似这样:
{"floorsNames": ["-0.45", "室外地坪", "1F", "2F", "3F", "4F", "5F", "6F", "7F", "8F", "9F", "10F", "11F", "12F", "13F", "14F", "15F", "16F", "17F", "18F", "19F", "20F", "RF", "86.9", "88"]}
"""
from pprint import pprint
import json
import os


def readWriteJSONFile(pathFile):
    """
    此函数用于,处理一个json文件,把文件中的所有单引号替换成双引号。
    """
    with open(pathFile, "r", encoding="utf-8") as f:
        floorsNames = f.read()
    # print(floorsNames)
    floorsNames = floorsNames.replace("'", "\"")
    # print(floorsNames)
    with open(pathFile, "w", encoding="utf-8") as f:
        f.write(floorsNames)


def get_abs_paths(directory, totalPathFiles=[]):
    """
    此函数旨在获取directory目录下,所有文件的绝对路径,
    并放在totalPathFiles里。
    directory下可以同时有目录和文件。
    totalPathFiles列表只在函数初始化时创建,分配固定起始地址的存储空间。
    """
    FFs = os.listdir(directory)
    # print(FFs)
    for f in FFs:
        totalPathFile = os.path.join(directory, f)
        if os.path.isfile(totalPathFile):
            # print(totalPathFile)
            totalPathFiles.append(totalPathFile)
        else:
            get_abs_paths(totalPathFile, totalPathFiles)
    return totalPathFiles


def mkdirs(path):
    # 去除首位空格
    path = path.strip()
    # 去除尾部 \ 符号
    path = path.rstrip("\\")
    # 判断路径是否存在
    # 存在     True
    # 不存在   False
    isExists = os.path.exists(path)
    # 判断结果
    if not isExists:
        # 如果不存在则创建目录
        # 创建目录操作函数
        os.makedirs(path)
        # print(path+' 创建成功')
        return True
    else:
        # 如果目录存在则不创建,并提示目录已存在
        print(path + ' 目录已存在')
        return False


def writeFloor_NodesToFile(floorData, currentDirectory):
    """
    此函数用于,把分层节点及其子节点id写到文件,文件名是分层名。
    """
    # print(floorData['floorName'])
    # mkdirs(currentDirectory + "\\floorsNodes")
    with open(currentDirectory + "\\floorsNodes\\" + floorData['floorName'] + '.json', 'wb') as f:
        f.write(str(floorData).encode('utf-8'))


def getFloor_Nodes(floor, floorData):
    """
    此函数用于,获取一层的数据floorData。
    该数据包括该层的层名及其附属节点id。
    floorData数据结构类似这样:
    {'floorName': '-0.45', 'childrenNodesIds': {'289': 0, '13381': 0, '5893179': 0, '40908': 0, '5985307': 0, '68078': 0, '6078149': 0}}

    floor,是分层json对象,是全局变量children数组的成员,数据结构类似这样:
    {'children': [{'children': 0,
                   'id': 289,
                   'sphere': [0, 0, 0, 0],
                   'type': 'IfcAnnotation'},
                  {'children': [{'children': 0,
                                 'id': 13381,
                                 'name': '现场浇注楼梯:楼梯:373762 Run 1',
                                 'sphere': [-2177693.38667827,
                                            4388599.94903105,
                                            4070236.88168458,
                                            1.00933146190932],
                                 'type': 'IfcStairFlight'},
                                {'children': 0,
                                 'id': 5893179,
                                 'name': '栏杆扶手:1050mm 圆管:374422',
                                 'sphere': [-2177693.85827209,
                                            4388600.89941588,
                                            4070236.65854068,
                                            0.873587672398189],
                                 'type': 'IfcRailing'}],
                   'id': 13225,
                   'name': '现场浇注楼梯:楼梯:373762',
                   'sphere': [0, 0, 0, 0],
                   'type': 'IfcStair'},
                  {'children': [{'children': 0,
                                 'id': 40908,
                                 'name': '现场浇注楼梯:楼梯:385103 Run 1',
                                 'sphere': [-2177805.4527059,
                                            4388554.60290546,
                                            4070225.7275786,
                                            0.998299335119483],
                                 'type': 'IfcStairFlight'},
                                {'children': 0,
                                 'id': 5985307,
                                 'name': '栏杆扶手:1050mm 圆管:385106',
                                 'sphere': [-2177805.91150105,
                                            4388555.52749761,
                                            4070225.48051487,
                                            0.825957508837764],
                                 'type': 'IfcRailing'}],
                   'id': 40751,
                   'name': '现场浇注楼梯:楼梯:385103',
                   'sphere': [0, 0, 0, 0],
                   'type': 'IfcStair'},
                  {'children': [{'children': 0,
                                 'id': 68078,
                                 'name': '现场浇注楼梯:楼梯:386551 Run 1',
                                 'sphere': [-2177739.62261367,
                                            4388575.6897725,
                                            4070238.21308496,
                                            0.998299335119483],
                                 'type': 'IfcStairFlight'},
                                {'children': 0,
                                 'id': 6078149,
                                 'name': '栏杆扶手:1050mm 圆管:386554',
                                 'sphere': [-2177740.08140882,
                                            4388576.61436465,
                                            4070237.96602122,
                                            0.82595750883776],
                                 'type': 'IfcRailing'}],
                   'id': 67921,
                   'name': '现场浇注楼梯:楼梯:386551',
                   'sphere': [0, 0, 0, 0],
                   'type': 'IfcStair'}],
     'id': 115,
     'name': '-0.45',
     'sphere': [0, 0, 0, 0],
     'type': 'IfcBuildingStorey'}
    """
    for child in floor['children']:
        if child['children'] == 0:
            floorData['childrenNodesIds'][str(child['id'])] = 0
        else:
            getFloor_Nodes(child, floorData)
    floorData['floorName'] = floor['name']


def getFloors_Nodes(children, currentDirectory):
    """
    此函数用于,获取每一分层的数据,并写入文件。
    一个分层数据写到一个文件,文件名为分层名。
    文件内容类似这样:
    {'floorName': '-0.45', 'childrenNodesIds': {'289': 0, '13381': 0, '5893179': 0, '40908': 0, '5985307': 0, '68078': 0, '6078149': 0}}
    """
    mkdirs(currentDirectory + "\\floorsNodes")
    # 循环遍历所有的分层
    for child in children:
        # 每层清空一次floorData,以确保每一层都是自己层的数据。
        floorData = {'floorName': 0, 'childrenNodesIds': {}}
        # 把floorData作为参数传给函数,填充数据。
        # 此函数不用返回,因为floorData就是此处传入的,处理后直接使用即可。
        getFloor_Nodes(child, floorData)
        # print("floorData:", floorData)
        writeFloor_NodesToFile(floorData, currentDirectory)
        # break


def getAllFloorsNames_writeToFile(children, pathFile):
    """
    此函数用于,获取所有的分层名,并写到文件。
    children, 所有分层对象的数组。
    pathFile, 要写入文件的绝对路径。
    """
    floorsNames = {"floorsNames": []}
    for child in children:
        floorsNames["floorsNames"].append(child['name'])
    # print(floorsNames)
    # print(len(floorsNames["floorsNames"]))
    with open(pathFile, 'wb') as f:
        f.write(str(floorsNames).encode('utf-8'))
    readWriteJSONFile(pathFile)


def getChildren(sceneTreeDict):
    """
    此函数用于,获取scenetree.json文件的所有层对象的数组,并返回。
    sceneTreeDict,是scenetree.json文件的内容的字典形式。
    """
    # children = sceneTreeDict['children']
    # print(children[0]['name'])
    # print(children[0]['name'] == sceneTreeDict['name'])
    # print(sceneTreeDict['children'][0]['name'])

    if sceneTreeDict['children'][0]['name'] != sceneTreeDict['name']:
        # pprint(sceneTreeDict['children'][8])
        # print(type(sceneTreeDict['children']))
        # print(len(sceneTreeDict['children']))
        return sceneTreeDict['children']
    else:
        return getChildren(sceneTreeDict['children'][0])


def hanldeOneScenetreeFile(scenetreePathFile):
    """
    此函数用以处理一个scenetree.json文件,生成分层数据。
    scenetreeFilePath,一个scenetree.json文件的绝对路径,
    类似这样:
    'D:\\Gaoshengjie\\龙哥任务\\BIM分层\\小学\\南站九年一贯制学校风雨操场食堂模型0404\\楼板\\scenetree.json'
    """
    # 模型scenetree.json文件的绝对路径。
    # modelSceneTree = "scenetree.json"
    # 只处理scenetree.json文件。
    currentDirectory = '\\'.join(scenetreePathFile.split('\\')[:-1])
    # print("currentDirectory:", '\\'.join(scenetreePathFile.split('\\')[:-1]))
    if scenetreePathFile.split('\\')[-1] == 'scenetree.json':
        print(scenetreePathFile)
        # 读取该文件。
        with open(scenetreePathFile, "rb") as f:
            sceneTreeStr = f.read().decode("utf-8")
        # 把js对象null替换成0。以下可作为判断其是否有子节点的条件。
        sceneTreeStr2 = sceneTreeStr.replace('null', '0')
        # 把字符串对象转换成python的字典对象。
        sceneTreeDict = json.loads(sceneTreeStr2)
        # print(len(children))  # 25
        # len(children)就是层节点的个数。
        # 层节点下最后一级节点就是特性(feature)节点。
        # children,是一个数组,里边的每一个成员是一个json对象。该对象保存着该模型场景树的(可用来分层的)层节点及其子节点。
        # children = sceneTreeDict['children']
        # pprint(sceneTreeDict)
        # print(type(sceneTreeDict))
        children = getChildren(sceneTreeDict)
        # print(type(children))
        # print(len(children))
        # pprint(children[0])

        getAllFloorsNames_writeToFile(children, currentDirectory + "\\floorsNames.json")
        getFloors_Nodes(children, currentDirectory)

        # 以下要对directory目录下的json文件进行修改,把所有的单引号改成双引号。
        directory1 = currentDirectory + "\\floorsNodes"
        # print("directory1:", directory1)
        totalPathFiles = get_abs_paths(directory1, [])
        # print("totalPathFiles:", totalPathFiles)
        # print(len(totalPathFiles))
        print()
        for pathFile in totalPathFiles:
            # print(pathFile)
            readWriteJSONFile(pathFile)


def main(directory):
    """
    主函数。
    """
    # 以下要获取目标目录下所有的scenetree.json文件的绝对路径的列表。
    totalPathFiles = []
    get_abs_paths(directory, totalPathFiles)
    # print(totalPathFiles)
    # print(len(totalPathFiles))
    for scenetreePathFile in totalPathFiles:
        hanldeOneScenetreeFile(scenetreePathFile)
        # break


if __name__ == "__main__":
    # 要处理的scenetree.json文件的目录。
    directory = r"D:\Gaoshengjie\龙哥任务\BIM分层\小学"
    main(directory)
    print("done!")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值