python 在PyVista中挤出凹的复杂多边形

kuhbmx9i  于 2023-01-24  发布在  Python
关注(0)|答案(1)|浏览(284)

我想取一个凹的复杂多边形(包含孔洞),然后将其垂直挤压成一个多面体,纯粹是为了可视化。我从一个形状优美的Polygon开始,如下所示:

poly = Polygon(
    [(0,0), (10,0), (10,10), (5,8), (0,10), (1,7), (0,5), (1,3)], 
    holes=[
        [(2,2),(4,2),(4,4),(2,4)],
        [(6,6), (7,6), (6.5,6.5), (7,7), (6,7), (6.2,6.5)]])

我在matplotlib中正确地将其绘制为(将外部坐标重定向为顺时针,将孔坐标重定向为逆时针):

然后,我试图使用PyVista渲染这个从页面中挤出的多边形(沿着z)。PyVista不直接支持PolyData类型的凹(或复杂)输入,所以我们首先创建一个简单(无孔)凹多边形的挤出,如this discussion

def extrude_simple_polygon(xy, z0, z1):

    # force counter-clockwise ordering, so PyVista interprets polygon correctly
    xy = _reorient_coords(xy, clockwise=False)

    # remove duplication of first & last vertex
    xyz0 = [(x,y,z0) for x,y in xy]
    if (xyz0[0] == xyz0[-1]):
        xyz0.pop()

    # explicitly set edge_source
    base_vert = [len(xyz0)] + list(range(len(xyz0)))
    base_data = pyvista.PolyData(xyz0, base_vert)
    base_mesh = base_data.delaunay_2d(edge_source=base_data)
    vol_mesh  = base_mesh.extrude((0, 0, z1-z0), capping=True)

    # force triangulation, so PyVista allows boolean_difference
    return vol_mesh.triangulate()

依次挤出外部多边形及其每个内部多边形时,请观察此操作的效果:

extrude_simple_polygon(list(poly.exterior.coords), 0, 5).plot()

extrude_simple_polygon(list(poly.interiors[0].coords), 0, 5).plot()
extrude_simple_polygon(list(poly.interiors[1].coords), 0, 5).plot()

第一节第二节第一节第三节第一节
我推断,要创建原始 * 复杂 * 多边形的拉伸,我可以计算boolean_difference

outer_vol = extrude_simple_polygon(list(poly.exterior.coords), 0, 5)
for hole in poly.interiors:
    hole_vol = extrude_simple_polygon(list(hole.coords), 0, 5)
    outer_vol = outer_vol.boolean_difference(hole_vol)

outer_vol.plot()

是错误的:

该文档建议通过plot_normals检查法线,发现所有挤出体积都有向内指向(或意外)的法线:
第一个第五个第一个第一个第六个第一个第七个第一个
extrude文档没有提到挤出曲面法线,也没有提到原始对象(在本例中为多边形)方向。
我们可以原谅我们的多边形必须是顺时针方向的,所以我们在extrude_simple_polygon的第一行设置clockwise=True,然后再试一次。调用base_mesh.plot()会显示(* 应该 * 看起来像我们原始的蓝色外部多边形):

用挤压

  • PyVista总是期望逆时针多边形吗?
  • 为什么拉伸会创建具有向内指向的曲面法线的体积块?
  • 如何更正挤出的曲面法线?
  • 否则,我怎样才能让PyVista正确地可视化一个难以置信的简单挤压的凹复杂多边形呢?
x4shl7ld

x4shl7ld1#

你已经很接近了,你需要做的是使用一个 single 调用delaunay_2d(),把所有三个多边形(即包围的一个和两个洞)作为边源(循环源?),同样重要的是从每个多边形得到面(而不是线);这使得可以加强孔的孔度。
下面是一个完整的输入示例(我手动翻转了孔的方向;您似乎有一个_reorient_coords()帮助器,您应该使用它来代替):

import pyvista as pv

# coordinates of enclosing polygon
poly_points = [
    (0, 0), (10, 0), (10, 10), (5, 8), (0, 10), (1, 7), (0, 5), (1, 3),
]
# hole point order hard-coded here; use your _reorient_coords() function
holes = [
    [(2, 2), (4, 2), (4, 4), (2, 4)][::-1],
    [(6, 6), (7, 6), (6.5, 6.5), (7, 7), (6, 7), (6.2, 6.5)][::-1],
]

z0, z1 = 0.0, 5.0

def points_2d_to_poly(points, z):
    """Convert a sequence of 2d coordinates to a polydata with a polygon."""
    faces = [len(points) + 1, *range(len(points)), 0]
    poly = pv.PolyData([p + (z,) for p in points], faces=faces)
    return poly

# bounding polygon
polygon = points_2d_to_poly(poly_points, z0)

# add all holes
for hole_points in holes:
    polygon += points_2d_to_poly(hole_points, z0)

# triangulate poly with all three subpolygons supplying edges
# (relative face orientation is critical here)
polygon_with_holes = polygon.delaunay_2d(edge_source=polygon)

# extrude
holey_solid = polygon_with_holes.extrude((0, 0, z1 - z0), capping=True)
holey_solid.plot()

以下是多边形预挤出的顶视图:

plotter = pv.Plotter()
plotter.add_mesh(polygon_with_holes, show_edges=True, color='cyan')
plotter.view_xy()
plotter.show()

相关问题