I have a list of points in cartesian plane, and a test point. I want to find list indices of three points nearest to test point. What's the better way to find these indices? Thanks in advance for tour replies.
=== EDIT ===
I've found a solution in C++. At first I create a vector:
typedef struct
{
int iIndex;
double dSqrDistance;
} IndexedDistance;
std::vector<IndexedDistance> xDistanceVector;
and then a function to sort its elements
bool compareIndexedDistance(IndexedDistance xD1, IndexedDistance xD2)
{
return (xD1.dSqrDistance < xD2.dSqrDistance);
}
Then in a loop I calculate all distances, then I sort them and at the end I take first three elements:
IndexedDistance xDistanceElement;
for (int i = 0; i < xPointList.size(); i++)
{
dSqrDistance = xPointList.at(i).sqrDistance(xTestPoint);
xDistanceElement.iIndex = i;
xDistanceElement.dSqrDistance = dSqrDistance;
xDistanceVector.push_back(xDistanceElement);
}
std::sort(xDistanceVector.begin(), xDistanceVector.end(), compareIndexedDistance);
xDistanceVector.resize(3);
In this way, I found what I need. I don't know if it's the best way, but it seems to work.
Binary space partitioning may provide algorithms complexity of O(log n * log n).
Determine bounds of your point set. Infinum and supremum points will give you an axis-aligned square containing all the points in set.
Split the bounding square in two by any of axis. Make a separate list of contained points for each square. Link each of bounding squares to the parent square.
Repeat splitting bounding squares (step 2) until corresponding lists of containing points will be reasonably small to utilize exhaustive search.
Now you will be able to use tree search to localize space around your point of interest and therefore greatly reduce number of distance tests.
The tricky part is that you must scan all the neighbour bounding squares around the point of interest because the closest point may lie in any of them.
Related
Given some points in plane (upto 500 points), no 3 collinear. We have to determine the number of triangles whose vertices are from the given points and that contain exactly N points inside them. How to efficiently solve this problem? The naive O(n^4) algorithm is too slow. Any better approach?
You could try thinking of the triangle as the intersection of three half-spaces. To find the number of points inside a triangle A, B, C first consider the set of points on one side of the infinite line in direction AB. Let these sets L(AB) and R(AB) for points of the left and right. Similarly you the same with other two edges and build sets L(AC) and R(AC) and sets L(BC) and R(BC).
So the number of points in ABC will be the number of points in the intersection of L(AB), L(AC) and L(BC). (You might want to consider R(AB) instead depending on the orientation of the triangle).
Now if we want to consider the full set of 500 points. First take all pairs of points AB and construct the sets L(AB) and R(AB). This will take O(n^3) operations.
Next we test all triangles and find the intersections of the three sets. If we use some hash table structure for the sets then to find the intersection points is like a hashtable lookups. If L(AB) has l elements, L(AC) has m elements and L(BC) n elements. Say l > m > n. For each point in L(BC) we need to do a lookup in L(AC) and L(BC) so thats a maximum of 2n hashtable lookups.
It might be faster to consider a geometric lookup table.
Divide your whole domain into a coarse grid say a 10 by 10 grid. We can then put each point into a set G(i,j). We can then split the sets L(AB) into each grid cell. Say call these sets L(AB,i,j) and R(AB,i,j). In testing for intersections first workout which grid cells lie in the intersection. This dramatically reduces the search space and as each set L(AB,i,j) contain fewer members there will be fewer hashtable lookups.
Actually I happened to encounter similar problem recently but the only difference was that there were around 300 pts and I solved it using bitset (C++ STL). For every pair of points, say (x[i],y[i]) and (x[j],y[j]), I formed a bitset<302>B[i][j] and B[i][j][k] stores 1 if k-th point is above line segment from point i to point j else I would store 0.
Now in a brute force manner I get three points so as to form a triangle, lets say (x[i],y[i]), (x[j],y[j]) and (x[k],y[k]), then a point,say z-th point ,would be inside triangle if B[i][j][z]==B[i][j][k] && B[j][k][z]==B[j][k][i] && B[k][i][z]==B[k][i][j] because a point inside triangle would show similar sign w.r.t. a side of triangle as the third point of triangle(one which is not on this side).
So i get three bitset variables P=B[i][j], Q=B[j][k] and R=B[k][i] and there taking there bitwise AND then applying count() function to give me the active number of bits and hence the number of points within the triangle. But make sure you change variable P such that it gives B[i][j][k]=1 if not then take bitwise not (~) of this variable.
Though the above solution is problem specific, i hope it helps. This is the problem link: http://usaco.org/current/index.php?page=viewproblem&cpid=660
Given a collection of points, I'd like to find the center of a bounding box (fixed-length and width) that maximizes the number of points within said box. I'm at a loss for an efficient way to do this.
Algorithm with complexity O(N^2*logN) (I hope that better one exists):
Edit: article exploiting interval trees claims O(NlogN) complexity
Sort data array A by X coordinate.
Scan A with sweep line left to right.
For every point in A get LeftX = A[k].X - left coordinate of vertical band, find the rightmost coordinate of vertical band RightX = LeftX + Width.
Copy points inside the band to another array B.
Sort B by Y-coordinate.
Scan B width sweep line top to down.
For every point B[i] get TopY = B[i].Y - top coordinate of rectangle, calculate BottomY = TopY + Height.
Use binary search in B:
B[j] is the last bottom point in B with B[j].Y <= BottomY.
Find number of points in the current rectangle:
Number of points is N(k, i) = j - i + 1
Check whether N(k, i) is maximum among others
This seems like a difficult problem, here is my idea:
Hold a graph, each node holds a rectangle and a subset of points. the rectangle defines the area where placing the bounding box in would overlap all the points in the subset.
To build the graph:
Start with a root node holding the empty set and the rect [top:-inf, bottom:inf, left:-inf, right:inf]
For each point in the tree call this recursive function with the root node (pseudo code):
function addPoint(node, point)
// check that you didn't already try to add this point to this node
// node.tested can be a hash set
if(node.tested contains point)
return
node.tested.add(point)
newRect = node.rect.intersectWith(boundingBoxAround(point))
// if the bounding box around the point does not intersect the rectangle, return
if(newRect is invalid) // rect is invalid if right<left or bottom<top
return
node.addChild(new node(newRect, node.pointSet U {point})
for each child of node
addPoint(child, point)
Now you just pick the node with the largest subset, you can keep track of that when building the graph so you don't need to run through the graph again.
I hope my idea is clear, let me know if I can explain it better.
Given the coordinates of a polygon,
I found many algorithms to detect if a point is in a polygon - for example: [1] and [2]. But none of these algorithms are able to detect if the point lies on the vertices of this polygon. For example I have a polygon:
|---------------------|
| |
| |
|---------------------|
My point is in the right upper corner. I want an algorithm that tells me whether the point is inside the polygon. How can I do this?
Except for problem of dealing with issues related to floating point not exact match but close enough, the same algorithm should work for both.
Just pick a point inside the polygon, create the test line segment from the test point to the inside point, and then, for each segment in the polygon, determine if a test line segment intersects that polygon segment, To count as intersect, count intersects open on one end of polygon segment, and closed on the other end, i.e., if the intersection is exactly the same as the start of the polygon, count it, but if it's exactly the same as the end point, do Not count it. You need to do this so that when the test segment intersects with a polygon vertex, you must only count it as intersecting one of the two segments on either side of the vertex.
Then If test point is inside polygon, the number of intersections will be an even number, if it is outside, it will be an odd number.
Just found a solution right here. It is very easy and the code from [1] has a and b already implemented. Additional information to the source code can be found here.
const float EPSILON = 0.001f;
bool IsPointOnLine(Point linePointA, Point linePointB, Point point)
{
float a = (linePointB.y - linePointA.y) / (linePointB.x - linePointB.x);
float b = linePointA.y - a * linePointA.x;
if ( fabs(point.y - (a*point.x+b)) < EPSILON)
{
return true;
}
return false;
}
I was wondering if the following algorithm to check if a point is inside a rectangle is valid.
I've developed it using my own intuition (no strong trig/math basis to support it), so I'd love to hear from someone with more experience in the matter.
Context:
The rectangle is defined with 4 points. It could be rotated.
Coordinates are always positive.
By definition, the point is considered inside the rectangle if intersects it.
Hypothesis:
Use the distance between the point and the rectangle vertices (first diagram below).
The maximum possible total distance is when the point is in one vertex (second diagram).
If the point is just outside the rectangle, the distance will be greater (third diagram).
Diagram link: http://i45.tinypic.com/id6o35.png
Algorithm (Java):
static boolean pointInsideRectangle(Point[] rect, Point point) {
double maxDistance = distance(rect[0], rect[1]);
maxDistance += distance(rect[0], rect[2]);
maxDistance += distance(rect[0], rect[3]);
double distance = 0;
for (Point rectPoint : rect) {
distance += distance(rectPoint, point);
if (distance > maxDistance) return false;
}
return true;
}
Questions: is this correct?
Short answer: NO :P (don´t fell bad about it)
Long Answer: Intersecction the areas from the four circles that you mention (max distance between opposite vertex) does not produce a rectangle.
Since I´m a bit rusty in geometry I can´t give full mathematical explanation (time constrain for my part), but give you some pseudocode of the procedure with the constrains that you ask (no fancy formulae), valid for any rectangle the wikipeida or a geometry book can fill the gaps.
Find the N,E,S,W vertex (the uppermost, rightmost, lowest and leftmost vertex) this is trivially easy for any rectangle but the axis aligned who can produce oddly assignation of the vertex (see images with examples)
Find the NE, SE, SW and NW border, this is the line equation in wikipedia or another link, again should be easy, but the axis aligned border should be analized carefully because those generate another type of ecuation/restriction.
Check if your point is on the "right side" of the border see inequality as mathematical term, only a point inside your rectangle satisfy the four restrictions as you can see in the image attached.
my apologies if I have overlook some command of java.geom that can accomplish this task
I hope this help with your endevour
You can try this.Lets name the point we have as A.Draw a line between A and every point of the rectangle.After that you get 4 different triangles.Calculate the area the triangles are taking(using Heron's formula) and compare it to the area of the rectangle.If the areas are the same then your point is inside the rectangle.
Cheers
I'm looking for a very simple algorithm for computing the polygon intersection/clipping.
That is, given polygons P, Q, I wish to find polygon T which is contained in P and in Q, and I wish T to be maximal among all possible polygons.
I don't mind the run time (I have a few very small polygons), I can also afford getting an approximation of the polygons' intersection (that is, a polygon with less points, but which is still contained in the polygons' intersection).
But it is really important for me that the algorithm will be simple (cheaper testing) and preferably short (less code).
edit: please note, I wish to obtain a polygon which represent the intersection. I don't need only a boolean answer to the question of whether the two polygons intersect.
I understand the original poster was looking for a simple solution, but unfortunately there really is no simple solution.
Nevertheless, I've recently created an open-source freeware clipping library (written in Delphi, C++ and C#) which clips all kinds of polygons (including self-intersecting ones). This library is pretty simple to use: https://github.com/AngusJohnson/Clipper2
You could use a Polygon Clipping algorithm to find the intersection between two polygons. However these tend to be complicated algorithms when all of the edge cases are taken into account.
One implementation of polygon clipping that you can use your favorite search engine to look for is Weiler-Atherton. wikipedia article on Weiler-Atherton
Alan Murta has a complete implementation of a polygon clipper GPC.
Edit:
Another approach is to first divide each polygon into a set of triangles, which are easier to deal with. The Two-Ears Theorem by Gary H. Meisters does the trick. This page at McGill does a good job of explaining triangle subdivision.
If you use C++, and don't want to create the algorithm yourself, you can use Boost.Geometry. It uses an adapted version of the Weiler-Atherton algorithm mentioned above.
You have not given us your representation of a polygon. So I am choosing (more like suggesting) one for you :)
Represent each polygon as one big convex polygon, and a list of smaller convex polygons which need to be 'subtracted' from that big convex polygon.
Now given two polygons in that representation, you can compute the intersection as:
Compute intersection of the big convex polygons to form the big polygon of the intersection. Then 'subtract' the intersections of all the smaller ones of both to get a list of subracted polygons.
You get a new polygon following the same representation.
Since convex polygon intersection is easy, this intersection finding should be easy too.
This seems like it should work, but I haven't given it more deeper thought as regards to correctness/time/space complexity.
Here's a simple-and-stupid approach: on input, discretize your polygons into a bitmap. To intersect, AND the bitmaps together. To produce output polygons, trace out the jaggy borders of the bitmap and smooth the jaggies using a polygon-approximation algorithm. (I don't remember if that link gives the most suitable algorithms, it's just the first Google hit. You might check out one of the tools out there to convert bitmap images to vector representations. Maybe you could call on them without reimplementing the algorithm?)
The most complex part would be tracing out the borders, I think.
Back in the early 90s I faced something like this problem at work, by the way. I muffed it: I came up with a (completely different) algorithm that would work on real-number coordinates, but seemed to run into a completely unfixable plethora of degenerate cases in the face of the realities of floating-point (and noisy input). Perhaps with the help of the internet I'd have done better!
I have no very simple solution, but here are the main steps for the real algorithm:
Do a custom double linked list for the polygon vertices and
edges. Using std::list won't do because you must swap next and
previous pointers/offsets yourself for a special operation on the
nodes. This is the only way to have simple code, and this will give
good performance.
Find the intersection points by comparing each pair of edges. Note
that comparing each pair of edge will give O(N²) time, but improving
the algorithm to O(N·logN) will be easy afterwards. For some pair of
edges (say a→b and c→d), the intersection point is found by using
the parameter (from 0 to 1) on edge a→b, which is given by
tₐ=d₀/(d₀-d₁), where d₀ is (c-a)×(b-a) and d₁ is (d-a)×(b-a). × is
the 2D cross product such as p×q=pₓ·qᵧ-pᵧ·qₓ. After having found tₐ,
finding the intersection point is using it as a linear interpolation
parameter on segment a→b: P=a+tₐ(b-a)
Split each edge adding vertices (and nodes in your linked list)
where the segments intersect.
Then you must cross the nodes at the intersection points. This is
the operation for which you needed to do a custom double linked
list. You must swap some pair of next pointers (and update the
previous pointers accordingly).
Then you have the raw result of the polygon intersection resolving algorithm. Normally, you will want to select some region according to the winding number of each region. Search for polygon winding number for an explanation on this.
If you want to make a O(N·logN) algorithm out of this O(N²) one, you must do exactly the same thing except that you do it inside of a line sweep algorithm. Look for Bentley Ottman algorithm. The inner algorithm will be the same, with the only difference that you will have a reduced number of edges to compare, inside of the loop.
The way I worked about the same problem
breaking the polygon into line segments
find intersecting line using IntervalTrees or LineSweepAlgo
finding a closed path using GrahamScanAlgo to find a closed path with adjacent vertices
Cross Reference 3. with DinicAlgo to Dissolve them
note: my scenario was different given the polygons had a common vertice. But Hope this can help
If you do not care about predictable run time you could try by first splitting your polygons into unions of convex polygons and then pairwise computing the intersection between the sub-polygons.
This would give you a collection of convex polygons such that their union is exactly the intersection of your starting polygons.
If the polygons are not aligned then they have to be aligned. I would do this by finding the centre of the polygon (average in X, average in Y) then incrementally rotating the polygon by matrix transformation, project the points to one of the axes and use the angle of minimum stdev to align the shapes (you could also use principal components). For finding the intersection, a simple algorithm would be define a grid of points. For each point maintain a count of points inside one polygon, or the other polygon or both (union) (there are simple & fast algorithms for this eg. http://wiki.unity3d.com/index.php?title=PolyContainsPoint). Count the points polygon1 & polygon2, divide by the amount of points in polygon1 or Polygon2 and you have a rough (depending on the grid sampling) estimate of proportion of polygons overlap. The intersection area would be given by the points corresponding to an AND operation.
eg.
function get_polygon_intersection($arr, $user_array)
{
$maxx = -999; // choose sensible limits for your application
$maxy = -999;
$minx = 999;
$miny = 999;
$intersection_count = 0;
$not_intersected = 0;
$sampling = 20;
// find min, max values of polygon (min/max variables passed as reference)
get_array_extent($arr, $maxx, $maxy, $minx, $miny);
get_array_extent($user_array, $maxx, $maxy, $minx, $miny);
$inc_x = $maxx-$minx/$sampling;
$inc_y = $maxy-$miny/$sampling;
// see if x,y is within poly1 and poly2 and count
for($i=$minx; $i<=$maxx; $i+= $inc_x)
{
for($j=$miny; $j<=$maxy; $j+= $inc_y)
{
$in_arr = pt_in_poly_array($arr, $i, $j);
$in_user_arr = pt_in_poly_array($user_array, $i, $j);
if($in_arr && $in_user_arr)
{
$intersection_count++;
}
else
{
$not_intersected++;
}
}
}
// return score as percentage intersection
return 100.0 * $intersection_count/($not_intersected+$intersection_count);
}
This can be a huge approximation depending on your polygons, but here's one :
Compute the center of mass for each
polygon.
Compute the min or max or average
distance from each point of the
polygon to the center of mass.
If C1C2 (where C1/2 is the center of the first/second polygon) >= D1 + D2 (where D1/2 is the distance you computed for first/second polygon) then the two polygons "intersect".
Though, this should be very efficient as any transformation to the polygon applies in the very same way to the center of mass and the center-node distances can be computed only once.