Find 2 points in X-Y Plane - c++

I have X-Y plane and points (xi, yi) where x, y and i are integers. Now if I draw infinite lines of slope 1 and -1, I have to find those 2 points which either will lie on the same line or if none of them lie then should output:
Case : If atmost 1 point lies on a line the 2nd point should be the point which has minimum distance from the line. In such cases we can draw the line exactly between those 2 points to minimize the distance.
I am not able to find the solution to this problem. My approach was to look at the points in opposite quadrants but I did not get any solution better than O(n^2).

First, I would transform the points into a different coordinate system that is rotated by 45°:
u = x + y
v = x - y
If the original points lie on a line with slope 1, their v coordinate will be equal. If they lie on a line with slope -1, their u coordinate will be equal.
Now, create two lists of points. One sorted by u, the other sorted by v. Then iterate all the points. To find the point that is closest to the corresponding line, you just have to check the neighbors in the sorted order. If there are neighbors with the same u/v coordinate, you are done. If not, find the neighbor with the smallest u/v difference and remember it. Do this for all the points and report the pair with the smallest distance.

Related

How to calculate coordinate system based on normal vector and center coordinates?

I want to calculate the X direction vector that is determined by the normal vector (Z direction vector) and center coordinates.
For example, given Z direction vector Z(2, 5, 8) , center coordinates point P(5, 10, 14)
Since I have no idea how to do it, any other plain could anybody give me any hint as to what should I do now?
There is infinite number of possible X/Y directions.
If you want to get arbitrary vector perpendicular to given Z, you can apply the next approach:
Compare magnitudes of Z vector components. Exchange the largest and the next components, negate the largest, make the smallest component zero.
For example, if Abs(Z.z)>=Abs(Z.x)>=Abs(Z.y), then vector X = (-Z.z, 0, Z.y) is perpendicular (check that scalar product is zero). For your example:
Z(2, 5, 8)
X(0, -8, 5)
Y = Z x X (vector product)

nanoflann two points equidistance from center

I'm using nanoflann to find the k nearest neighbors (e.g., the k closest points to x). Say, I find k points and define r to be the smallest radius that contains all k points. I then add a new point y such that y lies on the edge of the ball. When I again find the k closest points to x, y is NOT included. It seems that nanoflann's default behavior if two points are equidistant from a point is to return the point that was added first. Is there a way to switch this so it returns the point that was added last?

Distance between two cells in a 2D matrix

I have a 2D matrix represented as a vector of values, an index representing the first cell and a pair of coordinate representing the second cell.
vector<double> matrix;
auto index = 10;
auto x1 = index % width;
auto y1 = index / width;
auto x2 = ...
auto y2 = ...
I need to find the distance between these two cells, where the distance is equals to 1 for the first "ring" of the 8 neighbor cells, 2 for the second ring, and so on.
Is there a way faster than the euclidean distance?
What you need is something like a modified Manhattan Distance. I think there may be a specific name for your use case, but I don't know it. Anyway, this is how I'd do it.
Suppose the two points are x rows away and y columns away. Then x+y is the Manhattan Distance. But in your case, diagonal movements are also allowed. So, if you moved diagonally towards the point initially, you'd cover the smaller of x and y, with some amount remaining in the other. You can then move horizontally/vertically to cover the remaining distance. Hence, the distance by your metric would be max(x,y).
Given points (x1,y1) and (x2,y2), the answer would be max(|x1-x2|,|y1-y2|)

How does the algorithm of merging two convex hulls by using their tangents work in practice?

I'm trying to implement in C++ the divide and conquer algorithm of finding the convex hull from a set of two dimensional points. For simplicity let's assume that all the points are described with integers.
The most important part of the algorithm is merging the two convex hulls that you have computed from previous recursive calls. This part involves finding the lower and upper tangents of the two convex hulls and then proceeding with the merging.
The merging is trivial, if you have found the four points that describe the tangents, then the points that aren't inside the polygon defined by these four points will be part of the new convex hull.
However, I have no idea how to find these four points.
Here is the pseudocode that most sources (this one is from http://www.cs.wustl.edu/~pless/506/l3.html) suggest for finding the lower tangent of convex hull HA and convex hull HB.
Finding the Lower Tangent
LowerTangent(HA ; HB ) :
(1) Let a be the rightmost point of HA .
(2) Let b be the leftmost point of HB .
(3) While ab is not a lower tangent for HA and HB do
(a) While ab is not a lower tangent to HA do a = a - 1 (move a clockwise).
(b) While ab is not a lower tangent to HB do b = b + 1 (move b counterCW).
(4) Return ab.
(1), (2)
The points are initially sorted by their x coordinate, so finding the rightmost point of HA and the leftmost point of HB can be done in O(1).
a = HA[HA.size-1]
b = HB[0]
Now I can't understand the next steps.
Having chosen this ab line segment, how can we check if ab is not a lower tangent so we can either enter the first while loop or not?
And then, how do we move the point a to a-1 by following a clockwise direction? The points are sorted by their x coordinate, and doing just a = a-1 will lead to wrong results.
Thanks!
Your reference only briefly states:
Lower tangency is a condition that can be tested locally by an
orientation test of the two vertices and neighboring vertices on the
hull. (This is a simple exercise.)
and doesn't appear to give any more details. I found this reference which goes into further details of how to find the lower tangency including some example code.
Also note that your should not be sorting the X-coordinates for this purpose. This algorithm relies on the points being in their normal consecutive order that defines the polygon. Sorting by X only helps you in finding the initial points.
Pseudo-code of the lower tangency algorithm from that reference is:
idx1 = (Rightmost point index of Poly1)
idx2 = (Leftmost point index of Poly2)
while (TRUE)
while (isLeft(Poly1[idx2], Poly2[idx1], Poly2[idx1+1]) <= 0)
++idx1;
end while
while (isLeft(Poly2[idx1], Poly1[idx2], Poly1[idx2-1]) >= 0)
--idx2;
done = FALSE;
end while
end while
// idx1/idx2 are now the two indices that form the lower tangent
The isLeft() code from the same reference is:
float isLeft (Point P0, Point P1, Point P2)
{
return (P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y);
}
If the two convex polygons are intersecting then it is incorrect to assume that there are only two tangents that connect the two polygons.
It depends upon how exactly the points are divided. If division ensures that the resultant convex hulls never intersect then it is fine to make such assumption. But if the division of points does not guarantee the convex hulls to be non intersecting then algorithm needs to be modified to find multiple tangents.

how to determine if points is on shape and in shape?

I have two of this:
bool isPointOnShape(int a, int b)
{
}
bool isPointInShape(int a, int b)
{
}
Say I have a square, first point (bottom left corner) is x,y (0,0) second point (top left) is (0,2), third is (2,2) and fourth is (0,2).
The Points on shape would be (0,1) (1,2) (2,1) (1,0) and Points in shape is (1,1)
How do I find out the points on shape / in shape and return a true value so that I can store it somewhere?
For a potentially non-convex shape you may use an algorithm like this:
Find how many shape edges intersect a ray starting at (a,b). You may choose any ray, but it is easier to calculate intersections if the ray is horizontal or vertical.
Point is inside if the number of intersections is odd.
Try going over this tutorial in openCV explaining how to use the point in polygon test. Also a good reference is this wiki page which covers several other methods.
If you don't want to use openCV - in general you can use the Ray casting algorithm:
take a line from the given point (x,y) in any direction you want, let's call it L
for each line in ((0,0),(0,2)), ((0,0),(2,0)), ((2,2),(0,2)), ((2,2),(2,0)) test if that line intersect with with L and count the number of intersections N
if N is odd the point (x,y) is in the polygon