IfcOpenShell正确设置几何体的坐标

36 篇文章 21 订阅

在之前的文章中,我们使用 IfcOpenShell (IOS) 读取 ifc 几何并将其转换为 brep。 当我们读取 wikilab.ifc文件时,一切似乎都是正确的,但真的如此吗?

当你在项目中使用 BIM 时,坐标始终是正确讨论的主题。 就此而言,我建议你阅读 Dion Moult 的文章 IFC Coordinate Reference Systems and Revit 以及文章中引用的参考资料。

本教程使用的 IfcOpenShell 版本:0.6.0a1,教程中的完整代码可以从这里下载。

1、IFC 中的Placement

几何体通常有自己的局部坐标系 (LCS)。 为什么 ?

以航站楼为例。 你经常在一个项目中使用几种类型的风道末端。 在每个空间中多次复制相同的航站楼几何形状。 如果你的几何图形是使用世界坐标系 (WCS) 定义的,则需要为每个几何体定义一个新几何图形。 如果你的几何图形在其自己的 LCS 中定义,则可以在任何地方使用相同的几何图形,并给出其相对于另一个参考的位置。

在 ifc 规范中,通风终端是 IfcAirTerminal (IFC4)IfcFlowTerminal (IFC2x3)。 两者都继承自IfcProduct(如墙、窗、管道等),它具有 IfcObjectPlacement 类型的 ObjectPlacement 属性。

ObjectPlacement属性描述产品在空间中的放置,放置可以是绝对的(相对于世界坐标系)、相对的(相对于另一个产品的对象放置)或约束(例如相对于网格轴)。 它由 IfcObjectPlacement 的各种子类型决定,其中包括用于确定对象坐标系变换的轴放置信息。 — IFC 文档中的ObjectPlacement属性定义
IfcLocalPlacement 子类型,我认为是最常见的,有 2 个属性:

  • #1 - IfcObjectPlacement 类型的 PlacementRelTo。 如果填充位置是相对的。 如果空放置使用 WCS。
  • #2 - RelativePlacement 基本上是一个 2D 或 3D 坐标。
    可以链接相对位置,例如: AirTerminal << space << buildingstorey << building << Site。 要检索相对于 WCS 的对象放置,需要通过完整链转换第一个相对放置。

2、IfcOpenShell 中的Placement

IfcOpenShell 可用作解析器以获取与 IfcSchema 中定义的完全相同的位置。 然而,它也有方便的工具来避免抓取整个相对放置链。 要了解这一点的选项是 USE_WORLD_COORDS :

/// Specifies whether to apply the local placements of building elements
/// directly to the coordinates of the representation mesh rather than
/// to represent the local placement in the 4x3 matrix, which will in that
/// case be the identity matrix.
USE_WORLD_COORDS = 1 << 1,

当你像我们在之前的文章中所做的那样显示几何体时,坐标是使用几何体的局部坐标系 给出的。 它不可见,因为我们的墙放置在坐标 0,0,0 处。 现在让我们使用来自 ifcopenshell academy 的脚本来生成一个放置在 20,10,3 的新墙。 默认情况下,脚本还会在 0,0,0 处生成一堵墙。 要修改它的相对位置,我们需要修改以下行:

wall_placement = create_ifclocalplacement(ifcfile, relative_to=storey_placement)

考虑到函数定义,我们需要将这一行替换为:

wall_placement = create_ifclocalplacement(ifcfile, point=(20., 10., 3.), relative_to=storey_placement)

现在,如果你尝试根据我们之前的脚本从这个新创建的 hello_wall.ifc 加载几何图形,将看到墙仍然位于 0,0,0,这是错误的。

在这里插入图片描述

为了正确放置它,我们有 2 个选项:使用矩阵变换和 USE_WORLD_COORDINATES 设置。

3、使用Placement矩阵

正如你在创建几何体时在其源代码中所述,它的位置由一个 4×3 矩阵给出。 但要注意,当显示为元组时,IfcOpenShell 矩阵和 FreeCAD 矩阵是转置的:

  • IfcOpenShell 矩阵值是 4 个连续向量的 xyz 的元组。格式 : (v1.x, v1.y, v1.z, v2.x, v2.y …, v4.z)
  • FreeCAD 矩阵构造函数最多占用 16 个浮点数。 按 x、y、z 值分组的 4 个向量。格式 : (v1.x, v2.x, v3.x, v4.x, v1.y, …, v4.z, 0, 0, 0, 1)

关于 FreeCAD 矩阵的最后 0、0、0、1。 正如 OpenGL 教程的矩阵章节中所述:

这很快就会变得更加清楚,但现在,请记住这一点:
如果 W == 1,则向量 (X,Y,Z,1) 是空间中的一个位置。
如果 W == 0,则向量 (X,Y,Z,0) 是一个方向。
(事实上 ,永远记住这一点。) - OpenGL Tutorial Matrices Chapter

所以我们将使用一个函数将 IfcOpenShell 矩阵转置为 FreeCAD 矩阵:

def ios_to_fc_matrix(ios_matrix):
    m_l = list()
    for i in range(3):
        line = list(ios_matrix[i::3])
        line[-1] *= SCALE
        m_l.extend(line)
    return FreeCAD.Matrix(*m_l)

在几何形状创建之后,我们调用它来设置对象的位置:

    # Create FreeCAD shape from Open Cascade BREP
    fc_shape = Part.Shape()
    fc_shape.importBrepFromString(occ_shape)
    
    # Ifc lenght internal unit : meter. FreeCAD internal unit : mm.
    fc_shape.scale(SCALE)
    # Shape scale must be applied before shape placement else placement scale would be doubled
    fc_shape.Placement = ios_shape_to_fc_placement(ios_shape)

这样我们就得到了正确放置的墙:
在这里插入图片描述

4、USE_WORLD_COORDINATES

定义设置仍然是相同的过程:

settings.set(settings.USE_WORLD_COORDS, True)

我们可以保留相同的代码库,因为它将应用不会改变任何内容的单位矩阵。 通过运行脚本,你将再次获得正确放置的墙,但这次位置仍然是 0, 0, 0,这意味着几何顶点坐标是用它们的绝对坐标定义的:

在这里插入图片描述

出于在第一部分中解释的原因,我倾向于说此解决方案不是 HVAC 领域中 CAD/BIM 工作的最佳选择。 目前 FreeCAD 以这种方式导入和导出 ifc 我将调查原因并可能在论坛上发布此主题。


原文链接:IfcOpenShell坐标问题 — BimAnt

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值