Plot contour with "concave" XY coordinates

7 Ansichten (letzte 30 Tage)
Dennis Weber
Dennis Weber am 5 Apr. 2023
Kommentiert: Dennis Weber am 6 Apr. 2023
I have an array of XYZ coordinates and want to plot them using contourf, so I followed this guide:
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:
close all
load(websave('myFile', ''))
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
Please lend me your brain power, for mine is weak.

Akzeptierte Antwort

Cris LaPierre
Cris LaPierre am 5 Apr. 2023
Bearbeitet: Cris LaPierre am 5 Apr. 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));
% Visualize the result
hold on
hold off
  1 Kommentar
Dennis Weber
Dennis Weber am 6 Apr. 2023
Thank you, this is just what I need. contourf seems to do some interpolation with the colors and levels itself, because this looks very similar but the individual datapoints are a lot more coarse.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Bjorn Gustavsson
Bjorn Gustavsson am 5 Apr. 2023
Bearbeitet: Cris LaPierre am 5 Apr. 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);
hold on
for i1 = 1:numel(X)
% 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;
% I assume that you want them gone
tri3(idxRM,:) = [];
triplot(tri3, X, Y,'r')
hold on
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.
  1 Kommentar
Dennis Weber
Dennis Weber am 6 Apr. 2023
Thank you for your work, but this does not look that good, which is a problem because these graphs are for my thesis.

Melden Sie sich an, um zu kommentieren.


Mehr zu Contour Plots finden Sie in Help Center und File Exchange




Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by