3D-plot values at specific coords - matlab

I have a 6000*3 matrix Points of 6000 (x,y,z) points representing a surface in space.
I also have a 6000*3 matrix fieldValues such that each row in Points is the location of the field value in the same row in fieldValues:
Points(1,:) = -0.0198 -0.0889 -0.0561
fieldValues(1,:) = 0.7184 -0.1626 -0.0184
so in (-0.0198 -0.0889 -0.0561) which is a point in space, I have a field which its x part is 0.7184, y part is -0.1626 and z part is -0.0184.
How can I plot fieldValues as a function of Points so I can observe how the field acts according to where it is.
Thanks

Related

Finding points in array that is in the specified rectangle( matlab)

I have a matrix that is consists of some points of image.look at below
Cout=
[215,59;165,126;215,72;236,65;258,60;296,71;296,84;246,77;240,120;228,120;225,74;176,58;178,72];
Now I want to find points in rectangle below [x,y,width,height]
rec=[105,210,31,31]
How should I code it in Matlab?
Thanks.
Use inpolygon.[https://www.mathworks.com/help/matlab/ref/inpolygon.html]
HOW IT WORKS:
in = inpolygon(xq,yq,xv,yv) returns in indicating if the query points specified by xq and yq are inside or on the edge of the polygon area defined by xv and yv.
xq: x-coordinates of query points, specified as a scalar, vector, matrix, or multidimensional array(The size of xq must match the size of yq).
yq: y-coordinates of query points, specified as a scalar, vector, matrix, or multidimensional array.
xv: x-coordinates of polygon vertices, specified as a vector(The size of xv must match the size of yv).
yv: y-coordinates of polygon vertices, specified as a vector.
in: Indicator for the points inside or on the edge of the polygon area, returned as a logical array. in is the same size as xq and yq.
% points of image you're searching
% (x,y) are not the coordinates of matrices in MATLAB! And images are
% matrices. The coordinates of matrices are (row, column) which is NOT (x,y) - it's (y,x).
yq=Cout(:,1)
xq=Cout(:,2)
xv=[rec(1);rec(1);rec(1)+rec(3);rec(1)+rec(3);rec(1)];
yv=[rec(2);rec(2)+rec(4);rec(2)+rec(4);rec(2);rec(2)];
in = inpolygon(xq,yq,xv,yv)
I find 2 points by this way.
here is what you need (I think):
Cout= [235,65;296,71;296,84;240,120;229,119;224,74;165,126];
Rec=[105,210,31,31];
% set the range of the rectangle in x and y
xr=[Rec(2) (Rec(2)+Rec(4))];
yr=[Rec(1) (Rec(1)+Rec(3))];
% draw the rectangle for ref
rectangle('Position',Rec); hold on
% the next line is what you asked for, checking if points fall in the
% rectangle I chose here limits with < and >, but you may want <= and >= ...
id = Cout(:,1)<xr(end) & Cout(:,1)>xr(1) & Cout(:,2)<yr(end) & Cout(:,2)>yr(1);
% let's check:
plot(Cout(:,2),Cout(:,1),'x',Cout(id,2),Cout(id,1),'ro')

Mapping a column related by unique values to all values in another matrix

I have a matrix of drill hole positions ([X Y]). I have extracted the unique positions ([Xuq Yuq]) and then interpolated an elevation (Z) for each using griddata. Now I want to create a column in the original matrix with the relevant Z assigned back to every X & Y position. Is this possible without for loops?
If you created your unique positions and the elevation by doing something like:
XY = unique(data(:,[1 2]),'rows');
Z = f(XY); % some function of XY(:,1) and XY(:,2)
Then all you need to do is keep the third output value from unique and use that to map Z back in appropriately:
[XY,~,ic] = unique(data(:,[1 2]),'rows');
Z = f(XY);
data = [data Z(ic)]; % append the mapped column

Centroid calculation for a connected component in 3D volume using Matlab

I am trying to implement brain tumor segmentation on 3D brain MRI(.mha data type).
After preliminary segmentation, I am applying 26-neighbor connected component algorithm(using bwconncomp) to obtain the largest connected component by obtaining the component with the largest volume, following which I need to calculate the centroid of the resultant component.
I am not sure if my method of calculating the largest connected component and the centroid is correct, because the centroid obtained and its nearby voxels all have value 0.
Also I am having confusion with the representation of 3D voxel coordinates. For eg. if centroid=(x,y,z), does it correspond to x=row,y=column and z=2D slice?
Any help would be appreciated. Below is my code with the relevant part.
CC=bwconncomp(Ibin,26); %Input Black & White 3D data of size 240x240x155
Pixelid=regionprops(CC,'PixelIdxList');
[prow pcol]=size(Pixelid);
maxval=numel(Pixelid(1).PixelIdxList);
index=1;
for i=1:prow
number=numel([Pixelid(i).PixelIdxList]);
if (number>maxval) %calculating the component with max number of voxels
maxval=number;
index=i;
end
end
for i=1:prow
if i~=index
Ibin(Pixelid(i).PixelIdxList)=0;
end
end
CC1=bwconncomp(Ibin,26);
Cent=regionprops(CC1,'Centroid');
I changed your code to the following:
CC=bwconncomp(Ibin,26);
PixelIdxList = CC.PixelIdxList;
maxval = numel(PixelIdxList{1});
index = 1;
for ii = 1:length(PixelIdxList)
number = numel(PixelIdxList{ii});
if number > maxval
maxval = number;
index = ii;
end
end
[y,x,z] = ind2sub(size(Ibin),PixelIdxList{index})
centroid = [mean(x), mean(y), mean(z)];
bwconncomp already gives you a PixelIdxList so you don't have to use regionprops. The PixelIdxList lists pixels by their linear indices, so you have to convert them into subscripts to get x, y, and z coordinates. The first dimension in MATLAB matrix represents y coordinates, and second dimension represents x, while the third dimension represents z. Centroid is calculated by taking the mean x, y, and z coordinates of all the pixels contained in the object.

Plot points at a specific height from an existing 3D plot/data set

I have a robot leg (3 joints) and I've plotted the maximum range of the end of the leg in a 3D plot using convhull. Now, I want to be able to specify a particular height within that entire workspace and create a 2D plot with X and Y coordinates of all the possible points within the workspace at that height (3D plot works just as well but might be more difficult).
EDIT: Forgot to mention that the data is stored in a 3 by 1088 matrix with coordinates for each row. Also, since the Z coordinate might not match exactly the value I'm looking for, the next closest point works just as well.
Thank you.
If I am interpreting your question correctly, you wish to isolate out points in your matrix that match a particular z coordinate. Failing an exact match, you wish to find the closest z coordinate to your desired query. Also, since your data is stored in a 3 x 1088 matrix, you probably meant to say that each column is a coordinate, not each row.
I'm going to assume that the first, second and third rows denote the x, y and z coordinates of the movement of your robot. The first step would simply be to find the minimum distance between your desired z coordinate with all of those found in the matrix. Once you find that matching coordinate, we simply need to find those z coordinates in your matrix that match, isolate those out and plot only the x and y coordinates. Therefore, assuming your matrix of points is stored in data, and your query z coordinate is stored in queryZ, do something like this:
queryZ = 2.0; %// 1
zPoints = data(3,:); %// 2
[~,loc] = min(abs(queryZ - zPoints)); %// 3
minZ = zPoints(loc); %// 4
ind = data(3,:) == minZ; %// 5
xPoints = data(1,ind); %// 6
yPoints = data(2,ind); %// 7
plot(xPoints, yPoints, 'b.'); %// 8
title(['Points found for ' num2str(minZ)]); %// 9
The first line of code declares a desired z coordinate for you to search for. The next two lines extract out the z coordinates for your data, and then uses min and searches through the z coordinates and finds the location that is closest to your desired z coordinate. We use this location to extract out what the closest z coordinate is (line 4), then find those locations in your data matrix that share this same z coordinate (line 5).
Lastly, these locations are used to filter out the x and y coordinates of your data matrix (lines 6 and 7) and we then plot these points in blue and with dot markers (line 8). As a bonus, we place a title on the plot that shows you what the actual z coordinate was that matched to your query (line 9).
Edit
Given your inquiry in your comments, you would like to find multiple values of z within a particular tolerance for each value. The easiest way would be to do this in a for loop. There are certainly other ways to do this vectorized, but I won't invest the time into doing so. As such, you would have to slightly modify the above formulation and perform the following steps:
For each query point queryZ:
Find the closest point in your data
Search for all z points within a tolerance tol of this point
Add these points to a list
Repeat Step #1 for all query points desired
Plot all of these points for display
As such, the code would look something like this:
%// Step #1
queryZ = [2.0 1.0 -1.0 -2.0]; %// Define desired z points
tol = 0.001; %// Define tolerance here
zPoints = data(3,:); %// Extract out z points
%// Step #2
loc = false(numel(zPoints));
for idx = 1 : numel(queryZ)
z = queryZ(idx); %// Get query point
[~,minInd] = min(abs(z - zPoints)); %// Find closest point to query
minZ = zPoints(minInd);
loc(abs(minZ - zPoints) < tol) = true; %// Find indices within tolerance wrt closest point
%// Set to true
end
%// Step #3
xPoints = data(1,ind); %// 6
yPoints = data(2,ind); %// 7
plot(xPoints, yPoints, 'b.'); %// 8
The first step is self-explanatory. We first define a bunch of z coordinates that you are seeking, define a tolerance for similarity and extract out the z coordinates of your data. Next, for each point in our query set, we find the closest z coordinate to your data, and then with respect to this closest coordinate, we search for points that are within a specified tolerance of this matched point. We use these locations (not the coordinates) to mark into a logical array where true means that this point has met the criteria of being matched and false otherwise. In the end, any locations in the logical array that are set to true means that the corresponding point located at this index has met the criteria to be matched for at least one of the points in your query.
Finally, we use this logical array to index into our data, grab all of the valid points and plot them.
Hope this helps!

Finding the belonging value of given point on a grid of 3D histogram?

I use 2D dataset like below,
37.0235000000000 18.4548000000000
28.4454000000000 15.7814000000000
34.6958000000000 20.9239000000000
26.0374000000000 17.1070000000000
27.1619000000000 17.6757000000000
28.4101000000000 15.9183000000000
33.7340000000000 17.1615000000000
34.7948000000000 18.2695000000000
34.5622000000000 19.3793000000000
36.2884000000000 18.4551000000000
26.1695000000000 16.8195000000000
26.2090000000000 14.2081000000000
26.0264000000000 21.8923000000000
35.8194000000000 18.4811000000000
to create a 3D histogram.
How can I find the histogram value of a point on a grid? For example, if [34.7948000000000 18.2695000000000] point is given, I would like to find the corresponding value of a histogram for a given point on the grid.
I used this code
point = feat_vec(i,:); // take the point given by the data set
X = centers{1}(1,:); // take center of the bins at one dimension
Y = centers{2}(1,:); // take center of the bins at other dim.
distanceX = abs(X-point(1)); // find distance to all bin centers at one dimension
distanceY = abs(Y-point(2)); // find distance to center points of other dimension
[~,indexX] = min(distanceX); // find the index of minimum distant center point
[~,indexY] = min(distanceY); // find the index of minimum distant center point for other dimension
You could use interp2 to accomplish that!
If X (1-D Vector, length N) and Y (1-D vector, length M) determine discrete coordinate on the axes where your histogram has defined values Z (matrix, size M x N). Getting value for one particular point with coordinates (XI, YI) could be done with:
% generate grid
[XM, YM] = meshgrid(X, Y);
% interpolate desired value
ZI = interp2(XM, YM, Z, XI, YI, 'spline')
In general, this kind of problem is interpolation problem. If you would want to get values for multiple points, you would have to generate grid for them in similar fashion done in code above. You could also use another interpolating method, for example linear (refer to linked documentation!)
I think you mean this:
[N,C] = hist3(X,...) returns the positions of the bin centers in a
1-by-2 cell array of numeric vectors, and does not plot the histogram.
That being said, if you have a 2D point x=[x1, x2], you are only to look up the closest points in C, and take the corresponding value in N.
In Matlab code:
[N, C] = hist3(data); % with your data format...
[~,indX] = min(abs(C{1}-x(1)));
[~,indY] = min(abs(C{2}-x(2)));
result = N(indX,indY);
done. (You can make it into your own function say result = hist_val(data, x).)
EDIT:
I just saw, that my answer in essence is just a more detailed version of #Erogol's answer.