jmlarson
jmlarson

Reputation: 978

MATLAB contour sharp corners

MATLAB contour plots appear to round corners, even when they should not be rounded.

In the plot

num_incs = 1000;
x = linspace(-1,1,num_incs);
[Xa,Ya] = meshgrid(x,x);
Z = abs(Xa) + abs(Ya);

contour(Xa,Ya,Z,20,'LineWidth',4);

one-norm plot

the corners are rounded. Is there a way to turn off automatic rounding in order to make the corners "sharp"?

I've tried changing the renderer, but to no affect. Also, turning off graphics smoothing with

set(gcf,'GraphicsSmoothing','off'); does not produce sharp corners.

EDIT: Note that on Matlab 2020b with num_incs = 1001 (or 3), I still get rounded corners: enter image description here

EDIT 2: I'm trying to access and modify the LineJoin property:

num_incs = 3;
x = linspace(-1,1,num_incs);
[Xa,Ya] = meshgrid(x,x);
Z = abs(Xa) + abs(Ya);

[C,hContour] = contour(Xa,Ya,Z,20,'LineWidth',4);

drawnow;
for i = 1:length(hContour.EdgePrims)
    hContour.EdgePrims(i).LineJoin = deal('miter');
    hContour.EdgePrims(i).LineWidth = 1; % to see what is being adjusted
end

but this only affects the "outer" lines. This approach was inspired by this post.

Conclusion:

https://stackoverflow.com/a/68533356/3385432

Upvotes: 1

Views: 372

Answers (2)

Cris Luengo
Cris Luengo

Reputation: 60504

You can set the LineJoin property of the lines to 'miter' to get sharp corners:

[C,h] = contour(Xa,Ya,Z,20, 'LineWidth',4);
draw now
set(h.EdgePrims,'LineJoin','miter')

By default this property is 'round'.

But be aware that the sharp corners produced can be unreasonably long, depending on the angle between the two lines meeting, and leading to misinterpretation of the data. A third option is 'chamfer', which gives sharp corners but cuts them off if they become too large.

Upvotes: 1

Hoki
Hoki

Reputation: 11802

The choice of renderer may affect how the antialiasing will be applied to the drawn lines, but in your case the rounded corner effect is simply because no data is defined at the coordinates which should be the actual corners.

If you zoom in on any of your "corners", you'll notice that there is no point defined for all the x=0 points, (nor for all the y=0). To overcome that, Matlab draws a line between the two closest defined points:

corner not defined

This is because of the way you define your grid. By choosing an even number of points (you chose 1000) over an interval, you can never have a point defined right at the center of the interval. To have the center point of the interval defined, you have to use an odd number of points.

The table below show the grid Ya close to the transition. You'll notice that the values go from negative to positive but there is no point defined at y=0:

table

To demonstrate without having to zoom in too much, we can use a lower number of points. Observe the difference between the 2 graphs below, they use the same code except for the first line. On the left I have used num_incs = 10;, while on the right I used num_incs = 11;:

odd and even


So in your case, use num_incs = 1001; and your corners should diseapear. Or if your example was actually your case use, notice that for such a simple shape you can get exactly the same visual result with num_incs = 3;. This only defines the necessary corner points, which are the start and stop of each line (and do not use the unnecessary intermediate points on a line).

simplest

Upvotes: 1

Related Questions