多边形数据包含非凸多边形。

huangapple go评论60阅读模式
英文:

PolyData with nonconvex polygons

问题

以下是翻译好的内容:

为了复制这个错误,让我们考虑描述非凸多边形的点的连续性:

[0. , 0. , 0. ],
[1. , 0. , 0. ],
[1. , 0.5, 0. ],
[0.5, 0.5, 0. ],
[0.5, 1. , 0. ],
[1. , 1. , 0. ],
[1. , 1.5, 0. ],
[0. , 1.5, 0. ]

这些数据应该表示一个看起来像这样的非凸多边形:多边形数据包含非凸多边形。

但是,当尝试使用PyVista的PolyData构造函数设置它时,如下所示:

import numpy as np
import pyvista

b = 0.5
c = 0.5
points = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [1, b, 0],
    [1-b, b, 0],
    [1-b, b+c, 0],
    [1, b+c, 0],
    [1, 2*b+c, 0],
    [0, 2*b+c, 0],
])

face = np.concatenate([
    [9],
    np.arange(9),
    [0],
])
polygon = pyvista.PolyData(
    points,
    face)
polygon.plot()

不知何故,我得到了一个扭曲的版本:

多边形数据包含非凸多边形。

我是否漏掉了PyVista文档中的某些内容?

英文:

Just to replicate the error, let's consider the succession of points describing a nonconvex polygon:

[0. , 0. , 0. ],
[1. , 0. , 0. ],
[1. , 0.5, 0. ],
[0.5, 0.5, 0. ],
[0.5, 1. , 0. ],
[1. , 1. , 0. ],
[1. , 1.5, 0. ],
[0. , 1.5, 0. ]

This data should represent a nonconvex polygon looking like 多边形数据包含非凸多边形。

But when trying to set this up using PyVista's PolyData constructor, as:

import numpy as np
import pyvista

b = 0.5
c = 0.5
points = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [1, b, 0],
    [1-b, b, 0],
    [1-b, b+c, 0],
    [1, b+c, 0],
    [1, 2*b+c, 0],
    [0, 2*b+c, 0],
])

face = np.concatenate([
    [9],
    np.arange(9),
    [0],
])
polygon = pyvista.PolyData(
    points,
    face)

polygon.plot()

I somehow get a distorted version of it:

多边形数据包含非凸多边形。

Is there something I'm missing from pyvista documentation?

答案1

得分: 1

以下是翻译好的部分:

"你的代码中有一个错误,但这不是你看到这个现象的原因。

你代码中的错误是你有8个点,但使用了np.arange(9),它的长度和最大值都是错误的(它在末尾包含了不存在的点索引8)。你可以从以下代码怀疑到某些地方出错了

>>> polygon.n_cells
2

你传递的面有一个结尾的零,这意味着一个大小为0的单元格。更大的问题是在第一个面中引用了一个不存在的点8;我怀疑这甚至可能会导致后续的段错误。

你可以通过使用np.arange(8)来修复此错误,或者使用一些未来版本的代码,如下所示

import numpy as np
import pyvista

b = 0.5
c = 0.5
points = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [1, b, 0],
    [1-b, b, 0],
    [1-b, b+c, 0],
    [1, b+c, 0],
    [1, 2*b+c, 0],
    [0, 2*b+c, 0],
])

face = np.concatenate([
    [points.shape[0] + 1],
    np.arange(points.shape[0]),
    [0],
])
polygon = pyvista.PolyData(points, face)

polygon.plot()

现在,问题是这个现象仍然存在。我偶尔会遇到这个问题,我不知道这是PyVista的错误还是VTK的错误(可能是后者)。你可以在绘图窗口中通过按下 ws 键来在线框模型和表面模型之间切换;显然有些地方不对,因为线框模型看起来是正确的。

但无论如何,你可以通过使用triangulate() 过滤器将你的凹多边形面拆分成三角形来解决这个问题:

polygon = pyvista.PolyData(points, face).triangulate()
polygon.plot()

现在,这个多边形在表面渲染中看起来正确。但是当然,现在它不再是一个单一的单元格,而是包含了多个(6个)三角形。对于大多数应用程序来说,这是完全可以的,实际上甚至有一些只能处理三角形输入的过滤器。所以这可能是你问题的一个完全合适的解决方案。"

英文:

There's a bug in your code but that's not the reason you're seeing this artifact.

The bug in your code is that you have 8 points but use np.arange(9) which has the wrong length and the wrong maximum value (it contains point index 8 at the end which doesn't exist). You can suspect that something's not right from

>>> polygon.n_cells
2

The faces you passed have a trailing zero, which would mean a cell of size 0. The larger issue is the reference to a non-existent point 8 in the first face; I suspect this might even lead to segfaults later.

You can fix this bug by using np.arange(8), or with some future-proofing, with

import numpy as np
import pyvista

b = 0.5
c = 0.5
points = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [1, b, 0],
    [1-b, b, 0],
    [1-b, b+c, 0],
    [1, b+c, 0],
    [1, 2*b+c, 0],
    [0, 2*b+c, 0],
])

face = np.concatenate([
    [points.shape[0] + 1],
    np.arange(points.shape[0]),
    [0],
])
polygon = pyvista.PolyData(points, face)

polygon.plot()

Now, the problem is that the artifact is still there. I've run into this occasionally, and I don't know if it's a PyVista bug or a VTK one (probably the latter). You can switch between a wireframe and a surface model in the plot window by pressing w and s, respectively; it's evident that something's not right because the wireframe looks correct.

But anyway you can get around the issue by breaking down your concave polygon face into triangles using the triangulate() filter:

polygon = pyvista.PolyData(points, face).triangulate()
polygon.plot()

Now this polygon looks correct in a surface render. But of course instead of a single cell it now contains multiple (6) triangles. For most applications this is perfectly fine, in fact there are even filters which only work with triangulated inputs. So this might be a perfectly fine solution to your problem.

huangapple
  • 本文由 发表于 2023年6月9日 01:03:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434183.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定