use*_*081 6 python mesh matplotlib
我有一个用空间中的 (x,y) 点列表定义的几何图形。我想用这些数据创建一个三角形网格,因此我尝试了matplotlib 中的三角测量函数来实现此目的。然而,由于我的几何体有一些曲线,该算法在我的零件的边缘之间生成不需要的三角形:

红色曲线是我的几何图形的边缘。
有什么办法可以解决这个问题吗?也许三角测量功能不是我需要的,在这种情况下,您对使用什么有什么建议吗?
以下代码来自该示例。在示例中,他们通过显式命名三个点来定义三角形,而不是我想通过调用函数来使用的 Delaunay 三角剖分triang = tri.Triangulation(x, y),这将给我提供与原始图片相同的行为。
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
xy = np.asarray([
[-0.101, 0.872], [-0.080, 0.883], [-0.069, 0.888], [-0.054, 0.890],
[-0.045, 0.897], [-0.057, 0.895], [-0.073, 0.900], [-0.087, 0.898],
[-0.090, 0.904], [-0.069, 0.907], [-0.069, 0.921], [-0.080, 0.919],
[-0.073, 0.928], [-0.052, 0.930], [-0.048, 0.942], [-0.062, 0.949],
[-0.054, 0.958], [-0.069, 0.954], [-0.087, 0.952], [-0.087, 0.959],
[-0.080, 0.966], [-0.085, 0.973], [-0.087, 0.965], [-0.097, 0.965],
[-0.097, 0.975], [-0.092, 0.984], [-0.101, 0.980], [-0.108, 0.980],
[-0.104, 0.987], [-0.102, 0.993], [-0.115, 1.001], [-0.099, 0.996],
[-0.101, 1.007], [-0.090, 1.010], [-0.087, 1.021], [-0.069, 1.021],
[-0.052, 1.022], [-0.052, 1.017], [-0.069, 1.010], [-0.064, 1.005],
[-0.048, 1.005], [-0.031, 1.005], [-0.031, 0.996], [-0.040, 0.987],
[-0.045, 0.980], [-0.052, 0.975], [-0.040, 0.973], [-0.026, 0.968],
[-0.020, 0.954], [-0.006, 0.947], [ 0.003, 0.935], [ 0.006, 0.926],
[ 0.005, 0.921], [ 0.022, 0.923], [ 0.033, 0.912], [ 0.029, 0.905],
[ 0.017, 0.900], [ 0.012, 0.895], [ 0.027, 0.893], [ 0.019, 0.886],
[ 0.001, 0.883], [-0.012, 0.884], [-0.029, 0.883], [-0.038, 0.879],
[-0.057, 0.881], [-0.062, 0.876], [-0.078, 0.876], [-0.087, 0.872],
[-0.030, 0.907], [-0.007, 0.905], [-0.057, 0.916], [-0.025, 0.933],
[-0.077, 0.990], [-0.059, 0.993]])
x = np.degrees(xy[:, 0])
y = np.degrees(xy[:, 1])
triang = tri.Triangulation(x, y)
fig1, ax1 = plt.subplots()
ax1.set_aspect('equal')
ax1.triplot(triang, 'bo-', lw=1)
Run Code Online (Sandbox Code Playgroud)
如果您有内部形状的轮廓来绘制三角剖分,您可以应用@ThomasK\xc3\xbchn 的答案。
\n\n否则,点之间可能存在最大距离,超过该距离的三角形不应被考虑在内。在这种情况下,您可以掩盖这些三角形。
\n\nimport matplotlib.pyplot as plt\nimport matplotlib.tri as tri\nimport numpy as np\n\nxy = np.asarray([\n [-0.101, 0.872], [-0.080, 0.883], [-0.069, 0.888], [-0.054, 0.890],\n [-0.045, 0.897], [-0.057, 0.895], [-0.073, 0.900], [-0.087, 0.898],\n [-0.090, 0.904], [-0.069, 0.907], [-0.069, 0.921], [-0.080, 0.919],\n [-0.073, 0.928], [-0.052, 0.930], [-0.048, 0.942], [-0.062, 0.949],\n [-0.054, 0.958], [-0.069, 0.954], [-0.087, 0.952], [-0.087, 0.959],\n [-0.080, 0.966], [-0.085, 0.973], [-0.087, 0.965], [-0.097, 0.965],\n [-0.097, 0.975], [-0.092, 0.984], [-0.101, 0.980], [-0.108, 0.980],\n [-0.104, 0.987], [-0.102, 0.993], [-0.115, 1.001], [-0.099, 0.996],\n [-0.101, 1.007], [-0.090, 1.010], [-0.087, 1.021], [-0.069, 1.021],\n [-0.052, 1.022], [-0.052, 1.017], [-0.069, 1.010], [-0.064, 1.005],\n [-0.048, 1.005], [-0.031, 1.005], [-0.031, 0.996], [-0.040, 0.987],\n [-0.045, 0.980], [-0.052, 0.975], [-0.040, 0.973], [-0.026, 0.968],\n [-0.020, 0.954], [-0.006, 0.947], [ 0.003, 0.935], [ 0.006, 0.926],\n [ 0.005, 0.921], [ 0.022, 0.923], [ 0.033, 0.912], [ 0.029, 0.905],\n [ 0.017, 0.900], [ 0.012, 0.895], [ 0.027, 0.893], [ 0.019, 0.886],\n [ 0.001, 0.883], [-0.012, 0.884], [-0.029, 0.883], [-0.038, 0.879],\n [-0.057, 0.881], [-0.062, 0.876], [-0.078, 0.876], [-0.087, 0.872],\n [-0.030, 0.907], [-0.007, 0.905], [-0.057, 0.916], [-0.025, 0.933],\n [-0.077, 0.990], [-0.059, 0.993]])\nx = np.degrees(xy[:, 0])\ny = np.degrees(xy[:, 1])\n\ntriang = tri.Triangulation(x, y)\n\nfig1, ax1 = plt.subplots()\nax1.set_aspect(\'equal\')\n\n# plot all triangles\nax1.triplot(triang, \'bo-\', lw=0.2)\n\n# plot only triangles with sidelength smaller some max_radius\nmax_radius = 2\ntriangles = triang.triangles\n\n# Mask off unwanted triangles.\nxtri = x[triangles] - np.roll(x[triangles], 1, axis=1)\nytri = y[triangles] - np.roll(y[triangles], 1, axis=1)\nmaxi = np.max(np.sqrt(xtri**2 + ytri**2), axis=1)\ntriang.set_mask(maxi > max_radius)\n\nax1.triplot(triang, color="indigo", lw=2.6)\n\n\nplt.show()\nRun Code Online (Sandbox Code Playgroud)\n\n窄线显示所有三角形(点的凸包),粗线仅显示那些边长不大于某些最大值(在本例中选择为2)的三角形。
该线程可能同样相关:matplotlibcontour/contourf of **concave** non-gridded data
\nIf the shape of the geometry is well defined, say by a curve, one can check for each triangle whether it lies within the shape or not. One can then define a mask and mask out undesired triangles. I found a solution using shapely, where define a polygon for the original shape (outline) and a polygon for each resulting triangle of Triangulation(), for which I then check whether it lies inside outline or not:
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
import shapely
from shapely.geometry import Polygon as sPolygon
fig, (ax1,ax2) = plt.subplots(ncols=2)
ax1.set_aspect('equal')
ax2.set_aspect('equal')
##setting up basic shape
phi = np.linspace(0,2*np.pi,20)
r = 1 + 2*np.sin(phi)**2
x = np.cos(phi)*r
y = np.sin(phi)*r
ax1.plot(x,y,'ro-', lw=3, ms=6, zorder= 1, label='edge')
ax2.plot(x,y,'ro-', lw=3, ms=6, zorder= 1)
##original triangulation
triang1 = tri.Triangulation(x, y)
ax1.triplot(triang1, 'ko--', lw=1, ms=4, zorder=2, label='all')
##masking
outline = sPolygon(zip(x,y))
mask = [
not outline.contains(sPolygon(zip(x[tri], y[tri])))
for tri in triang1.get_masked_triangles()
]
triang1.set_mask(mask)
ax1.triplot(triang1, 'b-', lw=1, zorder=3, label='inner')
##adding more points
x_extra = np.random.rand(30)*(x.max()-x.min())+x.min()
y_extra = np.random.rand(30)*(y.max()-y.min())+y.min()
x = np.concatenate([x,x_extra])
y = np.concatenate([y,y_extra])
triang2 = tri.Triangulation(x,y)
ax2.triplot(triang2, 'ko--', lw=1, ms=4, zorder=2)
##masking
mask = [
not outline.contains(sPolygon(zip(x[tri], y[tri])))
for tri in triang2.get_masked_triangles()
]
triang2.set_mask(mask)
ax2.triplot(triang2, 'b-', lw=1, zorder=3)
fig.legend()
plt.show()
Run Code Online (Sandbox Code Playgroud)
The result of the code looks something like this:
我不太确定OP想要什么,所以在左侧我只使用边缘的点,而在右侧我添加了一些随机的额外点进行三角测量。图中,形状的轮廓以红色绘制,Delaunay 三角剖分的原始结果以黑色虚线绘制,蒙版三角剖分以蓝色绘制。
编辑:
我刚刚注意到,显然过滤后的右侧图片中不包含轮廓点之一。这一定是由于数字不准确造成的。解决此问题的一种方法是使用buffer()命令稍微增加轮廓的大小。这样的事情似乎适合当前的问题:
outline = sPolygon(zip(x,y)).buffer(.01)
Run Code Online (Sandbox Code Playgroud)
但实际的缓冲量可能需要调整。
| 归档时间: |
|
| 查看次数: |
3253 次 |
| 最近记录: |