将带孔的多边形转换为多个简单的无孔多边形

2024-03-08

我正在处理IfcFace http://www.buildingsmart-tech.org/ifc/IFC4/Add2/html/schema/ifctopologyresource/lexical/ifcface.htm。我得到了一个带孔的简单多边形,我需要将其转换为多个不带孔的简单多边形,以便 CAD 进一步处理它。一个小演示图:

My best approach is to do a constrained delaunay triangulation and rejoin the triangles into bigger polygons. Like so: enter image description here But the delaunay triangulation and even more the constraining part tends to fail for difficult input because of floating point precision and algorithmic instabilities. My input sometimes generates triangles with height 1e-8 and base length 1.

是否有更好更稳健的算法来实现这种转换?


我认为形状的完整三角测量需要进行大量计算才能满足您的需求。而且三角剖分还给出了位于图形外部的三角形,甚至部分位于内部、部分位于外部的三角形,因此正确地重新组合它们也很复杂。

提案1

我想到了一种完全不同的方法。
是否真的需要将图形分成 2 个图形才能在 CAD 程序中使用?我希望如果您可以将其描述为一个循环中的一个图形(形成多边形的点列表),也可以。
您需要的是找到连接图形的不同循环并且完全位于图形内部的线,以便您可以使用它们来组合循环。

我将首先比较不同循环的成对段并搜索彼此最接近的段。 开始将外循环的所有段与所有内循环的所有段进行比较。
实际上,我将通过比较外循环上的点与内循环的段以及内循环上的点与外循环的段来实现它。如果 x 或 y 距离大于已找到的最小距离,我将通过跳过计算进行优化。
两条线段或彼此最接近的点和线段将为您提供一条线,可用于组合循环(或分割图形):从其中一个线段(或点)的角开始的线垂直于其他部分。缺点是您要添加新节点,但它很高效并且始终正确。
一旦找到这样的线,所连接的内循环和新线/段就可以合并到一个修改后的外循环中,其中包含新段两次以关闭新循环。您可以通过将修改后的外循环的段与其余其他内循环的段进行比较来重复该过程。
当使用所有内部循环时,您将拥有一个描述整个图形的循环。

要将图形完全分成 2 个图形,您将需要多一个额外的部分。
但我认为我们目前拥有的循环可以在大多数 CAD 软件中使用来表示您的图形。它不是标准化图形,因为它会触及自身,但 CAD 程序通常不关心这一点。它非常适合 CAD 程序来表示图形的表面。

如果您确实想将其完全分成 2 个数字,则可以通过搜索 2 个线段找到您需要的额外线,或者如果您将比较限制为分开的线段和点对,则可以更好地找到彼此最接近的点和线段。由循环的两个方向上所有已添加的段组成的循环。所有添加的段在循环中都会出现两次,因此新循环中始终会有 2 个部分被所有部分分隔开。

评论您对提案 1 的回答

我还没有权利评论你的答案,因为我没有足够的学分,所以我会将评论添加到我自己的答案中。

我正在看你的例子,我首先误解了它,所以我改编了这个评论。

您有 3 个洞,因此算法的第一部分将添加您显示的 3 个部分。

是的,您显然对算法的第二部分有一个问题案例。您需要第四条线,但在这种情况下,没有 2 个部分,它们被两个方向上所有 3 个添加的线段分隔开,否则我不会立即看到它们。
我假设新循环中始终有 2 个部分被所有新段分隔开。当有 3 个或更多孔时,该假设是错误的。

但我会进一步考虑。

建议2

我现在正在考虑另一种可能的算法。

  1. 计算图中每个孔的表面积。选取每个孔的一个角。

  2. 通过最小 2 个孔的选定角画一条线。
    可以是任意 2 个孔,但采用最小的孔可以增加用更少的线切割更多孔的机会。
    如果只剩下一个洞,只需在已有的一个点上画一条线即可。方向并不重要。我会选择通过所选点和定义孔的最近的其他点绘制线。

  3. 检测所绘制的线与图形的线段的所有交点,以将线减少为完全位于图形内部并连接图形的不同环的一组线段。省略在同一循环上开始结束的任何段。
    如果找到的线段仅在一个点接触到一个孔。将其中一个线段移动到同一个孔中最接近该点的点,以避免最终形成一个具有接触外部的孔的图形。 检查与修改后的路段是否有新的交叉点,如果发现则再次将其分割。
    查找所有交点需要将找到的线与图形的所有线段进行比较,这也需要大量计算,但您可以通过在计算交点之前检查线是否穿过线段周围的边界框来跳过计算。我将首先计算与外循环的交点,以便尽快为线的剩余部分提供边界框,因为这也可以帮助检查不需要比较交点的部分。
    您还可以通过将每个找到的线段替换为连接所连接线段的最近端点的线段(如果尚未位于 2 个线段的连接点中)来进行优化。这样做可以避免为新人物创建额外的点,并增加一步消除更多洞的机会。但随后您需要再次检查新的交叉点并重复此优化,直到找不到更多交叉点。
    还有一种可能的优化:检查尚未切割的孔中靠近找到的线段的点,并将找到的线段分成两段,以便在同一步骤中捕获该孔。就像之前的优化一样,这也需要再次检查新的交叉点。

  4. 使用线段将图形分成 2 个图形,并对每个仍然有孔的新图形重复步骤 2。

缺点是您最终可能会得到超过 2 个数字(最大 (n +1)/2 个数字,其中 n 是孔的数量),但如果您有很多孔导致许多数字,则可能会重新组合一些数字他们。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将带孔的多边形转换为多个简单的无孔多边形 的相关文章

随机推荐

  • 如何使用 php 在 XML 文件中进行搜索?

    不知道有没有办法在xml文件中搜索 例如 我想要得到Value使用Name from AttrList和产品代码 是否可以 这就是我的 xml 的样子
  • jQuery 将类添加到图像链接,而不会在链接传递变量时弄乱

    好的 所以我使用了一些 jquery 来选择所有 a 页面上的标签以及它们是否链接到图像文件以添加zoom出于灯箱的目的对其进行类处理 这是有效的代码 document ready function a href png a href gi
  • List<>.IndexOf 是按引用还是按值进行比较?

    List
  • ant+cpptasks 与 scons 与 make

    我正在调查scons http www scons org 我只是想确保在我将大量脑细胞投入到完全不同的事物之前我知道替代方案是什么 我过去一直在使用 GNU make 但从来没有对它感到特别满意 特别是 为什么 Ant 没有更频繁地用于
  • 使用固定装置返回值作为 mark.parametrize() 中的值

    我的问题是 是否可以使用夹具的返回值作为参数化中的值 问题是 我想动态获取参数化的可能值 例如 虚拟服务器上的可用系统 当其中一个设备创建虚拟服务器时 我可以访问这些 测试看起来像这样 伪代码 conftest py pytest fixt
  • iOS 7:自定义容器视图控制器和内容插入

    我有一个封装在导航控制器中的表视图控制器 当通过以下方式呈现时 导航控制器似乎会自动将正确的内容插入应用到表视图控制器presentViewController animated completion 谁能向我解释一下它到底是如何工作的 但
  • Paypal 结帐中无法访问 iframe 元素 id 的异常处理

    我有一个电子商务网站 当我尝试下订单时 它会重定向到 Paypal 页面 当我以 Paypal 用户身份登录时 它会重定向到另一个结账屏幕 我在其中尝试使用 selenium Web 驱动程序进行自动化 在此步骤中 出现以下异常 我尝试使用
  • 如何在数据库中保存跟踪折线?

    我创建了一个功能 可以跟踪用户的路线并创建折线 我一直在尝试将其保存到 Firebase 路线 ID 路线名称 纬度 经度 我使用的方法是 每次位置更改时 用户的新纬度和经度都会保存到 Firebase 用户设置的路线名称和 当前 静态路线
  • 在 Play Slick 中分配动态注入的数据库名称

    我有以下 Play Slick DAO 课程 注意数据库配置是一个常量control0001 DAO 有一个功能readUser根据用户 ID 读取用户 class UsersDAO Inject NamedDatabase control
  • Angular 5 HttpClient 与之前的 Http 相比有哪些优势?

    我阅读了官方升级指南 上面写着 因为 HttpClient 得到广泛采用 我们决定 但是这个 HttpClient 带来的真正好处是什么 我正在考虑尝试一下 但中途感到困惑 因为我不知道升级后这些需要发生什么 从 angular http
  • 使用 nginx 的子目录中的 CakePHP(重写规则?)

    不久前我设法让它工作 但是当我回到我开始的 cakephp 项目时 似乎我最近对 nginx 所做的任何更改 或者可能是最近的更新 都打破了我的重写规则 目前我有 worker processes 1 events worker conne
  • Angular cli 项目中的绝对路径

    如何在 Angular cli 生成的项目中使用绝对路径 所以我有这条路 src gt app gt shared我想写import from shared ffdsdf my module ts 代替 shared ffdsdf my m
  • 将 dynamodb 表复制到 hive 的 pyspark 代码问题:不允许操作

    我正在尝试使用 pyspark 代码从 aws emr 上的 Dynamodb 创建外部配置单元表 当我在 hive 提示符下执行查询时 该查询工作正常 但当我将其作为 pyspark 作业执行时 该查询会失败 代码如下 from pysp
  • 本地开发主机的通配符

    我最近在多个项目之间切换 所有这些都在相同的IP上本地运行 但具有不同的域 实际上它总是 local like foo local bar local等等 我可以继续将它们添加到我的 etc hosts文件 但这不是很干净的方式 这就是为什
  • 我无法在 Android AVD Manager 中创建模拟器

    我正在尝试创建一个 Android 模拟器 当我打开 AVD 管理器并尝试创建一个模拟器时 它一直显示 未选择目标 即使我选择了目标 http bit ly 15vr9fk http bit ly 15vr9fk 面临同样的问题 我检查了A
  • 未收到 Microsoft Graph 更改通知

    我想订阅用户删除 以便每当在 Azure AD 中删除用户时 我们的应用程序都可以做出相应的反应 这是我的订阅请求 const now new Date const threeDaysLater new Date now getTime 3
  • unix fork exec 序列真的像听起来那么昂贵吗?

    我正在读关于fork and exec对于考试 我的书说 每当需要在 UNIX 系统中运行一个新的 不同的 进程时 您都会分叉当前进程 然后是execve 然而 它也说 每当fork被调用时 父进程的整个内存映像被复制到新进程 那么我的问题
  • 是否可以通过在基类中添加新的虚函数来破坏代码?

    是否可以通过简单地向基类添加新的虚函数来改变程序的观察到的行为 我的意思是不必对代码进行其他更改 以下程序打印OK 取消注释虚函数B它将开始打印CRASH include
  • 如何使用 JavaScript 创建电子邮件按钮

    我找不到真正符合我的问题的帖子 所以我们开始 我想在我的网站上实现 通过邮件共享 按钮 因此当您单击该按钮时 假设 Outlook 或 Thunderbird 打开 并为您提供在新邮件中共享网站链接的选项 我不太确定 但我认为我无法仅使用
  • 将带孔的多边形转换为多个简单的无孔多边形

    我正在处理IfcFace http www buildingsmart tech org ifc IFC4 Add2 html schema ifctopologyresource lexical ifcface htm 我得到了一个带孔的