在PowerBI中提取IFC文件中的数据

news2024/12/25 9:33:44

在这里插入图片描述

推荐:用 NSDT编辑器 快速搭建可编程3D场景

在这篇文章中,我将逐步介绍从IFC文件中提取数据以创建 Shift IFC4PowerBI 函数的步骤。通过了解此工作流程,你能够更轻松地将 IFC 数据合并到自己的流程中。

在本文中,我们将重点关注文件中的元数据,但你也可以应用相同的逻辑来提取几何图形。 当然你也可以利用 NSDT 3DConvert这个强大的在线工具预览IFC几何模型(企业版可查看IFC属性数据并提供API)或者将IFC文件转换为GLTF、OBJ、STL等其他3D格式,而无需安装任何本地文件:

在这里插入图片描述

1、文件格式

关于 IFC 文件,首先要了解的是它们是文本文件,非常长且复杂的文本文件,但仍然是文本文件。 从数据的角度来看,这非常好,因为你通常会在建筑业遇到几种类型的本机文件:

  • 基于文本的文件,例如 IFC 和 P6 XML
  • 数据库文件,例如 Asta Powerproject 文件
  • 二进制文件,例如 Revit 或 DWG

可以使用标准工具读取文本和数据库文件,并将其引入 PowerBI 等工具或合并到数据工作流程中,而二进制文件通常只能由其源工具或其他经过认证的工具进行解释。 这使得基于文本的文件格式成为长期存储的绝佳解决方案,因为我们不依赖特定的软件来稍后查询数据。 Microsoft 的免费 VSCode 是我打开文本文件的首选工具,但你始终可以使用记事本、notepadd++ 或任何其他工具。 下面可以看到Github 上的一个 IFC 文件部分的屏幕截图:

在这里插入图片描述

使用 IFC 语法插件在 VSCode 中打开 IFC 文件

IFC 文件以 EXPRESS 结构编写,该结构涉及一大堆使用行号相互引用的行。 有一些与该文件相关的序言,但数据的主要内容是 DATA;行之后的所有内容。

2、处理 IFC

第一步是使用以下 PowerQuery 将数据从简单行转换为 PowerBI 中的智能表:

let
Source = Table.FromColumns({Lines.FromBinary(#"IFC Binary", null, null, 1252)}),
      // Split by Equal Sign
      SplitByEquals = Table.SplitColumn(
        Source, 
        "Column1", 
        Splitter.SplitTextByEachDelimiter({"="}, QuoteStyle.Csv, false), 
        {"Element ID", "Values"}
      ), 
      // Replace Single Quotes
      ReplaceSingleQuotes = Table.ReplaceValue(
        SplitByEquals, 
        "'", 
        """", 
        Replacer.ReplaceText, 
        {"Values"}
      ), 
      // Trim Text
      TrimValues = Table.TransformColumns(
        ReplaceSingleQuotes, 
        {{"Values", Text.Trim, type text}, {"Element ID", Text.Trim, type text}}
      ), 
      // Filter Non-null Rows
      FilterNonNullValues = Table.SelectRows(TrimValues, each ([Values] <> null)), 
      // Split by Open Parenthesis
      SplitByOpenParenthesis = Table.SplitColumn(
        FilterNonNullValues, 
        "Values", 
        Splitter.SplitTextByEachDelimiter({"("}, QuoteStyle.None, false), 
        {"Category", "Values"}
      ), 
      // Extract Data Before Close Parenthesis
      ExtractBeforeCloseParenthesis = Table.TransformColumns(
        SplitByOpenParenthesis, 
        {{"Values", each Text.BeforeDelimiter(_, ")", {0, RelativePosition.FromEnd}), type text}}
      )

采取的基本步骤是:

  • 加载 IFC 文件
  • 使用 =符号作为分隔符分割每一行。 在此步骤中,包含 QuoteStyle.csv参数非常重要,以确保忽略行实际值中包含的任何 =。 这为我们提供了一列包含行号的列和一列包含该行内容的列。
  • 将单引号替换为双引号,因为 PowerBI 理解引号的方式有点奇怪,这有助于我们稍后拆分数据。
  • 修剪值可以帮助我们删除前导或尾随空格,以保持一切整洁。
  • 过滤掉空值以可靠地删除与行数据无关的任何内容,你可以选择单独处理此标题数据。
  • 从值字段中删除前括号和尾括号。

现在我们有一个可爱的干净数据集,显示行号、数据类别和该类别中的数据值。

在这里插入图片描述

由于我们希望以最有效的方式处理该文件,因此我们将稍微改变一下数据。
在这里插入图片描述

IFC 数据结构的非常简单的近似

由于 IFC 数据使用一对多方法,这意味着相同的参数可以应用于多个父项,因此从参数开始并返回到几何元素更有意义,而不是循环遍历每个元素并多次重新处理相同的参数。

// Filtering & Transformation for IFCPROPERTYSINGLEVALUE
      FilterSingleValue = Table.SelectRows(
        ExtractBeforeCloseParenthesis, 
        each ([Category] = "IFCPROPERTYSINGLEVALUE")
      ), 
      SplitSingleValueDetails = Table.SplitColumn(
        FilterSingleValue, 
        "Values", 
        Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), 
        {"Property Name", "Property Description", "Property Value", "Property Unit"}
      ), 
      ExtractSingleValue = Table.TransformColumns(
        SplitSingleValueDetails, 
        {{"Property Value", each Text.BetweenDelimiters(_, "(", ")"), type text}}
      ), 

因此,我们将首先过滤所有 IFCPROPERTYSINGLEVALUE 行,然后从那里开始:

  • 用逗号分割值(记住之前的 QuoteStyle.csv)以获取属性名称、说明、值和度量单位。
  • 从“属性值”列中提取值,目前我们不担心值类型,但我们可能会在将来的版本中返回并检索它以帮助自动计算。

这给我们留下了一组很好的属性:
在这里插入图片描述

PowerBI 的有趣之处在于,我们现在可以一路回到第一步并从那里继续,将该表保留在内存中并稍后调用。 因此,接下来我们对 IFCPROPERTYSET 值执行相同的操作,最后合并到 IFCPROPERTYSINGLEVALUE 表中:

// Filtering & Transformation for IFCPROPERTYSET
      FilterPropertySet = Table.SelectRows(
        ExtractBeforeCloseParenthesis, 
        each [Category] = "IFCPROPERTYSET"
      ), 
      ExtractPropertyID = Table.AddColumn(
        FilterPropertySet, 
        "Property ID", 
        each Text.BetweenDelimiters([Values], "(", ")"), 
        type text
      ), 
      ExtractPsetName = Table.TransformColumns(
        ExtractPropertyID, 
        {{"Values", each Text.BetweenDelimiters(_, ",", ",", 1, 0), type text}}
      ), 
      RemoveQuotes = Table.ReplaceValue(ExtractPsetName, """", "", Replacer.ReplaceText, {"Values"}), 
      ExpandPropertyID = Table.ExpandListColumn(
        Table.TransformColumns(
          RemoveQuotes, 
          {
            {
              "Property ID", 
              Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), 
              let
                itemType = (type nullable text) meta [Serialized.Text = true]
              in
                type {itemType}
            }
          }
        ), 
        "Property ID"
      ), 
      RenamePsetColumns = Table.RenameColumns(ExpandPropertyID, {{"Values", "Pset Name"}}), 
      JoinSingleValueAndPset = Table.NestedJoin(
        RenamePsetColumns, 
        {"Property ID"}, 
        ExtractSingleValue, 
        {"Element ID"}, 
        "Properties", 
        JoinKind.LeftOuter
      ), 
      ExpandProperties = Table.ExpandTableColumn(
        JoinSingleValueAndPset, 
        "Properties", 
        {"Property Name", "Property Value"}, 
        {"Property Name", "Property Value"}
      ),

然后我们再做两次同样的事情,一直回到 IFCBUILDINGELEMENT和他们所有的子节点。

      // Filtering & Transformation for IFCRELDEFINESBYPROPERTIES
      FilterRelDefines = Table.SelectRows(
        ExtractBeforeCloseParenthesis, 
        each [Category] = "IFCRELDEFINESBYPROPERTIES"
      ), 
      ExtractObjectID = Table.AddColumn(
        FilterRelDefines, 
        "Object ID", 
        each Text.BetweenDelimiters([Values], "(", ")", {0, RelativePosition.FromEnd}, 0), 
        type text
      ), 
      ExtractPsetID = Table.TransformColumns(
        ExtractObjectID, 
        {{"Values", each Text.AfterDelimiter(_, ",", {0, RelativePosition.FromEnd}), type text}}
      ), 
      RenameForRelDefines = Table.RenameColumns(ExtractPsetID, {{"Values", "Pset ID"}}), 
      ExpandObjectID = Table.ExpandListColumn(
        Table.TransformColumns(
          RenameForRelDefines, 
          {
            {
              "Object ID", 
              Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), 
              let
                itemType = (type nullable text) meta [Serialized.Text = true]
              in
                type {itemType}
            }
          }
        ), 
        "Object ID"
      ), 
      JoinRelDefinesAndPset = Table.NestedJoin(
        ExpandObjectID, 
        {"Pset ID"}, 
        ExpandProperties, 
        {"Element ID"}, 
        "Property Sets", 
        JoinKind.LeftOuter
      ), 
      ExpandPropertySets = Table.ExpandTableColumn(
        JoinRelDefinesAndPset, 
        "Property Sets", 
        {"Pset Name", "Property Name", "Property Value"}, 
        {"Pset Name", "Property Name", "Property Value"}
      ), 
      // Final Join and Expansion
      JoinMain = Table.NestedJoin(
        ExpandPropertySets, 
        {"Object ID"}, 
        ExtractBeforeCloseParenthesis, 
        {"Element ID"}, 
        "Model", 
        JoinKind.LeftOuter
      ), 
      ExpandModel = Table.ExpandTableColumn(
        JoinMain, 
        "Model", 
        {"Category", "Values"}, 
        {"Ifc Type", "Values"}
      ), 
      FinalSplit = Table.SplitColumn(
        ExpandModel, 
        "Values", 
        Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), 
        {"GUID"}
      )
    in
      FinalSplit

剩下的最终表是每个属性引用其所有父项,一直到 IFC 元素的 IFCGUID。

在这里插入图片描述

此时,你可能想知道为什么我们有一个很长的属性列表,而不是每个项目单独一行,并在列中包含各种参数。 有几个原因:

  • 它可能会导致无限数量的列,具体取决于 IFC 文件
  • 不能再将属性集合并到数据集中
  • 过滤和利用仪表板内的数据要容易得多

发布项目涉及的最后一件事是使用 PowerBI 中的 let指令将其转换为函数:

let
    Source = (#"IFC File" as any) => let

      // REST OF THE CODE GOES HERE
    in
      FinalSplit
in
    Source

原文链接:PowerBI提取IFC数据 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1120256.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Reparameterization trick(重参数化技巧)

“Reparameterization trick”&#xff08;重参数化技巧&#xff09;是一种在训练生成模型中处理随机性潜在变量的方法&#xff0c;特别常见于变分自动编码器&#xff08;VAE&#xff09;等模型中。这个技巧的目的是使模型可微分&#xff08;differentiable&#xff09;&#x…

【源码】C++坦克大战源码

文章目录 题目介绍你收到的所有文件源码效果展示报告内容 题目介绍 代码量&#xff1a;1450 语言&#xff1a;C 你收到的所有文件 其中一个是devc版本&#xff0c;也可以用visual stdio 运行。 源码效果展示 typedef struct //这里的出现次序指的是一个AI_ta…

使用CountdownLatch和线程池批量处理http请求,并处理响应数据

背景和问题 ​ 背景&#xff1a;最近项目的一个接口数据&#xff0c;需要去请求其他多个服务器的数据&#xff0c;然后统一返回&#xff1b; 问题点&#xff1a;如果遍历所有的服务器地址&#xff0c;然后串行请求就会出现请求时间过长&#xff0c;加入需要请求十个服务器&…

Xray联动crawlergo自动扫描漏洞教程

xray和crawlergo联动 xray下载: https://github.com/chaitin/xray/releases crawlergo下载:360-crawlergo&#xff1a; github&#xff1a;https://github.com/Qianlitp/crawlergo/releases 联动脚本&#xff1a; github&#xff1a;https://github.com/timwhitez/crawlergo_x_…

Qt扫盲-QColor 理论使用总结

QColor 理论使用总结 一、概述1. 构造函数2. 合法性校验3. 组成值检索 二、整数与浮点精度三、Alpha-Blended Alpha混合图四、预定义颜色五、扩展的RGB颜色模型六、HSV颜色模型七、HSL颜色模型八、CMYK颜色模型 一、概述 QColor 是Qt里面描绘颜色的一个属性类&#xff0c;这个…

【算法练习Day25】 重新安排行程N 皇后 解数独

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 重新安排行程N 皇后解数独总…

图论05-【无权无向】-图的广度优先BFS遍历-路径问题/检测环/二分图/最短路径问题

文章目录 1. 代码仓库2. 单源路径2.1 思路2.2 主要代码 3. 所有点对路径3.1 思路3.2 主要代码 4. 联通分量5. 环检测5.1 思路5.2 主要代码 6. 二分图检测6.1 思路6.2 主要代码6.2.1 遍历每个联通分量6.2.2 判断相邻两点的颜色是否一致 7. 最短路径问题7.1 思路7.2 代码 1. 代码…

使用 Visual Studio Code (VS Code) 作为 Visual C++ 6.0 (VC6) 的编辑器

使用 Visual Studio Code (VS Code) 作为 Visual C 6.0 (VC6) 的编辑器 由于一些众所周知的原因&#xff0c;我们不得不使用经典&#xff08;过时&#xff09;的比我们年龄还大的已有 25 年历史的 VC 6.0 来学习 C 语言。而对于现在来说&#xff0c;这个经典的 IDE 过于简陋&a…

python:红狐优化算法(Red fox optimization,RFO)求解23个基本函数

一、红狐优化算法 红狐优化算法&#xff08;Red fox optimization&#xff0c;RFO&#xff09;由Dawid Połap和 Marcin Woźniak于2021年提出&#xff0c;该算法模拟了红狐的狩猎行为&#xff0c;具有收敛速度快&#xff0c;寻优精度高等优势。 参考文献&#xff1a; Poap D …

华为OD技术面试-最短距离矩阵(动态规划、广度优先)

背景 记录2023-10-21 晚华为OD三面的手撕代码题&#xff0c;当时没做出来&#xff0c;给面试官说了我的想法&#xff0c;评价&#xff1a;解法复杂了&#xff0c;只是简单的动态规范 或 广度优先算法&#xff0c;事后找资料记录实现方式。 题目 腐烂的橘子 问题描述&#xff…

【项目实战】从零开始设计并实现一个接口异常链路分析器

这不是马上要到1024了吗&#xff0c;这不得弄个什么工具给部门项目提提效&#x1f62f;&#xff1f; 1. 背景 在我们服务端应用当中&#xff0c;我们往往会要求更高的性能和更高的稳定性&#xff0c;但实际开发的过程中&#xff0c;可能会出现很多赶时间的情况&#xff08;也…

RustDay06------Exercise[91-100]

91.将指针还原成指定类型 因为指针不知道里面具体有什么,所以一般约定打上unsafe 申明开发者自己对该部分可用性负责,且在调试的时候也能起强调作用 // tests6.rs // // In this example we take a shallow dive into the Rust standard librarys // unsafe functions. Fix …

大疆智图(PC):新一代高效率高精度摄影测量软件

大疆智图是一款以二维正射影像与三维模型重建为主的软件&#xff0c;同时提供二维多光谱重建、激光雷达点云处理、精细化巡检等功能。它能够将无人机采集的数据可视化&#xff0c;实时生成高精度、高质量三维模型&#xff0c;满足事故现场、工程监测、电力巡线等场景的展示与精…

42914-2023 铝合金产品断裂韧度试验方法

1 范围 本文件描述了铝合金产品断裂韧度的试验方法。 本文件适用于铝合金轧制板材、挤压棒材、挤压板材、挤压管材、挤压型材和锻件产品的平面应变断 裂韧度和平面应力断裂韧度的测定。 2 规范性引用文件 下列文件中的内容通过文中的规范性引用而构成本文件必不可少的条款…

Bootstrap的卡片组件相关知识

Bootstrap的卡片组件 01-卡片介绍及常用场合 Bootstrap的卡片组件&#xff08;Card&#xff09;是一种常用的UI元素&#xff0c;或者也可称为一种常用的结构&#xff0c;用于呈现信息和内容&#xff0c;通常在网页和应用程序中用于以下情况&#xff1a; 博客文章和新闻文章&a…

Linux自有服务与软件包管理

服务是一些特定的进程&#xff0c;自有服务就是系统开机后就自动运行的一些进程&#xff0c;一旦客户发出请求&#xff0c;这些进程就自动为他们提供服务&#xff0c;windows系统中&#xff0c;把这些自动运行的进程&#xff0c;称为"服务" 举例&#xff1a;当我们使…

经管博士科研基础【27】如何判断正定矩阵或者负定矩阵?

在【26】一章中,我们学习到可以通过判断海塞矩阵是正定矩阵或负定矩阵来判断函数的极值问题,为此,我们今天就回顾一下怎么判断海塞矩阵或者说任意一个矩阵是一个正定矩阵或者负定矩阵。 一、正定矩阵的定义 其实,我们可以看到上面的任意非零向量x可以更换为“单位向量”。…

多继承的实例介绍

一、多继承同名覆盖 子类中的成员与父类中的成员同名问题&#xff0c;通过作用域分辨符&#xff08;&#xff1a;&#xff1a;&#xff09;进行限定类的访问&#xff0c;从而实现对不同类中的同名成员各自赋值。 #include<iostream> using namespace std; class A{//父…

一起学数据结构(10)——排序

从本文开始&#xff0c;通过若干篇文章展开对于数据结构中——排序的介绍。 1. 排序的概念&#xff1a; 将一堆杂乱无章的数据&#xff0c;通过一定的规律顺序排列起来。即将一个无序序列排列成一个有序序&#xff08;由小到大或者由大到小&#xff09;的运算。 在数据的排序中…

小微企业需要认定吗?怎么认定?

小微企业在方便人民群众生活&#xff0c;解决就业&#xff0c;活跃市场经济方面发挥了巨大作用。我国对小微企业也有相应的划分标准和税收优惠政策&#xff0c;那么小微企业需要认定吗&#xff1f;认定小微企业需要哪些资料&#xff1f;下面玖邀开业小编给大家做一个简单说明。…