Simplest way to draw filled triangles in matlab - matlab

I have a set of triangles in the standard format used in matlab, i.e a 3XN list of indinces, and two vectors of length N, called X and Y for the x and y coordinates.
I have a scalar value associated with each triangle, in a vector C. I want to draw filled triangles where the color of each tri is determined by the vector C. I know I can use patch, but that would mean I need to iterate over all tris and call patch for each one, right?
Is there a better way?

Actually if you check the documentation for patch you'll notice it says
Create one or more filled polygons.
It also says
If X and Y are m-by-n matrices, MATLAB draws n polygons with m vertices.
C determines the color of the patch.
patch may actually be exactly what you want. You just need to put the x and y coordinates into 3xN matrices.

Related

Conversion between co-ordinate systems

I have a set of data coordinates in 3D with respect to an Origin, say O1, and another set of data that represents the same movements but in 2D with respect to an Origin, say O2. What can I do to calculate the transformations that are required to implement on the 3D set to be able to compare the data points(2D vs 3D) in a 2D frame?
Setup of data generation
If the measurements are at the same times, then the following might work. I have not actually tried it and make no claim that it is the best solution, but it seems doable. Basically, after adjusting the coordinates so that they have the same origin, you want to minimize the following 2-norm:
|| vec(A*x) - vec(P*B*y) ||
where x is the 2xN array of the 2-D locations, A is a 2x2 rotation matrix that rotates x by the unknown angle theta, P is a 2x3 projection matrix that projects a 3x1 vector onto its first two dimensions (viz., just throws out the third value), B is a 3x3 rotation matrix, and y is the 3xN array of the 3-D locations.
The unknowns in the above are theta in the 2-D rotation matrix, and the three rotation angles needed to define B. The four angles that minimize the above should (at least I think) give you the rotation matrices needed to align the coordinate systems.

Matlab Surface Plot

I have a set of data points, x, y, and z contained in a matrix, record.
In record, each row is a data-point where the first value is the x-coordinate, the second is the y-coordinate, and the third is the z-coordinate. I would like to represent this as a surface plot. I tried:
surf([record(:,1), record(:,2)], record(:,3))
But the results were not what I expected. Any advice?
Try this code for instance.
[x,y,z]=sphere(n);
surf(x,y,z);
axis equal
This code plots with 3 parameters surf the surface of a sphere. As far as I understood from your code you want to utilize the 2 parameters surf for your application.
According to surf help when utilizing 2 parameters surf:
surf(Z) and surf(Z,C) use x = 1:n and y = 1:m. In this case,
the height, Z, is a single-valued function, defined over a
geometrically rectangular grid.
where:
The color scaling is determined
by the range of C
It just doesn't look like you want to utilize C as the color scaling parameter. For better understanding, can you send the contents of record for reference?

MeshGrid for Triangle Elements

I want to build a contourf plot of a certain aspect in my Plate. The plate is divided in triangle elements, which I have the coordinates (x,y) of each knot of the triangle.
So, How can I make a meshgrid for my knots so I can make my contourf plot?? I have the coordinates of everything and have the value of my function Z in each knot. (I'm a beginner in Matlab, sorry for this "basic" question)
If your goal is just to visualise the triangles then there is another way that's probably simpler and more robust (see the end of this post).
If you definitely need to generate contours then you will need to interpolate your triangular mesh over a grid. You can use the scatteredInterpolant class for this (documentation here). It takes the X and Y arguments or your triangular vertices (knots), as well as the Z values for each one and creates a 'function' that you can use to evaluate other points. Then you create a grid, interpolate your triangular mesh over the grid and you can use the results for the countour plot.
The inputs to the scatteredInterpolanthave to be linear column vectors, so you will probably need to reshape them using the(:)`notation.
So let's assume you have triangular data like this
X = [1 4; 8 9];
Y = [2 3; 4 5];
Z = [0.3 42; 16 8];
you would work out the upper and lower limits of your range first
xlimits = minmax(X(:));
ylimits = minmax(Y(:));
where the (:) notation serves to line up all the elements of X in a single column.
Then you can create a meshgrid that spans that range. You need to decide how fine that grid should be.
spacing = 1;
xqlinear = xlimits(1):spacing:xlimits(2);
yqlinear = ylimits(1):spacing:ylimits(2);
where linspace makes a vector of values starting at the first one (xlimits(1)) and ending at the third one (xlimits(2)) and separated by spacing. Experiment with this and look at the results, you'll see how it works.
These two vectors specify the grid positions in each dimension. To make an actual meshgrid-style grid you then call meshgrid on them
[XQ, YQ] = meshgrid(xqlinear, yqlinear);
this will produce two matrices of points. XQ holds the x-coordinates of every points in the grid, arranged in the same grid. YQ holds the y-coordinates. The two need to go together. Again experiment with this and look at the results, you'll see how it works.
Then you can put them all together into the interpolation:
F = scatteredInterpolant(X(:), Y(:), Z(:));
ZQ = F(XQ, YQ);
to get the interpolated values ZQ at each of your grid points. You can then send those data to contourf
contourf(XQ, YQ, ZQ);
If the contour is too blocky you will probably need to make the spacing value smaller, which will create more points in your interpolant. If you have lots of data this might cause memory issues, so be aware of that.
If your goal is just to view the triangular mesh then you might find trimesh does what you want or, depending on how your data is already represented, scatter. These will both produce 3D plots with wireframes or point clouds though so if you need contours the interpolation is the way to go.

Matlab -plot a vector field

I have written a function in Matlab that gives me a vector at a position (x,y,z).
Now I am looking for the easiest way to make a colored map of this field on a grid and the color should be related to the norm of the vector.
What is the easiest way to define such a grid for $x \in [x_0,x_1],y \in [y_0,y_1], z \in [z_0,z_1]$? Probably linspace for each component would be possible, but maybe there is already a command that gives me the grid.
Now I need to evaluate my function. The problem is, that it actually gives me two vectors, but I am only interested in the first one. So when I first tried to do this I thought that $[A(i,j,k),~]=function(x(i),y(j),z(k))$ could work, but it did not(My goal was: Choose the first vector(A) and mark him with the reference(i,j,k), so that you later on know to which coordinates this vector belongs to).
So I am highly interested in any kind of ideas.
The function meshgrid might be what you are looking for to generate the x, y and z coordinates.
Instead of
[A(i,j,k),~]=function(x(i),y(j),z(k));
try
[A(i,j,k,:),~]=function(x(i),y(j),z(k));
so that you can fit the entire size of the 3-coordinate vector. Also, if you want to preallocate space use
A = zeros(Nx,Ny,Nz,3);
where Nx,... are the dims of your coordinate space. Then like #Moly explains, use meshgrid to generate a 3D grid,
[X Y Z] = meshgrid(x,y,z);
and loop or vectorize to resolve values of your function at points X(i,j,k),Y(i,j,k),Z(i,j,k), compute the norm and store it in 3D array C.
Edit
Representing a cube with mesh(X,Y,Z,C) is not possible but individual slices of the 3D cube can be visualized with mesh, setting the height Z equal to the result of the function C. Some additional work is then required to get coloring right.
Yet another alternative is to use pcolor or contourf. This is perhaps the easiest way to show the 4D data beyond creating a 3D isosurface.
code:
figure
colormap(jet)
for ii=1:9
subplot(3,3,ii)
pcolor(X(:,:,ii),Y(:,:,ii),F(:,:,ii))
axis('equal','square'), title(['Z=' num2str(ii)])
caxis([0 1])
end

Find closest point in matlab grid

G'day
I'm trying to program a smart way to find the closest grid points to the points along a contour.
The grid is a 2-dimensional grid, stored in x and y (which contain the x and y kilometre positions of the grid cells).
The contour is a line, made up of x and y locations, not necessarily regularly spaced.
This is shown below - the red dots are the grid, and the blue dots are the points on the contour. How do I find the indices of the red dot closest to each blue dot?
Edit - I should mention that the grid is a latitude/longitude grid, of an area fairly close to the south pole. So, the points (the red dots) are the position in metres from the south pole (using a polar stereographic representation). Since the grid is a geographic grid there is unequal grid spacing - with slightly different shaped cells (where the red dots define the vertices of the cells) due to the distortion at high latitudes.
The result is that I can't just find which row/column of the x and y matrix corresponds closest to the input point coordinates - unlike a regular grid from meshgrid, the values in the rows and columns vary...
Cheers
Dave
The usual method is to go:
for every blue point {
for every red point {
is this the closest so far
}
}
But a better way is to put the red data into a kd tree. This is a tree that splits the data along its mean, then splits the two data sets along their means etc until you have them separated into a tree structure.
This will change your searching effeciancy from O(n*m) to O(log(n)*m)
Here is a library:
http://www.mathworks.com.au/matlabcentral/fileexchange/4586-k-d-tree
This library will provide you the means to easily make a kd tree out of the data and to search for the closest point in it.
Alternatively you can use a quadtree, not as simple but the same idea. (you may have to write your own library for that)
Make sure the largest data set (in this case your red points) go into the tree as this will provide the greatest time reduction.
I think I've found a way to do it using the nearest flag of griddata.
I make a matrix that is the same size as the grid x and y matrices, but is filled with the linear indices of the corresponding matrix element. This is formed by reshaping a vector (which is 1:size(x,1)*size(x,2)) to the same dimensions as x.
I then use griddata and the nearest flag to find the linear index of the point closest to each point on my contour (blue dots). Then, simply converting back to subscript notation with ind2sub leaves me with a 2 row vectors describing the matrix subscripts for the points closest to each point on the blue-dotted contour.
This plot below shows the contour (blue dots), the grid (red dots) and the closest grid points (green dots).
This is the code snippet I used:
index_matrix1 = 1:size(x,1)*size(x,2);
index_matrix1 = reshape(index_matrix1,size(x));
lin_ind = griddata(x,y,index_matrix1,CX,CY,'nearest'); % where CX and CY are the coords of the contour
[sub_ind(1,:),sub_ind(2,:)] = ind2sub(size(x),lin_ind);
I suppose that in the stereographic representation, your points form a neat grid in r-theta coordinates. (I'm not too familiar with this, so correct me if I'm wrong. My suggestion may still apply).
For plotting you convert from the stereographic to latitude-longitude, which distorts the grid. However, for finding the nearest point, consider converting the latitude-longitude of the blue contour points into stereographic coordinates, where it is easy to determine the cell for each point using its r and theta values.
If you can index the cell in the stereographic representation, the index will be the same when you transform to another representation.
The main requirement is that under some transformation, the grid points are defined by two vectors, X and Y, so that for any x in X and y in Y, (x, y) is a grid point. Next transform both the grid and the contour points by that transformation. Then given an arbitrary point (x1, y1), we can find the appropriate grid cell by finding the closest x to x1 and the closest y to y1. Transform back to get the points in the desired coordinate system.
dsearchn: N-D nearest point search.
[k, d] = dsearchn(A,B) : returns the distances, d, to the closest points. d is a column vector of length p.
http://au.mathworks.com/help/matlab/ref/dsearchn.html?s_tid=gn_loc_drop