superficies - gráficos 3d en matlab
Interpolar la superficie del cilindro 3D en Matlab (4)
Un cilindro es la colección de todos los puntos equidistantes a una línea. Entonces, usted sabe que sus datos xx
, yy
y zz
tienen una cosa en común, y es que todos deben estar a la misma distancia de la línea de simetría. Puede usar eso para generar un cilindro nuevo (línea de simetría tomada para ser eje z en este ejemplo):
% best-fitting radius
% NOTE: only works if z-axis is cylinder''s 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)
Tengo un conjunto de datos que describe una nube de puntos de un cilindro 3D ( xx,yy,zz,C
):
y me gustaría hacer un diagrama de superficie a partir de este conjunto de datos, similar a este
Para hacer esto, pensé que podría interpolar mis datos dispersos usando TriScatteredInterp
en una grilla normal y luego TriScatteredInterp
usando 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
Esto funciona muy bien para objetos convexos y cóncavos, pero termina en esto para el cilindro:
¿Alguien puede ayudarme a cómo lograr una trama más agradable?
TriScatteredInterp es bueno para ajustar superficies 2D de la forma z = f (x, y), donde f es una función de un solo valor. No funcionará para adaptarse a una nube de puntos como la que tiene.
Dado que se trata de un cilindro, que es, en esencia, una superficie 2D, aún puede usar TriScatterdInterp si convierte a coordenadas polares y, por ejemplo, ajusta el radio en función del ángulo y la altura, algo así como:
% 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)
¿Has probado la triangulación de Delaunay?
http://www.mathworks.com/help/matlab/ref/delaunay.html
load seamount
tri = delaunay(x,y);
trisurf(tri,x,y,z);
También hay TriScatteredInterp
http://www.mathworks.com/help/matlab/ref/triscatteredinterp.html
ti = -2:.25:2;
[qx,qy] = meshgrid(ti,ti);
qz = F(qx,qy);
mesh(qx,qy,qz);
hold on;
plot3(x,y,z,''o'');
Creo que lo que estás buscando es la función de casco convexo . Vea su documentación.
K = convhull (X, Y, Z) devuelve el casco convexo tridimensional de los puntos (X, Y, Z), donde X, Y y Z son vectores de columna. K es una triangulación que representa el límite del casco convexo. K es de tamaño mtri-por-3, donde mtri es el número de facetas triangulares. Es decir, cada fila de K es un triángulo definido en términos de los índices de puntos.
Ejemplo en 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+'')
Usa la gráfica para trazar la salida de convhull en 2-D. Usa trisurf o trimesh para trazar la salida de convhull en 3-D.