How can I find out the index of the points here?
8 views (last 30 days)
Show older comments
Ashfaq Ahmed
on 17 Feb 2023
Commented: Ashfaq Ahmed
on 21 Feb 2023
HI! I have this interesting indexing question.
I have a cloud data set (attached, Cloud.mat). Plotting the X and Y, I get this figure. My question is - I want to find all the indices that falls under these four sections. Can any one please tell me how can I get the indices? Any feedback will be much appreciated.
0 Comments
Accepted Answer
John D'Errico
on 17 Feb 2023
Edited: John D'Errico
on 18 Feb 2023
Pretty easy. (Easier yet, IF the lines were drawn at right angles. If they were, then we could do it in literally one line of code.) But I can see they are NOT exactly perpendicular to each other, so this will take a couple more lines of code, but not many.
Anyway, just create a simple triangulation.
triXY = [-1.5 -1.5;1.5 -1.5;-1.5 2;1.5 2;0 0.25]
triangles = [1 2 5;1 3 5;2 4 5;3 4 5];
T = triangulation(triangles,triXY)
xy = rand(10,2)*3 - 1.5; % some random points.
trimesh(triangles,triXY(:,1),triXY(:,2))
hold on
plot(xy(:,1),xy(:,2),'ro')
axis equal
Next, we consider what tools a triangulation can use.
methods(T)
In there, we see that pointLocation is a method for this class. That may help me.
help pointLocation
pointLocation(T,xy)
The index returned indicates where the corresponding point fell. You can skip the plots, as you wish.
A second solution is also not difficult. This relies on an affine transformation, if the points in the plane. Think of the data as a coordinate system around an origin at the point (0,0.25). Thus, where the lines cross. A problem is, the lines have the wrong slopes, as they are not perpendicular to each other. We can resolve that simply enough, by scaling y by a factor of 3/3.5. And then we can rotate the coordinate system by 45 degrees.
The final transformation, if we have an array xy of size nx2:
ang = -45; %degree rotation, so a clockwise rotation of 45 degrees
T = @(xy) (xy - [0 0.25]).*[1 3/3.5]*[cosd(ang) sind(ang);-sind(ang) cosd(ang)];
THe function handle T uses capabilities introduced in R2016b. Earlier releases would use bsxfun.
If you look at the transformation, first notice I subtract off 0.25 from y only, so x is unchanged. Effecively, now the lines cross at the origin.
Next, I scaled the problem, so multiplying y by a factor of 3/3.5. That effectively corrects the two lines so they are now perpendicular after the rotation. (This was the error @Walter Roberson made in his suggestion.)
Finally, the 2x2 matrix I multiply by there is a rotation matrix. I've used sind and cosd there so it is clear how it was formed. See what the transformation did to the points listed in triXY.
triXY
T(triXY)
The 5th point now lies at the origin. And each of the other points have been properly scaled, and then rotated. Now, how can we use the above transformation? I'll rotate the points in the array xy, into a new array, then plot the transformation.
newxy = T(xy);
figure
plot(xy(:,1),xy(:,2),'o')
hold on
trimesh(triangles,triXY(:,1),triXY(:,2))
plot(newxy(:,1),newxy(:,2),'x')
plot([xy(:,1),newxy(:,1)]',[xy(:,2),newxy(:,2)]','r-')
axis equal
hold off
grid on
As you can see, the entire system of points has been shifted, stretched just a bit, and then rotated.
How can we now use this? If the final location of a point was originally in the top triangle, then it is now in the first quadrant. In that case, both the new x and the new y are positive numbers. So now we can decide which of the original (quasi-)quadrants a point lies in, merely by testing the signs of the points after rotation.
T(xy) >= 0
So if both results are 1 there, then the point lies now in the first quadrant. If both results are zero, then the point lies in the 3rd quadrant. And then you can easily distinguish the other quadrants too. A nice trick is to use a binary to decimal encoding.
(T(xy)>0)*[1;2]
As you can see, that yields an integer, so 0,1,2,3, depending on which of the original regions a point fell in. I'll let you decode which of the regions was which.
2 Comments
More Answers (2)
Torsten
on 17 Feb 2023
Edited: Torsten
on 17 Feb 2023
X = [0,10,0,-10,0,5,0,-5]
Y = [10,0,-10,0,5,0,-5,0]
syms x y
g1 = (y-2)/(x-1.5) == (-1.5-2)/(-1.5-1.5);
g2 = (y-2)/(x-(-1.5)) == (-1.5-2)/(1.5-(-1.5));
g1 = matlabFunction(solve(g1,y))
g2 = matlabFunction(solve(g2,y))
section1 = find(Y >= g1(X) & Y >= g2(X))
section2 = find(Y < g1(X) & Y > g2(X))
section3 = find(Y <= g1(X) & Y <= g2(X))
section4 = find(Y > g1(X) & Y < g2(X))
0 Comments
Walter Roberson
on 17 Feb 2023
Subtract the center of mass. Rotate the result by +45 degrees. Now the combinations of sign() of the transformed x and y coordinates tells you which sector you started from.
1 Comment
John D'Errico
on 18 Feb 2023
Edited: John D'Errico
on 18 Feb 2023
Except that the lines drawn are not perpendicular to each other. It would be nice if they were, but they are not.
Check the slopes of the lines. One of them has a slope of
3.5/3
The other slope is
-3.5/3
If they were perpendicular, the slopes would be the negative reciprocal of each other.
You could still perform an appropriate transformation that would make the idea work. But not just a 45 degree rotation.
See Also
Categories
Find more on Resizing and Reshaping Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!