简体   繁体   English

Python,四面体(scipy.Delaunay)3D点云的一部分

[英]Python, section of a tetrahedralized (scipy.Delaunay) 3D cloud of points

I want to draw a "cross section" of a hull in a 3D space, the intersection of the hull with a plane . 我想在3D空间中绘制船体的“横截面” ,即船体与平面的交点

The space is defined by axis X, Y, Z , and the crossing plane, parallel to XZ is defined by Y = 50 该空间由X, Y, Z轴定义, 平行于XZ的交叉平面由Y = 50定义

First, I loaded a cloud of 3D points in a np.array : 首先,我在np.array加载了3D points云:

#loading colors

points = np.array([(GEO.XYZRGB(rank, name, X, Y, Z))
                  for rank, name, X, Y, Z in csv.reader(open('colors.csv'))])
  • point structure is rank, name, X, Y, Z, R, G, B 点结构是rank, name, X, Y, Z, R, G, B

  • and each points is defined in the 3D space by X, Y, Z 每个点在3D空间中由X, Y, Z

a few examples: 一些例子:

['2' 'Y2    ' '77.89506204' '87.46909733' '42.72168896' '254' '244' '21']
['3' 'Y4    ' '76.95634543' '83.94271933' '39.48573173' '255' '234' '0']
['4' 'PINKwA' '64.93353667' '59.00840333' '84.71839733' '218' '154' '225']
...

Now, I made a scipy.Delaunay tetrahedralization of the points: 现在,我做了一scipy.Delaunay

# Delaunay triangulation    
tri = scipy.spatial.Delaunay(points[:,[2,3,4]], furthest_site=False) 

So I can get all the vertices (ie each singular tetrahedron of the hull): 这样我就可以获得所有vertices (即,船体的每个奇异的四面体):

# indices of vertices
indices = tri.simplices

# the vertices for each tetrahedron
vertices = points[indices]

print vertices

My question: from here, I have the vertices, how do I find all the points of intersection between the plane and the hull? 我的问题:从这里有顶点,如何找到飞机和船体之间的所有交点?

Thanks 谢谢

Below I give python code that, given a set of 3d points and a plane (defined by its normal vector and a point on the plane) computes the 3d Delaunay triangulation (tessellation) and the intersection points of the Delaunay edges with the plane. 下面,我给出python代码,给定一组3d点和一个平面(由其法向矢量和平面上的点定义),计算3d Delaunay三角剖分(镶嵌)以及Delaunay边缘与平面的交点。

The following figure visualizes the result on an example of twenty random points in the unit cube intersecting with the x=0 plane (the intersection points are colored blue). 下图以单位多维数据集中与x=0平面相交的二十个随机点(交点为蓝色)的示例显示了结果。 The code used for the visualization is modified from the code in this answer . 从此答案中的代码修改了用于可视化的代码。 在此处输入图片说明

To actually compute the plane intersection points I use the following code. 为了实际计算平面相交点,我使用以下代码。 The basic function plane_delaunay_intersection uses two auxiliary functions - collect_edges to gather the edges of the Delaunay triangulation (only one copy of each segment), and plane_seg_intersection , which intersects a line segment with a plane. 基本函数plane_delaunay_intersection使用两个辅助函数collect_edges收集Delaunay三角剖分的边缘(每个线段只有一个副本),以及plane_seg_intersection ,该线与平面与线段相交。

Here is the code: 这是代码:

from scipy.spatial import Delaunay
import numpy as np

def plane_delaunay_intersection(pts, pln_pt, pln_normal):
    """ 
    Returns the 3d Delaunay triangulation tri of pts and an array of nx3 points that are the intersection
    of tri with the plane defined by the point pln_pt and the normal vector pln_normal.
    """
    tri = Delaunay(points)
    edges = collect_edges(tri)
    res_lst = []
    for (i,j) in edges:
        p0 = pts[i,:]
        p1 = pts[j,:]
        p = plane_seg_intersection(pln_pt, pln_normal, p0, p1)
        if not np.any(np.isnan(p)):
            res_lst.append(p)
    res = np.vstack(res_lst)
    return res, tri 


def collect_edges(tri):
    edges = set()

    def sorted_tuple(a,b):
        return (a,b) if a < b else (b,a)
    # Add edges of tetrahedron (sorted so we don't add an edge twice, even if it comes in reverse order).
    for (i0, i1, i2, i3) in tri.simplices:
        edges.add(sorted_tuple(i0,i1))
        edges.add(sorted_tuple(i0,i2))
        edges.add(sorted_tuple(i0,i3))
        edges.add(sorted_tuple(i1,i2))
        edges.add(sorted_tuple(i1,i3))
        edges.add(sorted_tuple(i2,i3))
    return edges


def plane_seg_intersection(pln_pt, pln_normal, p0, p1):
    t0 = np.dot(p0 - pln_pt, pln_normal)
    t1 = np.dot(p1 - pln_pt, pln_normal)
    if t0*t1 > 0.0:
        return np.array([np.nan, np.nan, np.nan])  # both points on same side of plane

    # Interpolate the points to get the intersection point p.
    denom = (np.abs(t0) + np.abs(t1))
    p = p0 * (np.abs(t1) / denom) + p1 * (np.abs(t0) / denom)
    return p

The following code was used to generate the input for the example figure above: 以下代码用于生成以上示例图的输入:

np.random.seed(0)
x = 2.0 * np.random.rand(20) - 1.0
y = 2.0 * np.random.rand(20) - 1.0
z = 2.0 * np.random.rand(20) - 1.0

points = np.vstack([x, y, z]).T
pln_pt = np.array([0,0,0])  # point on plane
pln_normal = np.array([1,0,0])  # normal to plane
inter_pts, tri = plane_delaunay_intersection(points, pln_pt, pln_normal)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM