146 views (last 30 days)

Hi everybody,

I used the following codes to extract X,Y,Z coordinates from a contour. When I ran it in MATLAB 2013a, it works. But when I ran it in MATLAB 2016a, it doesn't work. I found that the codes is very sensitive to MATLAB version. Can anybody tell me how to solve this problem? Or are there any other MATLAB codes that serve the similar function? The code is from this link:

Star Strider
on 19 Apr 2017

This works in R2017a, so it should also work for R2016a.

Example —

f = @(x,y) x.^2 - y.^2; % Your Function

x = linspace(-10, 10); % X-Range

y = linspace(-10, 10); % Y-Range

[X,Y] = meshgrid(x,y); % Create Matrix Arguments

figure(1)

[C,h] = contour(X, Y, f(X,Y));

grid

Lvls = h.LevelList;

for k1 = 1:length(Lvls)

idxc{k1} = find(C(1,:) == Lvls(k1));

Llen{k1} = C(2,idxc{k1});

conturc{k1,1} = C(:,idxc{k1}(1)+1 : idxc{k1}(1)+1+Llen{k1}(1)-1);

conturc{k1,2} = C(:,idxc{k1}(2)+1 : idxc{k1}(2)+1+Llen{k1}(2)-1);

end

figure(2)

plot(conturc{3,1}(1,:), conturc{3,1}(2,:))

grid

The contour data now are a (2xN) vector created by horizontally concatenating the (x,y) coordinates of each contour line. The segments are created each as:

C = [Level x-coordinates; Length y-coordinates]

so the first column of each segment are the ‘Level’ and the ‘Length’ of the segment. The second output are the properties of the plot.

My code first plots the contour function, returning both outputs. It then uses the ‘LevelList’ property to return the plotted levels, and then uses these in the loop to find the start indices of the segments in the ‘C’ matrix in the ‘idxc’ cell array, and the number of elements in each contour segment in the ‘Llen’ cell array. It then uses these to extract the x (first row) and y (second row) coordinates for each contour segment in the ‘conturc’ cell array. The z-coordinates are the levels. They do not appear in the cell arrays, but correspond to the values in the ‘Lvls’ vector.

The plot in figure(2) is not necessary for the code. It shows how to get the data from the cell arrays (in this instance the third cell in the first group), and that the extracted values are correct.

This turned out to be an interesting adventure!

Star Strider
on 19 Apr 2017

My pleasure.

As of R2014b, graphics in MATLAB changed from the original handle graphics, known now as HG1, to a second-generation version with significant changes, known as HG2. The transition was significant, and ‘broke’ a lot of pre-existing code in many graphics functions on the File Exchange and in MATLAB Answers.

There are no other functions that I am aware of that can extract the data from the R2014b and later contour function, although I did not search the File Exchange. I wrote this code specifically to Answer your Question., and is original to me and this Answer.

If my Answer solved your problem, please Accept it!

——————

EDIT —

Additionally, if you want to include the ‘Lvls’ variable with each cell array element, it is easy to add it:

for k1 = 1:length(Lvls)

idxc{k1} = find(C(1,:) == Lvls(k1));

Llen{k1} = C(2,idxc{k1});

conturc{k1,1} = C(:,idxc{k1}(1)+1 : idxc{k1}(1)+1+Llen{k1}(1)-1);

conturc{k1,2} = C(:,idxc{k1}(2)+1 : idxc{k1}(2)+1+Llen{k1}(2)-1);

conturc{k1,3} = Lvls(k1);

end

To use it with the rest of your data, address it as you would the other data:

figure(2)

plot(conturc{3,1}(1,:), conturc{3,1}(2,:), '-b')

hold on

plot(conturc{3,2}(1,:), conturc{3,2}(2,:), '-b')

hold off

legend(sprintf('Level = %.1f', conturc{3,3}), 'Location','E')

grid

This uses the legend function, and can be adapted to the text function if you want to.

Sign in to comment.

Rik
on 19 Apr 2017

The culprit is in this code snippet:

[c,h]=contour(X,Y,Z,v);

xcg=get(get(h,'children'),'xdata');

ycg=get(get(h,'children'),'ydata');

The form in which h is returned is slightly different between 2013a and 2016a. The first returns a handle, the second an object. Usually this doesn't matter, but it does in this case.

I compared the results from [c,h]=countour(flipud(P)) between 2012b and 2017a (after load penny;). Apparently, the newer object no longer has a child for each contour element, so you will have to put in some effort to add in the NaNs yourself to get back the original behavior.

Rik
on 19 Apr 2017

Star Strider did most the heavy lifting for you.

The conturc cell array is almost equal to the xcg and ycg variables that you can find in that FEX submission. You only need to add a NaN to the end of each matrix and split conturc. In short, replace these lines

[c,h]=contour(X,Y,Z,v);

xcg=get(get(h,'children'),'xdata');

ycg=get(get(h,'children'),'ydata');

with these lines

[c,h]=contour(X,Y,Z,v);

%get the Matlab version, add 0.5 to the year for the b release

MatlabVersion=version('-release');

MatlabVersion=str2double(MatlabVersion(1:(end-1)))...

+0.5*strcmp(MatlabVersion(end),'b');

if MatlabVersion<=2014%2014a is somewhere around the switch in behavior

xcg=get(get(h,'children'),'xdata');

ycg=get(get(h,'children'),'ydata');

else

Lvls = h.LevelList;

conturc=cell(length(Lvls),2);%pre-allocate variable

for k1 = 1:length(Lvls)

idxc{k1} = find(c(1,:) == Lvls(k1));

Llen{k1} = c(2,idxc{k1});

conturc{k1,1} = C(:,idxc{k1}(1)+1 : idxc{k1}(1)+1+Llen{k1}(1)-1);

conturc{k1,2} = C(:,idxc{k1}(2)+1 : idxc{k1}(2)+1+Llen{k1}(2)-1);

end

conturc=conturc(:);

for n=1:length(conturc)

conturc{n}=[conturc{n} NaN(2,1)];%add a NaN column

end

xcg=conturc;%this is a copy, containing both x and y

ycg=conturc;%this is a copy, containing both x and y

for n=1:length(xcg)

xcg{n}=xcg{n}(1,:)';%remove y

ycg{n}=ycg{n}(2,:)';%remove x

end

end

Sign in to comment.

Sign in to answer this question.

Opportunities for recent engineering grads.

Apply Today
## 2 Comments

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/336169-how-to-extract-x-y-z-coordinates-from-a-contour#comment_789386

⋮## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/336169-how-to-extract-x-y-z-coordinates-from-a-contour#comment_789386

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/336169-how-to-extract-x-y-z-coordinates-from-a-contour#comment_796099

⋮## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/336169-how-to-extract-x-y-z-coordinates-from-a-contour#comment_796099

Sign in to comment.