# Plot 3D surface within nonlinear bounds

11 views (last 30 days)
Patrick on 27 Jun 2024
Commented: Mathieu NOE on 2 Sep 2024 at 9:20
Let's say I have bounds as follows in the 2D plot below:
xmin1 = 0; xmax1 = 1; xmax2 = 2;
ymin1 = @(x)0.25* x.^2; ymax1 = @(x) x.^(1/3);
x1 = 0:0.05:1; x2 = 1.05:0.05:2; xAll = 2:-0.05:0;
yTop1 = ymax1(x1); yTop2 = ones(1,length(x2)); yBot = ymin1(xAll);
figure
fill([x1 x2 xAll],[yTop1 yTop2 yBot],'b')
I want to plot surf() with , but only in the bounds above. That's to say, the projection of the surface plot matches the 2D fill above. How do I program this?
Just adding the surface with fill for reference:
fun = @(x,y) sin(4.*x) + y.^2 + 2;
[X,Y] = meshgrid(0:0.05:2,0:0.05:1);
Z = fun(X,Y);
figure
surf(X,Y,Z); hold on
fill([x1 x2 xAll],[yTop1 yTop2 yBot],'b'); hold off

Abhinaya Kennedy on 27 Jun 2024
To plot the surface only within the specified bounds, you need to mask the values outside the bounds. This can be achieved by setting the Z values to NaN where the points fall outside the desired region. Here's how you can do it:
1. Define the bounds as logical conditions.
2. Apply these bounds to mask out the unwanted parts of the surface.
xmin1 = 0;
xmax1 = 1;
xmax2 = 2;
ymin1 = @(x) 0.25 * x.^2;
ymax1 = @(x) x.^(1/3);
x1 = 0:0.05:1;
x2 = 1.05:0.05:2;
xAll = 2:-0.05:0;
yTop1 = ymax1(x1);
yTop2 = ones(1, length(x2));
yBot = ymin1(xAll);
% Define the function
fun = @(x, y) sin(4 .* x) + y.^2 + 2;
% Create meshgrid
[X, Y] = meshgrid(0:0.05:2, 0:0.05:1);
Z = fun(X, Y);
% Mask Z values outside the bounds
% Apply the bounds to create the mask
for i = 1:length(X(:))
x = X(i);
y = Y(i);
if (x >= xmin1 && x <= xmax1 && y >= ymin1(x) && y <= ymax1(x)) || ...
(x > xmax1 && x <= xmax2 && y >= ymin1(x) && y <= 1)
end
end
% Plot the surface
figure
surf(X, Y, Z);
hold on
% Plot the 2D fill for reference
fill([x1 x2 xAll], [yTop1 yTop2 yBot], 'b');
hold off
• The "mask" array is created to identify the points within the specified bounds.
• The Z values outside the bounds are set to "NaN" to mask them.

Mathieu NOE on 27 Jun 2024
hello
this is a job for inpolygon
as you have already created the x,y data defining this polygon , the answer is quite simple to implement :
NB I have slightly modified your code to use xmax1 and xmax2 instead of hard coded 1's and 2's in multiple locations
xmin1 = 0;
xmax1 = 1;
xmax2 = 2;
%% main code
ymin1 = @(x)0.25* x.^2;
ymax1 = @(x) x.^(1/3);
% slightly modified these lines (1 replaced by xmax1, 2 replaced by xmax2);
dx = 0.05;
x1 = 0:dx:xmax1;
x2 = xmax1+dx:dx:xmax2;
xAll = xmax2:-dx:0;
yTop1 = ymax1(x1);
yTop2 = ones(1,length(x2));
yBot = ymin1(xAll);
% create polygon x,y data
xx = [x1 x2 xAll];
yy = [yTop1 yTop2 yBot];
fun = @(x,y) sin(4.*x) + y.^2 + 2;
[X,Y] = meshgrid(0:dx:xmax2,0:dx:xmax1); % (1 replaced by xmax1, 2 replaced by xmax2);
Z = fun(X,Y);
IN = inpolygon(X,Y,xx,yy);
figure
Z(~IN) = NaN; % remove Z data outside polygon
surf(X,Y,Z); hold on
plot(xx,yy,'b')
hold off
##### 3 CommentsShow 1 older commentHide 1 older comment
Patrick on 30 Aug 2024 at 21:18
Yeah, this works well. Thanks
Mathieu NOE on 2 Sep 2024 at 9:20
I'm glad it does.... in fact it was a polite way to ask you if you would consider accepting my answer...:)
tx !