matlab 如何找到一列3D点的“内部边界”/“内部船体”?

c2e8gylq  于 2023-06-06  发布在  Matlab
关注(0)|答案(3)|浏览(411)

我需要一些帮助来写这个algorithm
对于空间中给定的一组线,我试图找到原点(参考点)为0.5,0.5,0.5时的可访问体积。目前,我做以下工作:
对于每条线,计算到原点的距离(0.5,0.5,0.5)。然后,将所有线上的所有这些垂直距离点收集到一个列表中。
现在,我想计算“内部”(既不是boundary也不是convhull),因为我想计算一个以(0.5,0.5,0.5)为中心的球的可达体积。
例如,在这个简单的例子中,我想用我的算法计算绿色(内部线):

配置:

从原点(0.5,0.5,0.5)到直线

的最近点
只计算我想要的“内部边界”的点。这意味着形状的边界所有点无论是外部的内部或其边界上。

下面是我想要的代码,而不是convhull

close all
N=30;

S1 = cell(1, N);
for k = 1:N, S1{k} = rand(1, 3); end
S2 = cell(1, N);
for k = 1:N, S2{k} = rand(1, 3); end

M1 = cat(3, S1{:});
M2 = cat(3, S2{:});
M  = permute(cat(1, M1, M2), [1, 3, 2]);
figure
plot3(M(:, :, 1), M(:, :, 2), M(:, :, 3))
hold on
[x,y,z] = sphere;
x=x/100;y=y/100;z=z/100;
plot3(x+0.5,y+0.5,z+0.5)

figure 
hold on

NearestIntersectionPoints = cell(1,N); 
for k = 1:N 
    tmp1 = M(1,k,:); tmp2 = M(2,k,:);
    v1=tmp1(1,:); v2=tmp2(1,:);
    [d, intersection] = point_to_line([0.5,0.5,0.5], v1, v2);
    
    [x,y,z] = sphere;
    x=x/500;y=y/500;z=z/500;
    plot3(x+intersection(1),y+intersection(2),z+intersection(3))
    NearestIntersectionPoints{k} = intersection;

end

MHull = cat(3,NearestIntersectionPoints{:});
X=MHull(:,1,:); Y=MHull(:,2,:); Z=MHull(:,3,:);
X=X(:); Y=Y(:); Z=Z(:);
k = boundary(X,Y,Z);
hold on

plot3(X(k),Y(k),Z(k), 'r-*')

function [d,intersection] = point_to_line(pt, v1, v2)
      a = v1 - v2;
      b = pt - v2;
      d = norm(cross(a,b)) / norm(a);
      theta = asin(norm(cross(a,b))/(norm(a)*norm(b)));
      intersection = v2 + a * cos(theta);
      
end
qgelzfjb

qgelzfjb1#

我会这样做:
1.四面体化点云
因此,创建由四面体组成网格,其中四面体不与任何其他四面体相交,也不包含任何点。我是这样做的:
1.结构
你需要点、三角形和四面体的列表。每个三角形需要一个计数器,它会告诉你它是被使用一次还是两次。
1.创建第一个四面体
通过所有点的4个嵌套循环,并检查形成的四面体内部是否不包含任何点。如果没有,就停止,因为你找到了你的第一个四面体。这是O(n^5),但由于有很多有效的四面体,它永远不会达到如此高的运行时间...现在只需将这个四面体添加到三角形和四面体列表中。
1.查找下一个四面体
现在遍历所有使用过一次的三角形。对于每个形式的四面体,通过使用它使用的那3个点,并找到第4个点与在**#2**中相同的方式。有效的四面体不能包含任何点,也不能与列表中的任何现有四面体相交。
为了确保整个体积将填充没有洞,你需要优先考虑的过程中已经有更多三角形的四面体。因此,首先搜索4个三角形,如果没有发现比3等…
对于每个找到的有效四面体,将其添加到列表中并再次查看,直到没有有效的四面体可以形成…整个过程大约是O(n^2),所以要小心点云中的点太多。存储三角形的法线也可以大大加快测试速度…
1.外部边界
外部边界由列表中仅使用过一次的三角形组成
1.内部边界
内部间隙四面体应该大于所有其它的。所以检查他们的大小对平均大小,如果更大,他们最有可能是一个差距。把它们组合在一起,列在列表上。每个间隙只有大的四面体,并且所有四面体必须共享至少一个面(三角形)。现在只需计算每组三角形的使用情况,所有三角形使用一次就可以形成间隙/洞/内部边界/网格。
如果您的点密度是均匀的,则可以调整以下内容:

  • 在2D点集中寻找漏洞?

并创建点密度的体素图。。没有密度的体素是间隙或外部空间。这可以用于更快和更好地选择内部四面体。

brqmpdu1

brqmpdu12#

如果我很好地理解了你的问题,你想在另一个体积中有最大的体积,两个体积之间没有共同点。
外部体积从点集合的子集构建。显而易见的解决方案是用其余的点构建内部体积。
一组点的体积可以用几种方法来制作。如果体积不是凸的,那么你需要更多的信息(例如面之间的最小Angular ),因为您会得到带星号的多面体或类凸形或其他形状。
对于凸体,我推荐使用四面体的三维Delaunay构造。边界由不与其他“tet”共享的“tet”的面限定。
从全部点集中删除属于边界的点:边界中的每个泰特都有一个不在边界上的第四个点。
内部体积是另一个Delaunay构造。也许你只需要从前面的边界tets的第四点。

czq61nw1

czq61nw13#

我最后做的事情是这样的:

import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.pyplot as plt

def plot_random_points_on_circles(N: int, R: list, center: list):
    """
    Generates two sets of N random points on two circles with radii R and centers at center.
    Scales the points and calculates the convex hull of the scaled points.
    Plots the convex hull and the original points.

    :param N: Number of points to generate on each circle
    :type N: int
    :param R: List of radii for the two circles
    :type R: list
    :param center: List of x and y coordinates for the center of the circles
    :type center: list
    """
    x = np.zeros((len(R), N))
    y = np.zeros((len(R), N))
    theta = np.linspace(0, 2 * np.pi, N + 1)
    theta = theta[:-1]

    for i in range(len(R)):
        x[i,:] = R[i] * (np.random.randn() + 1) * np.cos(theta + np.random.rand()) + center[0]
        y[i,:] = R[i] * (np.random.randn() + 1) * np.sin(theta + np.random.rand()) + center[1]

    x = np.concatenate((x[0,:], x[1,:]))
    y = np.concatenate((y[0,:], y[1,:]))
    rSquared = x**2 + y**2
    q = rSquared / max(rSquared)**2
    xx = x / q
    yy = y / q

    k = ConvexHull(np.column_stack((xx, yy)))
    plt.plot(x[k.vertices], y[k.vertices], 'r-', x, y, 'b*')
    plt.show()
N = 20
R = [2, 6]
center = [0, 0]

plot_random_points_on_circles(N, R, center)

相关问题