Plot contour with "concave" XY coordinates
8 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Dennis Weber
le 5 Avr 2023
Commenté : Dennis Weber
le 6 Avr 2023
Hello
I have an array of XYZ coordinates and want to plot them using contourf, so I followed this guide: https://de.mathworks.com/matlabcentral/answers/814925-plots-using-contourf-in-matlab
This is the result. The red dots are a scatterplot of the XY coordinates and beyond the concave border of my data there is extrapolated garbage.
I assume this happens because of linspace, but what could I use instead? I could determine the Y border for every X and set the Z coordinate corresponding to each Y past that border to NaN, but there must be a better way.
This is the code and I have also attached the data points to this post:
clear
close all
load(websave('myFile', 'https://de.mathworks.com/matlabcentral/answers/uploaded_files/1346319/data.mat'))
xv = linspace(min(X), max(X),numel(X));
yv = linspace(min(Y), max(Y),numel(Y));
[Xm,Ym] = ndgrid(xv, yv);
Zm = griddata(X, Y, Z, Xm, Ym);
hold on
contourf(Xm,Ym,Zm,10);
scatter(X,Y,'red');
Please lend me your brain power, for mine is weak.
0 commentaires
Réponse acceptée
Cris LaPierre
le 5 Avr 2023
Modifié(e) : Cris LaPierre
le 5 Avr 2023
The interpolation employed by griddata is causing this. You could look into adjusting the method used, but I did not have much success. You have the data you want already, so if you can reshape it into a matrix, you can create the contour plot without needing to use griddata. You just need to put NaNs where you don't have data.
There is no slick function for this, so I took a brute force approach based on the fact that your X data seems to be regularly sampled, while Y and Z may vary. I used unique to find the indices of each X sampling, and used that to extract and reshape the Y and Z data from vectors into matrices. There might be better approaches to achieving the same end result.
load data.mat
[uX,ia,ic] = unique(X);
% Create X,Y, and Z matrices prepopulated with NaNs
myX = NaN(length(uX));
myY = NaN(length(uX));
myZ = NaN(length(uX));
% Fill in the matrices with the orginal values
for r = 1:length(ia)
myX(1:sum(ic==r),r) = X(ic==(r));
myY(1:sum(ic==r),r) = Y(ic==(r));
myZ(1:sum(ic==r),r) = Z(ic==(r));
end
% Visualize the result
figure
contourf(myX,myY,myZ)
hold on
scatter(X,Y,'red');
hold off
Plus de réponses (1)
Bjorn Gustavsson
le 5 Avr 2023
Modifié(e) : Cris LaPierre
le 5 Avr 2023
NOTE: edited so that the code runs here and displays the results CL
The problem happens because griddata (and both scatteredInterpolant and triscatteredInterp) produce a triangulation with a convex perimeter.
If you switch to use an explicit delaunay-triangulation and use tricontour instead you might evade that filling between your concave boundary and the default convex one. But that might require some handcraft-work to get right.
load data.mat
tri = delaunay(Y,X);
plot(X,Y,'ro')
hold on
for i1 = 1:numel(X)
text(X(i1)+50,Y(i1)+5,num2str(i1))
end
% manual identification of the concave part of the perimeter
idxConcave = [70 78 85 91 97 102 107 112 116 120 124 128 131 134];
tri3 = tri;
% if all three corners of a triangle belong to the concave perimeter
for i1 = size(tri3):-1:1
idxRM(i1) = numel(intersect(tri3(i1,:),idxConcave))==3;
end
% I assume that you want them gone
tri3(idxRM,:) = [];
triplot(tri3, X, Y,'r')
tricontour(tri3,X,Y,Z,linspace(min(Z),max(Z),8))
pause(2)
clf
tricontour(tri3,X,Y,Z,linspace(min(Z),max(Z),8))
hold on
plot(X,Y,'k.')
Here I've used the tricontour-function (contour-plot-for-scattered-data by Duane Hanselman), hopefully you can find a similar tool that make filled contours.
HTH
Voir également
Catégories
En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!