简体   繁体   English

使用Matlab在贴片表面显示3D数据

[英]Showing 3D data on a patch surface with Matlab

I want to show, with Matlab, a temperature distribution on an object surface. 我想用Matlab显示物体表面的温度分布。

I've got a 3D data in the form of (x, y, z, V) vectors. 我有(x,y,z,V)向量形式的3D数据。 I would like to show this object in Matlab, with the colour representing the local total "value". 我想在Matlab中显示该对象,其颜色代表本地总的“值”。

I can export the object as an STL file. 我可以将对象导出为STL文件。 It can be shown easily using the STL plotting (see stldemo ): 使用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');

To colour it according to (x,y,z,V), I need to attach each (x, y, z) point to a vertex in the patch (the nearest one would work). 要根据(x,y,z,V)为它着色,我需要将每个(x,y,z)点附加到面片中的一个顶点上(最接近的那个会起作用)。 If there are many (x,y,z) points for which a single STL vertex is the nearest, I add up the corresponding V values for that vertex. 如果有多个(x,y,z)点,其中单个STL顶点最近,那么我将为该顶点求和相应的V值。

The number of vertices is thousands. 顶点数为数千。 The number of (x, y, z) points is also large. (x,y,z)点的数量也很大。 So doing a loop through (x, y, z) points and then an internal loop over vertices to find the nearest one (which involves calculating distances between points) is out of question. 因此,毫无疑问,需要遍历(x,y,z)点,然后在顶点上进行内部循环以找到最接近的点(这涉及到计算点之间的距离)。 Is there any smart way to do it quickly? 有什么聪明的方法可以快速地做到这一点?

Note: I cannot control the location of the data points, they are defined by an external program. 注意:我无法控制数据点的位置,它们是由外部程序定义的。 The STL points are controlled by another external program. STL点由另一个外部程序控制。 So I have to marry two different point sets. 所以我必须嫁给两个不同的观点集。

Here is the code illustrating what I want to achieve, with 4 vertices and 3 data points: 这是说明我要实现的代码,具有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';

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 ?). 将点的体积标量值(在您的情况下为Temperature)附加到相邻点是一项棘手的练习,需要复杂的for循环并定义特殊情况规则(在您的情况下,您希望将2个不同的点的值附加到同一点补丁顶点,如果要附加的两个值不同怎么办?您平均吗?丢弃?)。

A safer approach is to re-interpolate your temperature field over your object surface. 一种更安全的方法是在物体表面上重新插入温度场。 the function griddata can do that for you. 函数griddata可以为您完成此任务。

First I had to define a scalar field. 首先,我必须定义一个标量字段。 Since I do not have your temperature data, I use the flow function from Matlab. 由于我没有温度数据,因此使用Matlab的flow函数。 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 . 这给了我每个坐标x, y, z的标量场v (流量值,但可以说是你的温度)。

流

Then I created and introduced a 3D patch which will be your object. 然后,我创建并介绍了一个3D补丁,它将成为您的对象。 I chose a sphere but any 3D patch will work the same way. 我选择了一个球体,但是任何3D补丁都将以相同的方式工作。 The code to get the sphere as a patch is borrowed from surf2patch 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 . 在以下代码中, v是在坐标x, y, z处的标量场(对您而言的温度)的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 如果您想单独观察面片,则可以删除切片平面

最终的

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

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