How to plot a surface with a texture map

Ander Biguri picture Ander Biguri · May 2, 2013 · Viewed 7.1k times · Source

I want to plot a surface with a texture map on it, but the conditions are not the "ideal" ones.

first lets explain what I have.

I have a set of points (~7000) that are image coordinates, in a grid. This points do NOT define perfect squares. IT IS NOT A MESHGRID. For the sake of the question, lets assume that we have 9 points. Lets ilustrate what we have with an image:

 X=[310,270,330,430,410,400,480,500,520]
 Y=[300,400,500,300,400,500,300,400,500]

enter image description here Lets say we can get the "structure" of the grid, so

 size1=3;
 size2=3;
 points=zeros(size1,size2,2)
 X=[310,270,330;
    430,410,400;
    480,500,520]
 Y=[300,400,500;
    300,400,500;
    300,400,500]
 points(:,:,1)=X;
 points(:,:,2)=Y;

And now lets say we have a 3rd dimension, Z.

EDIT: Forgot to add a piece if info. I triangulate the points in the image and get a 3D correspondence, so when displayed in a surface they don't have the X and Y coords of the image, for a simplification of the given data lets say X=X/2 Y=Y/3

And we have:

 points=zeros(size1,size2,3)
 Z=[300,330,340;
    300,310,330;
    290,300,300]

 surf(points(:,:,1)/2,points(:,:,2)/3,points(:,:,3))

enter image description here

What I want is to plot the surface in 3D with the image texture. Each element should have the texture piece that have in the first image.

This needs to work for huge datasheets. I don't specially need it to be fast.

related post (but I has a meshgrid as initial set of points) : Texture map for a 2D grid

PD: I can post original images + real data if needed, just posted this because i think it is easier with small data.

Answer

H.Muster picture H.Muster · May 7, 2013

You can use the texturemap property of surf which works with rectangular meshes as well as with non-rectangular ones.

Creating non-rectangular data points

% creating non-rectangular data points
[X, Y] = meshgrid(1:100, 1:100);
X = X+rand(size(X))*5; 
Y = Y+rand(size(X))*5; 

which results in the following data points:

enter image description here

Generating height data:

Z = sin(X/max(X(:))*2*pi).*sin(Y/max(Y(:))*2*pi);

enter image description here

Loading picture:

[imageTest]=imread('peppers.png');

enter image description here

and mapping it as texture to the mesh:

surf(X,Y,Z, imageTest, ...
     'edgecolor', 'none','FaceColor','texturemap')

enter image description here

Note that, for the sake of demonstration, this non-rectangular grid is quite sparsely populated which results in a rather jagged texture. With more points, the result gets much better, irrespective of the distortion of the grid points.

Note also that the number of grid points does not have to match the number of pixels in the texture image.

~edit~

If X and Y coordinates are only available for parts of the image, you can adjust the texture accordingly by

minX = round(min(X(:)));
maxX = round(max(X(:))); 
minY = round(min(Y(:)));
maxY = round(max(Y(:)));

surf(X,Y,Z, imageTest(minX:maxX, minY:maxY, :), ...
     'edgecolor', 'none','FaceColor','texturemap')