Interpolate Triangular Grid - matlab

I have a triangular grid as used in trimesh where the z-coordinate is a (smooth) function of x,y. The triangulation is given by some index Matrix t, so I could display this piecewise linear approximation given by the grid as
trimesh(t,x,y,f(x,y))
Now I'd like to evaluate this apprixmation between the grid points i.e. in some general x0,y0. I am aware of griddata, but this function creates an new triangulation. I'd like to use the given triangulation t.

Given a triangulation created by delaunay :
tri = delaunay (X, Y);
and coordinates of a point to be interpolated as xi, yi.
Use tsearch* or pointLocation to find the triangle that contains the point:
idx = tsearch (X, Y, tri, xi, yi);
Extract indices of vertexes of the triangle:
pts= tri(idx, :);
Create a matrix that represents equation of a plane (triangle) given its 3 points:
m=[X(pts);Y(pts);Z(pts);ones(1,3)].';
Calculate z based on det(m)=0.**
z = (...
-xi*det(m(:,2:end)) + ...
yi*det([m(:,1) m(:,3:end)]) +...
det(m(:,1:end-1))...
)...
/ det([m(:,1:2) m(:,end)]);
*Here the Octave function tsearch is used that is deprecated in newer versions of MATLAB . Instead of it you can use pointLocation.
**Formula for calculating determinant of a [4 ,4] matrix can be found in Wikipedia.

Related

Plotting contour line from three matrices

I have two vectors A(1,512), B(1,8) , and one matrix C(8,512). I am trying to plot contour by using contour(X,Y,Z). I do not know to do it.
A vector represents distance, B vector is frequency, and C matrix is velocity.
This can be done by using function contourf(X,Y,Z)
C1=C';
contourf(B,A,C1);
Transposed of C used because length(B) must equal size(C,2) and length(A) must equal size(C,1)
I quote from the documentation:
contourf(X,Y,Z), contourf(X,Y,Z,n), and contourf(X,Y,Z,v) draw filled contour plots of Z using X and Y to determine the x and y values.

Finding the region in a Voronoi diagram that contains a point

I am trying to build a Voronoi diagram using the code in this link. However, I have a few points and want to know in which region they fall. This code, like the original function in MATLAB (i.e. voronoin) gives two outputs: [vornb,vorvx], one for the vertices and another one for the cells. So, I want to see which region of the Voronoi diagram the point (x, y, z) falls in.
I am actually looking for something like this region masking in 3D.
Regardless of whether you generate your Voronoi cells using the built-in voronoin (which takes an N-by-D matrix of points X as input) or polybnd_voronoi (the linked File Exchange submission for bounded Voronoi cells, which takes an additional M-by-D matrix of points BX defining a bounding convex polyhedron), you can compute which cell contains a given point [x y z] by using only those same input arguments.
For the bounded Voronoi cell case, you first need to determine if your point is inside the bounding convex hull or not. One way to do this is to create a Delaunay triangulation of the bounding points and use the pointLocation method to determine if the point is within the convex hull:
DT = delaunayTriangulation(BX);
cellIndex = pointLocation(DT, [x y z]);
If cellIndex is NaN, then the point is not within the boundary convex hull. Otherwise, it is in one of the Voronoi cells. To determine which, first consider that a Voronoi cell C{i} represents the set of all points that are closer to point X(i, :) than any other point in X. Therefore, to find out which cell a point [x y z] falls into you just have to find the point in X that it is closest to. You can do this using pdist2 and min like so:
[~, cellIndex] = min(pdist2(X, [x y z]));
If you don't have access to pdist2 (which is in the Statistics Toolbox), you can compute the distances yourself like so:
[~, cellIndex] = min(sqrt(sum(bsxfun(#minus, X, [x y z]).^2, 2)));
Now, cellIndex can be used as an index into the output arguments from voronoin or polybnd_voronoi to get the bounding Voronoi cell.
Generalize to multiple points:
You can generalize the above to more than just one point [x y z], which will allow you to create a 3D region mask:
[PX, PY, PZ] = meshgrid(...); % Generate regular points in a 3D volume
PXYZ = [PX(:) PY(:) PZ(:)]; % Combine them into one matrix
DT = delaunayTriangulation(BX); % Create triangulation for boundary
cellMask = pointLocation(DT, PXYZ); % Find points in boundary
index = ~isnan(cellMask); % Index of points in boundary
[~, cellMask(index)] = min(pdist2(X, PXYZ(index, :)), [], 1); % Find cell index
cellMask = reshape(cellMask, size(PX)); % Reshape mask to 3D
And the 3D mask cellMask will contain index values for points within Voronoi cells and NaN for points outside the bounding convex hull.

How to create a 2d color map plot from x and y coordinates and a vector of values?

I'm trying to plot a 2 dimensional signal on a specific plane in a 3d model. I have the matrix:
xyzp (nx3)
that contains all the points which are closest to the plane (e.g. when the plane is in the z direction, all the z coordinates are fairly similar).
and I have a vector:
signal (nx1)
that contains a value for each point in xyzp.
when I use:
"surf([xyzp(:,[1,2]),signal)" or "mesh([xyzp(:,[1,2]),signal])"
The plot I get doesn't look at all like the intersection of the plane with the model from any angle (I expected "view(2)" to show the signal in the Z direction), so I assume I didn't use the plot function correctly.
Can anyone show me an example? For instance - A circle on an xy plane with some random signal indicated by color
surf and mesh can be used when the points form a rectangular grid on the xy plane.
In the general case (points are arbitrarily placed), you can use scatter3. For purposes of illustration, consider the following example xyzp and signal:
[x y] = ndgrid(-1:.01:1);
x = x+.3*y; %// example values which do not form a rectangular grid
z = x+y; %// example z as a function of x, y
xyzp = [x(:) y(:) z(:)];
signal = z(:)+x(:)-y(:); %// example values
Then
scatter3(xyzp(:,1), xyzp(:,2), xyzp(:,3), 1, signal, '.');
produces the following figure.
Since scatter3 plots each point separately, the picture is not as smooth as it would be with surf. But this seems hard to improve if the coordinates do not a have any "structure" (as surf requires) .

B-spline fitting to 2D discrete data points (pixels of contour image)

I am trying to fit a B-spline to a set of ordered discrete data points which represent pixels of a contour extracted from an image.
While the below code works fine for some simple shapes, but not for others (please see attached image for examples). Why does this happen, and what would be a better way to approach this problem?
I am quite new to differential geometry, appreciate any insights or inputs. Thanks.
% data contains two columns representing x,y coordinates of pixels
x = data(:, 1);
y = data(:, 2);
plot(x, y, 'bo');
fittedmodel = fit(x, y, 'cubicinterp');
plot(fittedmodel, 'r-');
What went wrong?
You have two sets of numbers x and y with the same number of elements in both sets.
You assume:
a. That there is a function f such that f( x_i ) = y_i for all pairs x_i,y_i in your sets.
b. That the points in the set are ordered: that is, if you follow the curve of f(x) then x_i "comes before" x_{i+1}.
While these assumptions hold for the "correct fit" example you have. They are no longer valid for the "incorrect fit" example.
As you can see for yourself, the input contour on the top cannot be expressed as y = f(x) since there are values of x for which there are two possible corresponding values of y (see the definition of mathematical function). The fit you got is the closest thing to a mathematical function y = f(x) that can be given the pairs x,y you gave (the red curve has the property of each x having only one y value).
What can you do?
In most cases when you try and fit a 2D curve you search for a parametric curve: that is, you introduce an auxilary parameter t such that each point along the curve can be represented as [x(t), y(t)] for some 0<=t<=1.
Now, if assumption b holds (and by looking at your examples, I'm not certain it is), what you can do is
t = linspace( 0, 1, numel(x) ); % define the parameter t
fitX = fit( t, x, 'cubicinterp'); % fit x as a function of parameter t
fitY = fit( t, y, 'cubicinterp'); % fit y as a function of parameter t
plot( fitX, fitY, 'r-' ); % plot the parametric curve

Why not spherical plot? How to plot 3D-polar-plot in Matlab?

[r,t] = meshgrid(linspace(0,2*pi,361),linspace(0,pi,361));
[x,y]=pol2cart(sin(t)*cos(r),sin(t)*sin(r));
%[x,y]=pol2cart(r,t);
surf(x,y);
I played with this addon but trying to find an default function to for this. How can I do the 3D-polar-plot?
I am trying to help this guy to vizualise different integrals here.
There are several problems in your code:
You are already converting spherical coordinates to cartesian coordinates with the sin(theta)*cos(phi) and sin(theta)*sin(phi) bit. Why are you calling pol2cart on this (moreover, we're not working in polar coordinates!)?
As natan points out, there is no third dimension (i.e. z) in your plot. For unity radius, r can be omitted in the spherical domain, where it is completely defined by theta and phi, but in the cartesian domain, you have all three x, y and z. The formula for z is z = cos(theta) (for unit radius).
You didn't read the documentation for surf, which says:
surf(Z,C) plots the height of Z, a single-valued function defined over a geometrically rectangular grid, and uses matrix C, assumed to be the same size as Z, to color the surface.
In other words, your surf(x,y) line merely plots the matrix x and colors it using y as a colormap.
Here's the above code with the mistakes fixed and plotted correctly:
[f,t] = meshgrid(linspace(0,2*pi,361),linspace(0,pi,361));
x = sin(t)*cos(f);
y = sin(t)*sin(f);
z = cos(t);
surf(x,y,z)