ASCII STL to image
4 views (last 30 days)
Show older comments
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.
Accepted Answer
Geoff Hayes
on 16 Jun 2014
Edited: Geoff Hayes
on 16 Jun 2014
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
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.
More Answers (0)
See Also
Categories
Find more on Basic Display in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!