While searching for point-in-polygon tests I've found the one described by Dean Povey here. I like the approach as it can be easily understood (raycast along the x-axis) but I've come across a small inconsistency with that method. While writing Unit-Tests for my implementation I noticed that when taking a square as a "Test-Polygon" points on the left and bottom edge of the square are recognized as part of the polygon while points on the right and top side of the polygon are recognized as outside the polygon. Here's a small drawing showing what I mean (+ are not recognized as inside, doubled lines and the x are):
+--------+
‖ |
‖ |
x========+
Does anyone know how I can change the algorithm to show consistent behaviour for points on the edge? It doesn't matter if the edges are considered as inside or not, just that the behaviour is consistant.
To test if a point P lies on an edge QR, consider the transformation that maps Q to the origin and R to the point (0, 1).
Using complex numbers, write this transformation as Z = (z - Q) / (R - Q) and transform P with (P - Q) / (R - Q). This number must be pure real and its real part be in [0, 1].
You can use this test to detect points on the outline. It is also possible to allow a tolerance, by allowing the imaginary part to be a small number. In this case, it is advisable to normalize the denominator R - Q, so that the imaginary part becomes the Euclidean distance to the segment.
Related
I'm working on a project where some flying object scans the ground to know where its exact location is. For instance, let the following grid be the ground, the letters are literally placed on the ground. Each triangle in the grid is unique.
A---B---C---D
\ / \ / \ / \
E---A---H---G
/ \ / \ / \ / \
H---F---B---E---A
The flying object has access to a file containing these letters, separated by spaces. A zero denotes an empty node.
A B C D 0
E A H G 0
H F B E A
The flying object takes a picture of the ground, but because it's close to the ground, it only sees a part of the ground.
A---H---G
\ / \ /
B---E
The airplane scans this pattern in using OpenCV, it recognizes the numbers. It can also put a coordinate on each of the scanned numbers. For instance, A is placed on coordinate (100,200) on the taken picture, H on coordinate (301,201), B on coordinate (195,403) and so on.
Given the letters with their (approximate) coordinates (on the picture), and also the coordinates of the center of the picture, how does the airplane find out exactly where it is on the grid. It would be optimal if the following output could be produced:
If the airplane hovers above a triangle, return the 3 letters of that triangle.
If the airplane hovers approximately along the side of a triangle, return the 2 letters of that side.
If the airplane hovers approximately on a node, return the letter of that node.
I'm sorry if this is a very wide problem, I just have no idea how to solve it. I tried representing the problem as the subgraph isomorphism problem but the solution to that problem is NP-complete. The grid can have as much as 200 letters.
I'm currently working in python but any solution to this problem (or an idea) is appreciated.
Edit: A part of the question may have been a bit vague. After finding above which vertex/edge/triangle the airplane is flying, I need to find this vertex/edge/triangle on the given grid-file. That's why I tried the subgraph isomorphism problem. So if the airplane finds out it hovers above:
vertex H which is part of triangle HBE, the algorithm should return [(2,1)]
edge HB which is part of triangle HBE, the algorithm should return [(2,1) , (2,2)]
triangle HBE, the algorithm should return [(2,1) , (2,2) , (3,2)]
Thanks a lot!
One issue is that you are over-complicating it. Sub-graph isomorphism is much, much harder than what you are trying to do.
Assuming that you are able to analyze the imagine and determine the approximate coordinates (on the image) for each of the letters. You should be able to take the point set of the letters, with each point uniquely mapped to a letter, and do a linear search to find the three points nearest to to the center of the image.
The next step is the triangle lookup. First, is it important to know that since each triangle in the grid is unique, you can simply loop through all the triangles in the grid, standardize (via a canonization) them, then add them to dictionary to provide a fast lookups. Thus the code for building the look-up dictionary looks something like this:
def canonize_triangle_letters(letter_triple):
# Used in larger algorithm below
return tuple(sorted(list(letter_triple)))
def triangle_lookup_from_grid(triangle_grid)
# This is a preprocessing step
# Only needs to be done once if the grid doesn't change.
# If grid does change, a more complex approach will be needed.
triangle_lookup = {} # Used in larger algorithm below
for points_triple in get_points_triples(triangle_grid):
letter_to_point = dict((point_to_letter[p],p) for p in points_triple)
triangle = canonize_triangle_letters(letter_to_point.keys())
triangle_lookup[triangle] = letter_to_point
return triangle_lookup
The next step is to determine if the return a vertex, edge or triangle. A simple, but rather subjective method, rather useful for example if you want to bias the algorithm towards returning an edge rather than a vertex or triangle.
If the center is significantly closer to one point, return the letter of that point.
If the center is close to two points, return the letters of those two points.
Otherwise, return all three points.
A more balanced, precise way requires some extra math. The below image shows roughly how to go about it. To avoid confusion between areas where a vertex is returned (A), an edge is returned (AB) or a triangle is returned (ABC) as well as the math. The vertex A is labeled as 5, the vertex B is labeled as 6 and the vertex C is labeled as 7. Note that L/3 is showing the radius there, where L is the length of a side. The image assumes that closest point to the center is A followed by B then C. Thus a point would never be on the right side side of the line from vertices 5 and 8, as it breaks the assumption of the point being closer to A and B than C.
The way it is evaluated is as followed:
If the closest point (A) is within L/3 of the center. Then return A.
Create a point, p1 (vertex 8 in the diagram), that is way along the angle halfway between the angle from A to B and A to C. You then place a second point, p2 (vertex 9 in the diagram), at the same angle as A to B and at a distance of L. From there you can use the crossproduct to determine which side of the line the center is on.
If cross(p1,screen_center,p2) less than 0, then return AB, else return ABC.
The code then looks something like below. There are a few magic math functions in the code, but the algorithms for them shouldn't be difficult to look-up online.
def find_nearest_triangle(points, screen_center):
# Returns the nearest triangle, sorted by distance to center
dist_to_center = lambda p: distance(p, screen_center)
# Use the first three points in the list to create the inital triangle
nearest_triangle = set(points[:3])
farthest_point = max(nearest_triangle, key=dist_to_center)
farthest_dist = dist_to_center(farthest_point)
for point in points[3:]:
dist = dist_to_center(point)
if dist < farthest_dist: # Check for a closer point
farthest_dist = dist
nearest_triangle.remove(farthest_point)
nearest_triangle.add(point)
# Find the new farthest point
farthest_point = max(nearest_triangle, key=dist_to_center)
return sorted(list(nearest_triangle), key=dist_to_center)
def get_location(nearest_triangle, screen_center):
# nearest_triangle should be the same as returned by find_nearest_triangle.
# This algorithm only returns the 1-3 points that make up the triangle.
A, B = nearest_triangle[:2]
side_length = distance(A, B)
vertex_radius = side_length / 3.0
if distance(A, screen_center) < vertex_radius:
return [A], nearest_triangle
def cross(o, a, b): # Cross product
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
angle_AB = angle(A, B)
angle_AC = angle(A, C)
middle_angle = ((angle_AB + angle_AC) % 360) / 2.0 # For angle in degrees
p1 = offset_point_by_angle_dist(A, middle_angle, distance)
p2 = offset_point_by_angle_dist(p1, angle_AB, side_length)
if cross(p1,screen_center,p2) < 0:
return [A,B]
return [A,B,C]
def lookup_location(triangle_lookup, image_point_to_letter, points, screen_center):
nearest_triangle = find_nearest_triangle(points, screen_center)
triangle = canonize_triangle_letters([image_point_to_letter[p] for p in nearest_triangle])
letter_to_position = triangle_lookup[triangle]
location = get_location(nearest_triangle, screen_center)
letters = [image_point_to_letter[p] for p in location]
return [letter_to_position[L] for L in letters]
Note the above algorithm has a runtime of O(N), where N is the number of points in the point set. However, it must be ran for each image. Thus if a lot of images need to be checked, it is best to try to limit the number of letters. Although, it's likely that extracting the letters from the image will be more time intensive. Although, since the algorithm only needs the closest three letters, it should be best
So, I'm working on a 2D physics engine, and I have an issue. I'm having a hard time conceptualizing how you would calculate this:
Take two squares:They move, collide, and at some vector based off of the velocity of the two + the shape of them.
I have two vector lists(2D double lists) that represent these two shapes, how does one get the normal vector?
The hit vector is just (s1 is the first shape, s2 the second) s2 - s1 in terms of the position of the center of mass.
Now, I know a normal vector is one perpendicular to an edge, and I know that you can get the perpendicular vector of a line by 90 degrees, but what edge?
I read in several places, it is the edge a corner collided on. How do you determine this?
It just makes no sense to me, how you would mathematically or programmatically determine what edge.
Can anyone point out what I'm doing wrong in my understanding? Sorry for providing no code to explain this, as I'm having an issue writing the code for it in the first place.
Figure1: In 2D the normal vector is perpendicular to the tangent line:
Figure2: In 3D the normal vector is perpindicular to the tangent plane
Figure3: For a square the normal vector is easy if you are not at a corner; It is just perpendicular to the side of the square (in the image above, n = 1 i + 0 j, for any point along the right side of the square).
However, at a corner it becomes a little more difficult because the tangent is not well-defined (in terms of derivatives, the tangent is discontinuous at the corner, so perpendicular is ambiguous).
Even though the normal vector is not defined at a corner, it is defined directly to the left and right of it. Therefore, you can use the average of those two normals (n1 and n2) as the normal at a corner.
To be less technical, the normal vector will be in the direction from the center of the square to the corner of the collision.
EDIT: To answer the OP's further questions in the chat below: "How do you calculate the normal vector for a generic collision between two polygons s1 and s2 by only knowing the intersecting vertices."
In general, you can calculate the norm like this (N is total verts, m is verts inside collision):
vcenter = (∑N vi) / N
vcollision = (∑m vi) / m
n = vcollision - vcenter
Fig. 1 - vcollision is only a single vertex.
Fig. 2 - vcollision is avg of two verts.
Fig. 3 - vcollision for generic polygon intersection.
ADDED INFO:
I'm using the inside of a square as an arena. On start up, the square spawns in a random position, and rotation, and I can't access any of the squares attributes.
I then have a moving object inside the square, that I'm building AI for, and I want the object to 'learn' where the arena walls are. Every time the object bumps into a wall, I get a touch return, so I know if its hit or not. I'm using this to map the global position of where the object hit the wall and save it ... After 3 hits on the same wall, I want to mathematically 'draw a straight line' down those dots which will represent the arena walls - with this, I can tell my object not to go near these coordinates.
The reason for 3 dots? Well, if the object hit one side of a wall, then was to hit another side of a wall, I will have a line drawn from one side to another, giving false data about where the wall is.
If Java sees three (or more) dots inline, it knows that the object has hit the same wall (either being further up or so).
CONTINUED:
I'm trying to map out lines with given coordinate data. Basically I have an array that holds X and Y coordinates, and I want to be able to mathematically detect if it's they make up a straight line (give or take a few pixels). (The coordinate are a boarder of a square)
For example, the array might be like this:
[x0][y0] - 1,1
[x1][y1] - 2,2
[x2][y2] - 5,5
Which will present a diagonal line of on side of the square, like so:
But sometimes I might get one coordinate of one side of the square, and then another side, all mixed up (and not necessarily on a 90 degree angle either!). So I want to be able to run through the array, and detect what coordinates make a line (or the boarder side of the square), like so:
So right now, I have a 2D array:
private double wallLocations[][] = new double[10][10];
and a while loop that doesn't do the job. I don't really know where to even start with this one:
for(int r = 0; r < wallIndex; r++){
for(int c = 0; c < wallIndex; c++){
int index = 0;
if(wallLocations[r][index] == wallLocations[r][c] && wallLocations[r][index + 1] == wallLocations[r][c] &&
wallLocations[r][index + 2] == wallLocations[r][c]){
System.out.println("***** Wall Here! *****");
index++;
}
}
}
---- UPDATE ----
Heres a better example in what I'm looking for. The red dots represent the coordinates coming in, a line is detected when 3 or more dots line up (if it was 2 dots, then it would detect any and ever dot) ... You notice that this is starting to look like the boarder of a square?
This seems to essentially be a clustering problem, and those can be generally pretty hard. Part of a reason clustering is hard is that there may be more than one applicable mapping.
For instance (please forgive my bad ascii art):
X X X
X X X
X X X X
could be mapped
X---X---X X X X
\ / \ / \
X---X---X or X X X
/ \ / \ \
X---X---X---X X X X X
I've seen uses of the Expectation Maximization algorithm using mixed Gaussian models used for this kind of thing (when there were a lot of points but only a few expected lines) but you generally do have to give that algorithm a definite number of clusters, and while its results are good, it's a pretty slow algorithm requiring possibly many iterations. I'm kinda thinking I've seen something generally faster that's some sort of image processing algorithm but I'd have to do some research.
I'm kinda wondering about something where you find y=mx+b for every pair of points and them sort them over m and b. It might be advantageous to find the angle θ in [0,pi) for each pair instead and sort over the angles instead of m, or maybe beter cluster by cos(2θ)-- the point of that being that the group of lines {y= -0.0001x + 1, y =1, and y=0.0001x + 1} are very similar, the group of lines {y= -10000x + 10, x = 0, and y=10000x - 10} are also very similar, but cos(2θ) should put them as far apart as possible, as any two pairs between each group should be nearly perpendicular.
Also note, in my example, b doesn't matter much for the lines nearly perpendicular to the x axis, so "b" might not be so useful for direct clustering.
I guess, perhaps, there may be some utilizable measure of "distance" between two lines, I'm just not sure what it would be. Two lines that are nearly parallel that converge "on screen" (where the points generally are) might ought to be considered "closer" than if they converge a trillion units a way from the screen--or should they? Purely speaking, three lines can never pairwise be considered closer to one another if none of them are parallel (If they're on a plane, they'll all meet somewhere), but intuitively, if we have two lines that are generally one inch apart in the area we're concerned with, we'd pick that pair as closer over two identically pointed lines that are a mile apart in the area of concern. That makes me think maybe the area between the lines,as bound by our area* ought to be used as a metric.
Sorry, I'm not sure how useful all that brainstorming might be, but it might put a different light on things.
Edit: You know what, a better answer might possibly be found by researching this:
http://en.wikipedia.org/wiki/Hough_transform
Edit II & III:
Ok,... the situation you've just described is a lot simpler and less generic (although, to be honest, I think I misread your initial query to be more generic than it really was).
You've got 4 candidate walls. Let your AI bounce around until it finds three co-linear points. That should be a simple test of combinations. Assign those three points a wall. Depending upon what other points you have, you actually might be able to determine or at least estimate the other three walls (assuming it is a square). If you have 5 points with 3 on separate walls, you should be able to calculate the distance between walls, and therefore the likely position of the 4th wall. To test if the other two points are on separate walls, make sure they're pair-wise not co-linear with a line perpendicular or parallel to the line defined by your wall, or if they are on a line parallel, test to see if the distance between them is less than the distance between the wall and them (if that's the case, they're on the wall opposite of the first candidate wall). Given that they are on separate walls, either one is facing the first found wall, or they're on walls perpendicular to that wall. Either way you can find the lines defining the walls with a little tricky geometry.
(and actually, to determine the dimensions, I don't think you need to even test to see that you have 3 co-linear points... I think you just need to test to see that you've made two turns... which takes 4 points minimum but likely more if you're unlucky. two of the points would have to be determinable to be on a different wall from the other two, which means really big bounces!)
There's a bit of math involved, and I'm a bit too tired to explain further tonight, and I don't know how much of the geometry of points around a square you want to take advantage of, because you wouldn't be able to use those properties in a more general case, so I'll leave it at that, and maybe also remove some of my other previous brainstorm cruft later.
If you have two points you can calculate the slope of the connecting line with Math.atan2.
I need to minimize a complex linear multivariable function under some constraints.
Let x be an array of complex numbers of length L.
a[0], a[1], ..., a[L-1] are complex coefficients and
F is the complex function F(x)= x[0]*a[0] + x[1]*a[1] + ... + x[L-1]*a[L-1] that has to be minimized.
b[0], b[1], ..., b[L-1] are complex coefficients and there is a constraint
1 = complexConjuate(x[0])*x[0] + complexConjuate(x[1])*x[1] + ... + complexConjuate(x[L-1])*x[L-1] that has to be fulfilled.
I already had a detailed look at http://math.nist.gov/javanumerics/ and went through many documentations. But I couldn't find a library which does minimization for complex functions.
You want to minimize a differentiable real-valued function f on a smooth hypersurface S. If such a minimum exists - in the situation after the edit it is guaranteed to exist because the hypersurface is compact - it occurs at a critical point of the restriction f|S of f to S.
The critical points of a differentiable function f defined in the ambient space restricted to a manifold M are those points where the gradient of f is orthogonal to the tangent space T(M) to the manifold. For the general case, read up on Lagrange multipliers.
In the case where the manifold is a hypersurface (it has real codimension 1) defined (locally) by an equation g(x) = 0 with a smooth function g, that is particularly easy to detect, the critical points of f|S are the points x on S where grad(f)|x is collinear with grad(g)|x.
Now the problem is actually a real (as in concerns the real numbers) problem and not a complex (as in concerning complex numbers) one.
Stripping off the unnecessary imaginary parts, we have
the hypersurface S, which conveniently is the unit sphere, globally defined by (x|x) = 1 where (a|b) denotes the scalar product a_1*b_1 + ... + a_k*b_k, the gradient of g at x is just 2*x
a real linear function L(x) = (c|x) = c_1*x_1 + ... + c_k*x_k, the gradient of L is c independent of x
So there are two critical points of L on the sphere (unless c = 0 in which case L is constant), the points where the line through the origin and c intersects the sphere, c/|c| and -c/|c|.
Obviously L(c/|c|) = 1/|c|*(c|c) = |c| and L(-c/|c|) = -1/|c|*(c|c) = -|c|, so the minimum occurs at -c/|c| and the value there is -|c|.
Each complex variable x can be considered as two real variables, representing the real and imaginary part, respectively, of x.
My recommendation is that you reformulate your objective function and constraint using the real and imaginary parts of each variable or coefficient as independent components.
According to the comments, you only intend to optimize the real part of the objective function, so you can end up with a single objective function subject to optimization.
The constraint can be split into two, where the "real" constraint should equal 1 and the "imaginary" constraint should equal 0.
After having reformulated the optimization problem this way, you should be able to apply any optimization algorithm that is applicable to the reformulated problem. For example, there is a decent set of optimizers in the Apache Commons Math library, and the SuanShu library also contains some optimization algorithms.
I've written some basic graphing software in Clojure/Java using drawLine() on the graphics context of a modified JPanel. The plotting itself is working nicely, but I've come to an impasse while trying to converting a clicked pixel to the nearest data point.
I have a simple bijection between the list of all pixels that mark end points of my lines and my actual raw data. What I need is a surjection from all the pixels (say, 1200x600 px2) of my graph window to the pixels in my pixel list, giving me a trivial mapping from that to my actual data points.
e.g.
<x,y>(px) ----> <~x,~y>(pixel points) ----> <x,y>(data)
This is the situation as I'm imagining it now:
A pixel is clicked in the main graph window, and the MouseListener catches that event and gives me the <x,y> coordinates of the action.
That information is passed to a function that returns a predicate which determines whether or not a value passed to it is "good enough", and filter though the list with that pred, and take the first value it okays.
Possibly, instead of a predicate, it returns a function which is passed the list of the pixel-points, and returns a list of tuples (x index) which indicate how good the point is with the magnitude of x, and where that point is with index. I'd do this with both the x points and the y points. I then filter though that and find the one with the max x, and take that one to be the point which is most likely to be the one the user meant.
Are these reasonable solutions to this problem? It seems that the solution which involves confidence ratings (distance from pix-pt, perhaps) may be too processor heavy, and a bit memory heavy if I'm holding all the points in memory again. The other solution, using just the predicate, doesn't seem like it'd always be accurate.
This is a solved problem, as other graphing libraries have shown, but it's hard to find information about it other than in the source of some of these programs, and there's got to be a better way then to dig through the thousands of lines of Java to find this out.
I'm looking for better solutions, or just general pointers and advice on the ones I've offered, if possible.
So I'm guessing something like JFreeChart just wasn't cutting it for your app? If you haven't gone down that road yet, I'd suggest checking it out before attempting to roll your own.
Anyway, if you're looking for the nearest point to a mouse event, getting the point with the minimum Euclidean distance (if it's below some threshold) and presenting that will give the most predictable behavior for the user. The downside is that Euclidean distance is relatively slow for large data sets. You can use tricks like ignoring the square root or BSP trees to speed it up a bit. But if those optimizations are even necessary really depends on how many data points you're working with. Profile a somewhat naive solution in a typical case before going into optimization mode.
I think your approach is decent. This basically only requires one iteration through your data array, a little simple maths and no allocations at each step so should be very fast.
It's probably as good as you are going to get unless you start using some form of spatial partitioning scheme like a quadtree, which would only really make sense if your data array is very large.
Some Clojure code which may help:
(defn squared-distance [x y point]
(let [dx (- x (.x point))
dy (- y (.y point))]
(+ (* dx dx) (* dy dy))))
(defn closest
([x y points]
(let [v (first points)]
(closest x y (rest points) (squared-distance x y v) v)))
([x y points bestdist best]
(if (empty? points)
best
(let [v (first points)
dist (squared-distance x y v)]
(if (< dist bestdist)
(recur x y (rest points) dist v)
(recur x y (rest points) bestdist best))))))