在matlab中加载stl文件并转换为3D数组
Load stl file in matlab and convert to a 3D array
我有一个 stl 文件,我已经使用 stlread 函数将它加载到 Matlab 中。此时我有一组面和顶点。如何将这些面和顶点转换为 3D 二进制数组(如 512x512x100 数组)以获得二进制 3D 体积?
你真幸运。我最近在处理 STL 文件,我编写了一些函数来完成这项工作。
首先,请注意您失去了精度。 STL 文件以任意精度表示任意形状,将其转换为体积会导致离散化和损失。
就是说,有一种非常简单的方法可以知道某个东西是在 封闭、连通的 三角曲面的内部还是外部,无论它是否是凸面:与表面的无限和计数交点。如果是奇数,它在里面,如果是偶数,它在外面。
您唯一需要的特殊代码是直线-三角形相交,Möller Trumbore 算法是最常见的算法之一。
function in=inmesh(fv,points)
%INMESH tells you if a point is inside a closed,connected triangulated surface mesh
% Author: Ander Biguri
maxZ=max(fv.vertices(:,3));
counts=zeros(size(points,1),1);
for ii=1:size(points,1)
ray=[points(ii,:);points(ii,1:2) maxZ+1];
for jj=1:size(fv.faces,1)
v=fv.vertices(fv.faces(jj,:),:);
if all(v(:,3)<ray(1,3))
continue;
end
isin=mollerTrumbore(ray, fv.vertices(fv.faces(jj,:),:));
counts(ii)=counts(ii)+isin;
end
end
in=mod(counts,2);
end
来自 FileExchange,稍作修改:
function [flag, u, v, t] = mollerTrumbore (ray,tri)
% Ray/triangle intersection using the algorithm proposed by Moller and Trumbore (1997).
%
% IMPORTANT NOTE: Assumes infinite legth rays.
% Input:
% ray(1,:) : origin.
% d : direction.
% tri(1,:), tri(2,:), tri(3,:): vertices of the triangle.
% Output:
% flag: (0) Reject, (1) Intersect.
% u,v: barycentric coordinates.
% t: distance from the ray origin.
% Author:
% Jesus Mena
d=ray(2,:)-ray(1,:);
epsilon = 0.00001;
e1 = tri(2,:)-tri(1,:);
e2 = tri(3,:)-tri(1,:);
q = cross(d,e2);
a = dot(e1,q); % determinant of the matrix M
if (a>-epsilon && a<epsilon)
% the vector is parallel to the plane (the intersection is at infinity)
[flag, u, v, t] = deal(0,0,0,0);
return;
end
f = 1/a;
s = ray(1,:)-tri(1,:);
u = f*dot(s,q);
if (u<0.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
r = cross(s,e1);
v = f*dot(d,r);
if (v<0.0 || u+v>1.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
if nargout>3
t = f*dot(e2,r); % verified!
end
flag = 1;
return
end
只需生成您的积分:
yourboundaries=% get the range of your data from the STL file.
[x,y,z]=meshgrid(yourboundaries);
P=[x(:) y(:) z(:)];
in=inmesh(fv,P);
img=reshape(in,yourboundariesSize);
我有一个 stl 文件,我已经使用 stlread 函数将它加载到 Matlab 中。此时我有一组面和顶点。如何将这些面和顶点转换为 3D 二进制数组(如 512x512x100 数组)以获得二进制 3D 体积?
你真幸运。我最近在处理 STL 文件,我编写了一些函数来完成这项工作。
首先,请注意您失去了精度。 STL 文件以任意精度表示任意形状,将其转换为体积会导致离散化和损失。
就是说,有一种非常简单的方法可以知道某个东西是在 封闭、连通的 三角曲面的内部还是外部,无论它是否是凸面:与表面的无限和计数交点。如果是奇数,它在里面,如果是偶数,它在外面。
您唯一需要的特殊代码是直线-三角形相交,Möller Trumbore 算法是最常见的算法之一。
function in=inmesh(fv,points)
%INMESH tells you if a point is inside a closed,connected triangulated surface mesh
% Author: Ander Biguri
maxZ=max(fv.vertices(:,3));
counts=zeros(size(points,1),1);
for ii=1:size(points,1)
ray=[points(ii,:);points(ii,1:2) maxZ+1];
for jj=1:size(fv.faces,1)
v=fv.vertices(fv.faces(jj,:),:);
if all(v(:,3)<ray(1,3))
continue;
end
isin=mollerTrumbore(ray, fv.vertices(fv.faces(jj,:),:));
counts(ii)=counts(ii)+isin;
end
end
in=mod(counts,2);
end
来自 FileExchange,稍作修改:
function [flag, u, v, t] = mollerTrumbore (ray,tri)
% Ray/triangle intersection using the algorithm proposed by Moller and Trumbore (1997).
%
% IMPORTANT NOTE: Assumes infinite legth rays.
% Input:
% ray(1,:) : origin.
% d : direction.
% tri(1,:), tri(2,:), tri(3,:): vertices of the triangle.
% Output:
% flag: (0) Reject, (1) Intersect.
% u,v: barycentric coordinates.
% t: distance from the ray origin.
% Author:
% Jesus Mena
d=ray(2,:)-ray(1,:);
epsilon = 0.00001;
e1 = tri(2,:)-tri(1,:);
e2 = tri(3,:)-tri(1,:);
q = cross(d,e2);
a = dot(e1,q); % determinant of the matrix M
if (a>-epsilon && a<epsilon)
% the vector is parallel to the plane (the intersection is at infinity)
[flag, u, v, t] = deal(0,0,0,0);
return;
end
f = 1/a;
s = ray(1,:)-tri(1,:);
u = f*dot(s,q);
if (u<0.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
r = cross(s,e1);
v = f*dot(d,r);
if (v<0.0 || u+v>1.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
if nargout>3
t = f*dot(e2,r); % verified!
end
flag = 1;
return
end
只需生成您的积分:
yourboundaries=% get the range of your data from the STL file.
[x,y,z]=meshgrid(yourboundaries);
P=[x(:) y(:) z(:)];
in=inmesh(fv,P);
img=reshape(in,yourboundariesSize);