Perspective and STLs: how to create thinning edges along a 3D shape?
3 ビュー (過去 30 日間)
古いコメントを表示
Hello kind people, I'm trying to create a program that uploads a STL image of a 3D object, have the user rotate the shape to whatever perspective, and then have it output a 2D image of that rotated shape. The catch here is that I want the lines closest to the viewpoint to be thick, and gradually thin out the farther away the edge is from the viewpoint.
I've put in a few basic GUI's guiding the user to upload the file and coded the lighting such that it would accomodate each time the user rotated the image.
I'm basically looking for a function to detect all vertices of the STL, detect the distance from the camera viewpoint, and then somehow create a thick to thin line gradient along the edges such that those edges closest to the camera are thickest and those farthest from the camera are thinnest.
%%Begin GUI
% --- Executes on button press in pushbutton1.
function x = Program()
Button1 = questdlg ('Specify image file?');
switch Button1
case 'Yes'
I = uigetfile ('*.stl*', 'Specify 3D image file');
figure
fv = stlread (I);
patch(fv,'FaceColor', [0.8 0.8 1.0], ...
'EdgeColor', 'none', ...
'FaceColor', [0.5,0.5,0.5], ...
'FaceLighting', 'flat', ...
'EdgeLighting', 'flat', ...
'AmbientStrength', 0.8);
h1 = rotate3d;
h1.ActionPostCallback = @onOrbit;
% Add a camera light, and tone down the specular highlighting
h2 = camlight('headlight');
material('dull');
% Fix the axes scaling, and set a nice view angle
axis('image');
view([-135 35]);
case 'No'
disp ('Operation terminated')
end
function onOrbit(obj,event_obj)
% obj handle to the figure that has been clicked on
% event_obj object containing struct of event data (same as the
% event data of the 'ActionPreCallback' callback)
camlight(h2,'left');
Button2 = questdlg ('Finalize image?');
switch Button2
case 'Yes'
%create function here that thins outermost edges to two pixels
%and maps the closest edges to ten pixels and gradually thins
%them out. The farther away from the camera the edges are, the
%thinner they should be. The edges closest to the camera face
%should be ten pixels and farthest away should be two pixels.
%This will probably require detecting all the vertices and
%defining vertices closest and farthest from the camera face.
%Then, defining edge thickness at intervals away from the
%camera face.
%capture 2d image of rotated 3d figure
fr=getframe(gcf); %need to capture frame of rotated image
%without axes
img=frame2im(fr);
imagesc(img); % <- or imagesc(ff.cdata);
assignin ('base', 'frameshot', img);
%Below is the code to thin a png image to one pixel:
% b= bwmorph(im2bw(-rgb2gray(im2double(frameshot))+1,0.5),'thin'...
% ,Inf);imagesc(frameshot)
disp ('Image finalized')
%Below is the code to enter in an image name and save
%data from a function to the workspace. This is not
%quite right yet.
%Button3 = uiputfile ('Specify folder to save')
% prompt = {'Enter image name:'};
% title = 'Image display - assignin';
% lines = 1;
% def = {};
% answer = inputdlg(prompt, title, lines, def);
% assignin('base', {}, fv);
case 'No'
disp ('Operation terminated')
end
end
end
0 件のコメント
採用された回答
Ahmet Cecen
2016 年 5 月 31 日
Simply writing:
R = view;
will yield a proper rotation matrix for the current view like:
0.4384 0.8988 0 -0.6686
-0.5534 0.2699 0.7880 -0.2523
-0.7083 0.3454 -0.6157 9.1495
0 0 0 1.0000
In theory, the following multiplication should yield what you are looking for:
scores = fv.vertices * R;
where the z component of scores should now give you the distance from the viewer. (In theory, don't have time to test.) We probably can't do this on a continuous basis, but you can group the vertices into say 10 bins, where the closest 10% is in bin 1, next 10% is in bin 2 etc. Then you can call patch(or maybe even line) 10 times to create the image wrapping in a for loop like:
for i=1:10
STUFF PLOT STUFF
patch(fv, ...,'LineWidth',i)
MORE STUFF
end
2 件のコメント
Ahmet Cecen
2016 年 6 月 1 日
Well you need to do vertices*R(1:3,1:3) to jump from the generalized matrix to 3d rotation. Vertices just needs to be x y z coordinates each row.
その他の回答 (0 件)
参考
カテゴリ
Help Center および File Exchange で Data Distribution Plots についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!