Интерполировать поверхность 3D-цилиндра в Matlab

У меня есть набор данных, который описывает облако точек 3D-цилиндра (xx,yy,zz,C): 3D point cloud

и я хотел бы сделать поверхностный график из этого набора данных, подобный этому enter image description here

Чтобы сделать это, я подумал, что смогу интерполировать мои разбросанные данные с помощью TriScatteredInterp на регулярную сетку, а затем построить его с помощью surf:

F = TriScatteredInterp(xx,yy,zz);
max_x = max(xx); min_x = min(xx);
max_y = max(yy); min_y = min(yy);
max_z = max(zz); min_z = min(zz);
xi = min_x:abs(stepSize):max_x;
yi = min_y:abs(stepSize):max_y;
zi = min_z:abs(stepSize):max_z;
[qx,qy] = meshgrid(xi,yi);
qz = F(qx,qy);
F = TriScatteredInterp(xx,yy,C);
qc = F(qx,qy);

figure
surf(qx,qy,qz,qc);
axis image

Это хорошо работает для выпуклых и вогнутых объектов, но заканчивается в этом для цилиндра: enter image description here

Может ли кто-нибудь помочь мне в том, как добиться более приятного заговора?

Ответ 2

Я думаю, что вы задумываетесь о функции Convex hull. См. Его документацию.

K = convhull (X, Y, Z) возвращает трехмерную выпуклую оболочку точек (X, Y, Z), где X, Y и Z - векторы столбцов. K - триангуляция представляющий границу выпуклой оболочки. K имеет размер mtri-by-3, где mtri - число треугольных граней. То есть каждая строка K представляет собой треугольник, определенный в терминах точечных индексов.

Пример в 2D

xx = -1:.05:1; yy = abs(sqrt(xx));
[x,y] = pol2cart(xx,yy);
k = convhull(x,y);
plot(x(k),y(k),'r-',x,y,'b+')

enter image description here

Используйте график для построения вывода convhull в 2-D. Используйте trisurf или trimesh для построения вывода convhull в 3-D.

Ответ 3

Цилиндр представляет собой совокупность всех точек, эквидистантных к прямой. Знаете ли вы, что ваши данные xx, yy и zz имеют одну общую черту, и все они должны лежать на равном расстоянии от линии симметрии. Вы можете использовать это для создания нового цилиндра (линия симметрии, взятая в этом примере как ось z):

% best-fitting radius 
% NOTE: only works if z-axis is cylinder line of symmetry
R = mean( sqrt(xx.^2+yy.^2) );

% generate some cylinder
[x y z] = cylinder(ones(numel(xx),1));

% adjust z-range and set best-fitting radius
z = z * (max(zz(:))-min(zz(:))) + min(zz(:));
x=x*R;
y=y*R;

% plot cylinder
surf(x,y,z)

Ответ 4

TriScatteredInterp хорош для установки 2D-поверхностей вида z = f (x, y), где f - однозначная функция. Он не будет работать, чтобы соответствовать облако точек, как у вас.

Поскольку вы имеете дело с цилиндром, который, по существу, является двумерной поверхностью, вы все равно можете использовать TriScatterdInterp, если вы переходите в полярные координаты и, скажем, подгоняете радиус как функцию угла и высоты - что-то как:

% convert to polar coordinates:
theta = atan2(yy,xx);
h = zz;
r = sqrt(xx.^2+yy.^2);

% fit radius as a function of theta and h
RFit = TriScatteredInterp(theta(:),h(:),r(:));

% define interpolation points
stepSize = 0.1;
ti = min(theta):abs(stepSize):max(theta);
hi = min(h):abs(stepSize):max(h);
[qx,qy] = meshgrid(ti,hi);
% find r values at points:
rfit = reshape(RFit(qx(:),qy(:)),size(qx));
% plot
surf(rfit.*cos(qx),rfit.*sin(qx),qy)