Plot contour with "concave" XY coordinates
7 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Dennis Weber
el 5 de Abr. de 2023
Comentada: Dennis Weber
el 6 de Abr. de 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 comentarios
Respuesta aceptada
Cris LaPierre
el 5 de Abr. de 2023
Editada: Cris LaPierre
el 5 de Abr. de 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
Más respuestas (1)
Bjorn Gustavsson
el 5 de Abr. de 2023
Editada: Cris LaPierre
el 5 de Abr. de 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
Ver también
Categorías
Más información sobre Creating and Concatenating Matrices en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!