如何使 Forge Data Visualization 扩展与 IFC 文件一起使用?

Posted

技术标签:

【中文标题】如何使 Forge Data Visualization 扩展与 IFC 文件一起使用?【英文标题】:How to make the Forge Data Visualization extension work with IFC files? 【发布时间】:2021-07-21 21:38:01 【问题描述】:

我遵循了 Forge 数据可视化扩展文档中的教程:https://forge.autodesk.com/en/docs/dataviz/v1/developers_guide/quickstart/ 在 IFC 文件上,一切似乎都正常,除了房间的颜色,如下图所示,而不是被着色。

我还在 Revit 文件上进行了测试,房间颜色正确,所以这个问题是 IFC 文件特有的。

问题是 IFC 文件出现这种行为的原因可能是什么,我该如何解决?

编辑:解决方案在已接受帖子的 cmets 中。

【问题讨论】:

抱歉回复晚了。您能否考虑为我们的调查提供一个展示此问题的非机密可重现案例并将其发送至forge[DOT]help[AT]autodesk[DOT]com?非机密可再现案例包含非机密可再现 IFC 模型和最小查看器应用程序,其中包含用于测试此问题的代码。 更新我的回复,请看下面???? 【参考方案1】:

抱歉回复晚了。经过一番搜索,我设法重现了与您类似的行为,并找到了解决方案。

就我而言,我传递给DataVisualization#registerSurfaceShadingColors、DataVisualization#renderSurfaceShading 的sensorType 值以及levelRoomMap 中由this tutorial 手动创建的设备的sensorType 没有使用相同的字符大小写。例如,温度与temperature。修复字符大小写问题后,我的热图按预期重新绘制。这是快照:

这是我的代码 sn-p 供您参考:

async function getBoxAsync(dbId) 
    return new Promise((resolve, reject) => 
        const tree = viewer.model.getInstanceTree();
        const frags = viewer.model.getFragmentList();
        tree.enumNodeFragments(dbId, function(fragid) 
            let bounds = new THREE.Box3();
            frags.getWorldBounds(fragid, bounds);
            return resolve(bounds);
        , true);
    );


function getLevel(box) 
    const floors = viewer.getExtension("Autodesk.AEC.LevelsExtension").floorSelector.floorData;
    const currentElevation = box.min.z;

    if (currentElevation < floors[0].zMin) 
        return floors[0];
     else if (currentElevation > floors[floors.length - 1].zMax) 
        return floors[floors.length - 1];
     else 
        return floors.find(f => f.zMin <= currentElevation && f.zMax >= currentElevation );
    


async function getPropAsync(dbId) 
    return new Promise((resolve, reject) => 
        viewer.getProperties(dbId, result => resolve(result));
    );


async function getRoomName(dbId) 
    const result = await getPropAsync(dbId);
    const nameProp = result.properties.find(p => p.attributeName === 'lcldrevit_parameter_Pset_ProductRequirements_tab:lcldrevit_parameter_Name(Pset_ProductRequirements)_PG_IFC');

    return nameProp.displayValue;


async function getRoomDbIds() 
    return new Promise((resolve, reject) => 
        viewer.search( 'Rooms', resolve, reject, ['lcldrevit_parameter_Pset_SpaceCommon_tab:lcldrevit_parameter_Category(Pset_SpaceCommon)_PG_IFC'])
    );


async function buildRoomMap() 
    const dbIds = await getRoomDbIds();
    const DataVizCore = Autodesk.DataVisualization.Core;
    let levelRoomsMap = new DataVizCore.LevelRoomsMap();


    for ( let i = dbIds.length - 1; i >= 0; i-- ) 
        const dbId = dbIds[i];
        const box = await getBoxAsync( dbId );
        const level = getLevel( box );
        const name = await getRoomName( dbId );

        let room = new DataVizCore.Room(
            dbId, //Room's DbId
            name,
            box
        );

        levelRoomsMap.addRoomToLevel(level.name, room);
    

    return levelRoomsMap;


async function initHeatmap() 
    const DataVizCore = Autodesk.DataVisualization.Core;
    const dataVizExtn = viewer.getExtension('Autodesk.DataVisualization');
    const levelRoomsMap = await buildRoomMap();
    const devices = [];

    for(let lvl in levelRoomsMap) 
        const rooms = levelRoomsMap[lvl];
        for (let i = rooms.length - 1; i >= 0; i--) 
            const room = rooms[i];
            const center = room.bounds.center();
            const device = 
                id: `$room.name Device`, // An ID to identify this device
                position: center, // World coordinates of this device
                sensorTypes: ["temperature"], // The types/properties this device exposes
            

            devices.push(device);
            room.addDevice(device);
        
    

    const structureInfo = new DataVizCore.ModelStructureInfo(viewer.model);
    let shadingData = await structureInfo.generateSurfaceShadingData(devices, levelRoomsMap);

    await dataVizExtn.setupSurfaceShading(viewer.model, shadingData);

    // Set heatmap colors for temperature
    dataVizExtn.registerSurfaceShadingColors("temperature", [0x00ff00, 0xff0000]);

    function getSensorValue() 
        return Math.random(); // Your random function ?
    

    // Generate the heatmap graphics (do this one time, this is heavier)
    dataVizExtn.renderSurfaceShading(Object.keys(levelRoomsMap), "temperature", getSensorValue);
    // Do this as many times as you want (this is lightweight)
    dataVizExtn.updateSurfaceShading(getSensorValue);

    viewer.getExtension("Autodesk.AEC.LevelsExtension").floorSelector.selectFloor(0);


await initHeatmap();

【讨论】:

您好,抱歉这么晚才回复,今天才来得及测试一下。所以我尝试了你的建议,但是改变 sensorType 的大小写并没有解决问题。然后我想试试你的代码。我对其进行了调整并对“Autodesk.AEC.LevelsExtension”的加载以及房间 dbid 和名称的过滤条件进行了一些更改,但它仍然以与以前相同的方式“着色”房间。我正在使用的 ifc 文件可能是问题所在吗?你使用的文件是公开的,所以我可以测试它以供参考? 也许,但如果不查看文件,我不能说它们是相似的。您能否考虑向forge[dot]help[at]autodesk[dot]com 提供一个非机密的可重现 IFC 模型?我会在那里接你,或者你可以在这里测试我的模型:autode.sk/3uHFojc 很遗憾,我没有要分享的非机密 IFC 模型,因此我尝试了您提供的模型,但遇到了与我的模型相同的问题。我还注意到,在选择模型浏览器时,我只有 5531 个元素,而上图中的 6110 个元素。此外,我的元素没有您用于过滤的此属性:“lcldrevit_parameter_Pset_SpaceCommon_tab:lcldrevit_parameter_Category(Pset_SpaceCommon)_PG_IFC”。这两个差异是否与问题有关? 您使用的是哪个 IFC 管道?如果您的模型中没有 lcldrevit_parameter_Pset_SpaceCommon_tab:lcldrevit_parameter_Category(Pset_SpaceCommon)_PG_IFC 属性,您可以在使用 viewer.getProperties 查询属性时尝试将其替换为其值为 Rooms 的正确属性。 最终问题确实出在 IFC 管道上。我使用的是旧管道而不是现代管道。在转换过程中更改该参数并添加 spaces: show 参数后,模型会按预期呈现颜色。以下是有关参数的更多详细信息:forge.autodesk.com/en/docs/model-derivative/v2/reference/http/…

以上是关于如何使 Forge Data Visualization 扩展与 IFC 文件一起使用?的主要内容,如果未能解决你的问题,请参考以下文章