1

不应填充 PyVista 填充开口的问题

import math
import numpy as np
import matplotlib as mpl
import pyvista as pv


mpl.use("Qt5Agg")
mpl.rcParams["toolbar"] = "None"  # Get rid of toolbar


def xy_waveguide_contour(throat, x_waveguide, ellipse_x):
    x_initial = (throat + (x_waveguide * (ellipse_x - throat))) / 2

    return x_initial


def xy_waveguide_contour_x2(throat, x_waveguide, ellipse_x):
    x_initial = (throat + (x_waveguide * (ellipse_x - throat)))

    return x_initial


def z_waveguide_contour(x_array, depth_factor, angle_factor, throat):
    angle_factor = angle_factor / 10000

    x_prime = x_array - (throat / 2)

    z = (x_prime / angle_factor) ** (1 / depth_factor)

    return z


def ellipse_contour(a, b):
    a = a / 2
    b = b / 2
    ellipse_steps = np.linspace(0, 0.5 * math.pi, 100)
    x_ellipse_array = np.array([])
    y_ellipse_array = np.array([])
    for h in range(100):
        x_ellipse_array = np.append(x_ellipse_array, a * np.cos(ellipse_steps[h]))
        y_ellipse_array = np.append(y_ellipse_array, b * np.sin(ellipse_steps[h]))
    return x_ellipse_array, y_ellipse_array


def circle_contour(throat):
    throat = (throat / 2)
    circle_steps = np.linspace(0, 0.5 * math.pi, 100)
    x_circle_array = np.array([])
    y_circle_array = np.array([])
    for j in range(100):
        x_circle_array = np.append(x_circle_array, throat * np.cos(circle_steps[j]))
        y_circle_array = np.append(y_circle_array, throat * np.sin(circle_steps[j]))
    return x_circle_array, y_circle_array


waveguide_throat = 30

ellipse_x = 250
ellipse_y = 150
depth_fact = 4
angle_fact = 40

# Total steps = 100
array_length = 100

xy_steps = np.linspace(0, 1, array_length)

# initialize x, y, z, and zero array
x_array = np.array([])
y_array = np.array([])
z_array = np.array([])
xsub_array = np.array([])
ysub_array = np.array([])
zero_array = np.zeros([array_length])

# calculate hor(x), ver(y), and height(z) contour data and add into array
for i in range(array_length):
    x_array = np.append(x_array, xy_waveguide_contour(waveguide_throat, xy_steps[i], ellipse_x))
    y_array = np.append(y_array, xy_waveguide_contour(waveguide_throat, xy_steps[i], ellipse_y))

    z_array = np.append(z_array, z_waveguide_contour(x_array[i], depth_fact, angle_fact, waveguide_throat))

# calculate data for ellipse
x_ellipse_data, y_ellipse_data = ellipse_contour(ellipse_x, ellipse_y)

# grab last point from z_array and make entire array same value to define height of ellipse/waveguide
ellipse_height = z_array[array_length - 1]

ellipse_z = np.full(shape=array_length, fill_value=ellipse_height)

# Calculate data for throat
circle_x, circle_y = circle_contour(waveguide_throat)


for j in range(0, array_length, 20):
    for i in range(array_length):

        xsub_array = np.append(xsub_array, xy_waveguide_contour_x2(circle_x[j], xy_steps[i], x_ellipse_data[j]))
        ysub_array = np.append(ysub_array, xy_waveguide_contour_x2(circle_y[j], xy_steps[i], y_ellipse_data[j]))

# X = np.concatenate((circle_x, x_ellipse_data, x_array, zero_array))
# Y = np.concatenate((circle_y, y_ellipse_data, zero_array, y_array))
# Z = np.concatenate((zero_array, ellipse_z, z_array, z_array))

# Reshape arrays into 1 column, multiple rows
x_array = x_array.reshape(-1, 1)
y_array = y_array.reshape(-1, 1)
z_array = z_array.reshape(-1, 1)
ellipse_z = ellipse_z.reshape(-1, 1)
x_ellipse_data = x_ellipse_data.reshape(-1, 1)
y_ellipse_data = y_ellipse_data.reshape(-1, 1)
circle_x = circle_x.reshape(-1, 1)
circle_y = circle_y.reshape(-1, 1)
zero_array = zero_array.reshape(-1, 1)
xsub_array = xsub_array.reshape(-1, 1)
ysub_array = ysub_array.reshape(-1, 1)

# save arrays to text

X = np.concatenate((circle_x, x_ellipse_data, x_array, zero_array, xsub_array), axis=0)
Y = np.concatenate((circle_y, y_ellipse_data, zero_array, y_array, ysub_array), axis=0)
Z = np.concatenate((zero_array, ellipse_z, z_array, z_array, z_array, z_array, z_array, z_array, z_array), axis=0)


xyz = np.concatenate((X, Y, Z), axis=1)

cloud = pv.PolyData(xyz)
surf = cloud.delaunay_2d()
surf.plot()

我正在尝试使用 pyvista(也尝试过 Mayavi)创建 3D 表面,每当我执行 delaunay_2D 网格来创建表面时,它都会关闭该表面的“嘴”开口,该开口仍应打开。我附上了一张图片,显示了需要修复的部分,以及我的代码副本,该副本生成数据并重现当前问题。我非常感谢任何人对此问题的帮助。

4

1 回答 1

1

正如我在您问题的先前版本下的评论中指出的那样,我找不到一种简单的方法来解决您当前的方法。

  1. 您可以通过足够alpha=cloud.length/10接近delaunay_2d()的位置,但这仍然会在波导边缘留下虚假边缘。
  2. 能够使用挤压创建波导会很好,但我不知道这将如何适用于此。

所以我唯一能想到的就是改变你的整个方法:通过参数化你的表面,将你的波导创建为二维结构化网格。这实际上是可能的,而且不是太难:

  1. 在 2d 中,您有一个圆和一个椭圆,以及两者之间的线性插值。这意味着以 的形式获取点(r*cos(phi), r*sin(phi))并插值到 的点(a*cos(phi), b*sin(phi))。这很简单。
  2. z方向上你有一个根函数,它取决于你的二维网格的“径向”坐标。

您可以这样做:

import numpy as np
import pyvista as pv

# parameters for the waveguide
# diameter of the inner circle
waveguide_throat = 30
# axes of the outer ellipse
ellipse_x = 250
ellipse_y = 150
# shape parameters for the z profile
depth_factor = 4
angle_factor = 40
# number of grid points in radial and angular direction
array_length = 100

# now create the actual structured grid
# 2d circular grid
r, phi = np.mgrid[0:1:array_length*1j, 0:np.pi/2:array_length*1j]

# transform to ellipse on the outside, circle on the inside
x = (ellipse_x/2 * r + waveguide_throat/2 * (1 - r))*np.cos(phi)
y = (ellipse_y/2 * r + waveguide_throat/2 * (1 - r))*np.sin(phi)

# compute z profile
angle_factor = angle_factor / 10000
z = (ellipse_x / 2 * r / angle_factor) ** (1 / depth_factor)

waveguide = pv.StructuredGrid(x, y, z)
waveguide.plot(show_edges=True)

这为您提供了形成波导的密集二维网格。无论您需要对这个表面做什么,都可以使用结构化网格。

这是结构化网格,您的点云覆盖在上面以显示它们是相同的: 带有蓝色表面的图像,原始点云的红点叠加

于 2021-12-30T10:57:19.450 回答