我想用Matlab显示物体表面的温度分布。
我以(x,y,z,V)向量的形式获得了3D数据。我想在Matlab中显示这个对象,颜色代表当地的总和"值"。
我可以将对象导出为STL文件。使用STL绘图可以很容易地显示它(参见stldemo):
fv = stlread('file.stl');
patch(fv, 'EdgeColor', 'none', 'FaceLighting', 'gouraud', 'AmbientStrength', 0.15, 'FaceColor', [0.8 0.8 1.0]);
camlight('headlight');
material('dull');
要根据(x,y,z,V)对其进行着色,我需要将每个(x,y,z)点附加到贴片中的顶点(最近的一个可以工作)。如果有多个(x,y,z)点,单个STL顶点最近,我将为该顶点添加相应的V值。
顶点数量为数千。 (x,y,z)点的数量也很大。因此,通过(x,y,z)点进行循环,然后在顶点上进行内部循环以找到最近的点(这涉及计算点之间的距离)是不可能的。有没有聪明的方法可以快速完成?
注意:我无法控制数据点的位置,它们是由外部程序定义的。 STL点由另一个外部程序控制。所以我必须结婚两个不同的点集。
以下代码说明了我想要实现的目标,包括4个顶点和3个数据点:
% Create patch
figure;
p = patch;
colorbar
p.Vertices = [...
0, 0, 0; ...
1, 0, 0; ...
1, 1, 0;
0, 1, 0];
p.Faces = [ ...
1, 2, 3; ...
1, 3, 4];
% Data points
x = [0.1, 0.1, 0.25];
y = [0.01, 0.02, 0.75];
z = [0.01, 0.2, -0.01];
v = [1, 1, 1];
p.FaceVertexCData = zeros(size(p.Vertices, 1), 1);
% Point 1 (0.1, 0.01, 0.01) is closest to vertex 1 (0, 0, 0). Its value
% goes to vertex 1.
p.FaceVertexCData(1) = p.FaceVertexCData(1) + v(1);
% Point 2 (0.1, 0.02, 0.2) is also closest to vertex 1 (0, 0, 0). Its
% value also goes to vertex 1
p.FaceVertexCData(1) = p.FaceVertexCData(1) + v(2);
% Point 3 (0.25, 0.75, -0.01) is closest to vertex 4 (0, 1, 0). Its power
% goes to vertex 4.
p.FaceVertexCData(4) = p.FaceVertexCData(4) + v(3);
% Other vertices are left with 0.
p.FaceColor = 'interp';
答案 0 :(得分:2)
Attaching a volume scalar value (of Temperature in your case) of a point to a neighbouring point is a tricky exercise, requires complex for
loops and defining special case rules (in your case you wanted to attach the value of 2 different points to the same patch vertex, what if the 2 values to attach are different? Do you average? discard ?).
A safer approach is to re-interpolate your temperature field over your object surface. the function griddata
can do that for you.
First I had to define a scalar field. Since I do not have your temperature data, I use the flow
function from Matlab. I generated a scalar field the same ways than in this article: flow data.
This gave me a scalar field v
(flow value but let's say it's your temperature) at for every coordinates x, y, z
.
Then I created and introduced a 3D patch which will be your object. I chose a sphere but any 3D patch will work the same way.
The code to get the sphere as a patch is borrowed from surf2patch
you will have to offset and inflate the sphere to get it exactly as in the figure below
Now is the interesting bit. In the following code, v
is the value of the scalar field (temperature for you) at the coordinates x, y, z
.
%% // Extract patch vertices coordinates in separate variables
xp = fv.vertices(:,1) ;
yp = fv.vertices(:,2) ;
zp = fv.vertices(:,3) ;
%% // interpolate the temperature field over the patch coordinates
Tpv = griddata(x,y,z,v,xp,yp,zp) ;
%% // Set the patch color data to the new interpolated temperature
set(hp,'FaceVertexCData',Tpv) ;
And your object surface is now at the right interpolated temperature:
you can delete the slice plane if you want to observe the patch alone