MATLAB Answers

1

ASCII STL to image

Asked by Matlab2010 on 16 Jun 2014
Latest activity Commented on by Matlab2010 on 17 Jun 2014
I have been trying to use import_stl_fast to create an image (<http://www.cs.technion.ac.il/~gershon/EscherForReal/PenroseII.gif>) from an STL file (<http://www.cs.technion.ac.il/~gershon/EscherForReal/PenroseTriangleStl1.zip)>.
When I try and run the below code, it fails on axis.m and also, the image generated looks nothing like the intended image.
Any help much appreciated.
fv= cell(1,3);
[fv{1},fv{2},fv{3}] = import_stl_fast(file,1);
patch(fv,'FaceColor', [0.8 0.8 1.0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
camlight('headlight');
material('dull');
view([-135 35]);
axis('image');

  2 Comments

Geoff Hayes
on 16 Jun 2014
What is fv? How are the outputs from the import_stl_fast used in the subsequent lines of code? I think that there might be a line missing to populate fv with that data.
Matlab2010 on 16 Jun 2014
apologies geoff - typo on my part. Please have a look now.

Sign in to comment.

Tags

No tags entered yet.

1 Answer

Geoff Hayes
Answer by Geoff Hayes
on 16 Jun 2014
Edited by Geoff Hayes
on 16 Jun 2014
 Accepted Answer

This is a neat question. I'm not sure if you tried this or not, but a first step might have been to test out the stl to make sure it displays a Penrose Triangle (it does, I downloaded a free STL viewer and it looked fine).
I think that you are pretty close to having the correct code (though the first input to patch, fv, is invalid, or at least I couldn't get it to work correctly). Details on the patch function can be found here http://www.mathworks.com/help/matlab/ref/patch.html. Note that for 3D images, it states
patch(X,Y,Z,C) creates a patch in 3-D coordinates. If the coordinate data does not define closed polygons, patch closes the polygons . . . a patch object is one or more polygons defined by the coordinates of its vertices.
So four inputs are required for the 3D image - (paraphrasing from the link) the elements of X,Y and Z specify the vertices of a polygon. If X,Y and Z are m-by-n matrices, MATLAB draws n polygons with m vertices. C determines the color of the patch.
The import_stl_fast function has a second mode (2) that returns the vertices (and triangular norms) from the ASCII STL file, so if we do that (instead of getting the points, triangles and norms) it may be a little easier to plot the Penrose Triangle
[vertices,norms] = import_stl_fast(file,2);
The trick is to take vertices and put it in a format that is applicable to patch. From above, if the X,Y, and Z matrices are mxn, then n polygons with m vertices will be drawn. Since we are drawing triangles (as read in from the STL file) we need to initialize the matrices to be 3xn as each of our polygons have three vertices
n = length(vertices)/3;
X = reshape(vertices(:,1),3,n);
Y = reshape(vertices(:,2),3,n);
Z = reshape(vertices(:,3),3,n);
C = zeros(3,n); % only size matters here, not content since you
% are defining colour
A great reference was http://www.mathworks.com/matlabcentral/fileexchange/41910-function-for-importing-and-plotting-stl-files-in-matlab which did something similar but on a triangle-by-triangle basis.
Then you can call patch similar to what you did
patch(X,Y,Z,C,'FaceColor', [0.8 0.8 1.0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
camlight('headlight');
material('dull');
view([-135 35]);
axis('image');
Try the above and see what happens!
EDIT a note on use of reshape: the vertices matrix has three columns for each of the x,y and z coordinates of a vertex. We take each column that is a 20157x1 vector and re-shape it (without any loss of data) into a 3x6719 matrix.

  3 Comments

Matlab2010 on 17 Jun 2014
Thank you - that's a great answer!
I have one follow up question - How can I make the output image look like this one: www.cs.technion.ac.il/~gershon/EscherForReal/PenroseII.gif in terms of the colouring and angle. I have been playing around with Patch and the colouring terms but to no avail.
I would also be interested in an image that used shading to merge the colours depending on their location - (for example see this image: http://4g-portal.com/wp-content/uploads/2013/03/Matlab.png)
many thanks!!!
myStr = 'D:\blah\PenroseTriangle.stl';
[vertices, norms] = import_stl_fast(myStr,2);
n = length(vertices)/3;
X = reshape(vertices(:,1),3,n);
Y = reshape(vertices(:,2),3,n);
Z = reshape(vertices(:,3),3,n);
C = zeros(3,n);
figure;
set(gcf, 'Color', 'white');
patch(X,Y,Z,C, 'FaceColor', [0.8 0.8 1.0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'phong', ...
'AmbientStrength', 0.15);
colormap('hsv');
shading('interp');
camlight('headlight');
material('shiny');
view([-135 35]);
axis('image');
axis('off');
Geoff Hayes
on 17 Jun 2014
To get something similar to the colours in your link will require some guesswork or understanding of how the vertices in the file are laid out (or sorted). Here is something for you to start with, that patches three sets of the vertices in three different colours
strt=1;
stop=6000;
patch(X(:,strt:stop),Y(:,strt:stop),Z(:,strt:stop),C(:,strt:stop),...
'FaceColor', [0 0 1], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
strt=6001;
stop=6299;
patch(X(:,strt:stop),Y(:,strt:stop),Z(:,strt:stop),C(:,strt:stop),...
'FaceColor', [0 1 0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
strt=6300;
stop=6719;
patch(X(:,strt:stop),Y(:,strt:stop),Z(:,strt:stop),C(:,strt:stop),...
'FaceColor', [1 0 0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.15);
It is not quite the same (as the green and red merge) so you will have to figure out how the next steps.
As for your second question, you may want to post that separately or check the File Exchange.
Matlab2010 on 17 Jun 2014
excellent - thank you so much!

Sign in to comment.