How can I set 'EdgeLighting' for a patch line across a surface, so it matches the surface lighting?
조회 수: 1 (최근 30일)
이전 댓글 표시
I'm plotting maps defined by a grid of [latitude, longitude, value] as a 3D globe using surf(). I want to add lines such as coastlines across the surface, and have these lines lit in the same manner as the surface.
Thanks to this answer I found I need to plot the lines as the edges of patches to enable the 'EdgeLighting' property, and then manually reset the 'VertexNormals' property of the lines to represent the normal vectors of the surface.
So far I've managed to calculate approximate surface normals at the line coordinates and the lines are now lit variably in space, but not in the same manner as the surface lighting it should match:
% The 2D elevation map of `peaks` projected onto a spheroid via a
% colatitude, longitude grid
phi = linspace(-pi,pi,41);
theta = linspace(0,pi,41);
[phi,theta] = meshgrid(phi,theta);
rho = 20 + peaks(41);
r = rho.*sin(theta);
x = r.*cos(phi);
y = r.*sin(phi);
z = rho.*cos(theta);
figure
s = surf(x,y,z, 'Facelighting', 'gouraud');
shading interp
axis equal
camlight('left', 'infinite')
% A 2D line projected across the surface of the spheroid
l_theta = linspace(pi/4,3*pi/4,50);
l_phi = linspace(-pi,pi,50);
l_rho = interp2(phi, theta, rho, l_phi, l_theta);
l_r = l_rho.*sin(l_theta);
l_x = l_r.*cos(l_phi);
l_y = l_r.*sin(l_phi);
l_z = l_rho.*cos(l_theta);
hold on
p = patch([l_x,nan],[l_y,nan],[l_z,nan],'k'); % NaNs gives a patch without a face
set(p, 'Edgecolor', 'w', 'Edgelighting' ,'gouraud', 'LineWidth', 3);
% Don't know the spheroid normal vectors at the line coordinates, so
% convert spheroid point cloud to alpha shape, then find nearest point of
% spheroid to points of line
shp = alphaShape(x(:),y(:),z(:));
idx = nearestNeighbor(shp, p.Vertices(1:end-1,1), p.Vertices(1:end-1,2), p.Vertices(1:end-1,3));
% Get surface normal vectors of spheroid points
[nx, ny, nz] = surfnorm(x,y,z);
% Set line vertex normal vectors to those of nearest spheroid vertex normal, repeat
% the last value for the patch coordinate NaNs added earlier
set(p, 'VertexNormals', [[nx(idx); nx(idx(end))], [ny(idx); ny(idx(end))], [ny(idx); nz(idx(end))]])
% Plot the normal vectors of the line and of then the surface...they don't match?
quiver3(p.Vertices(:,1), p.Vertices(:,2), p.Vertices(:,3), ...
p.VertexNormals(:,1), p.VertexNormals(:,2), p.VertexNormals(:,3))
quiver3(x,y,z,s.VertexNormals(:,:,1),s.VertexNormals(:,:,2),s.VertexNormals(:,:,3),'r')
hold off
How can I get line normal vectors parallel to the surface normal vectors?
Is there a better way to get the surface normals at my line coordinates?
I see my surface normals are defined inward, I know I can transpose x,y,z to x',y',z' to close the surface outward instead, but I can't seem to match line normals outward too.
댓글 수: 0
답변 (1개)
darova
2019년 7월 29일
Can you generate surface like this instead of 3D curve? Then you could just use surfnorm() again and extract normal vector you want
참고 항목
카테고리
Help Center 및 File Exchange에서 Surface and Mesh Plots에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!