Comments on: GJK – Distance & Closest Points http://www.codezealot.org/archives/153 Development blog and open source repository by William Bittle Fri, 12 Jul 2013 07:28:47 +0000 hourly 1 http://wordpress.org/?v=3.5.2 By: Ernst http://www.codezealot.org/archives/153#comment-28822 Ernst Wed, 11 Apr 2012 12:32:35 +0000 http://www.codezealot.org/?p=153#comment-28822 right…. it looks like this was a drawing error and not an algorithmic one!

I was using the Margin property of an Ellipse to define it’s offset from the borders.

This works as long as positive integral values are provided. Negative, non-integral values for margin values are technically permitted, but should be avoided because they are rounded by the layout rounding behavior.

This perfectly explains the behavior I was seeing where points would ‘lag behind’ a shape.

Again, thanks for you suggestions. It helped me verify the points where chosen correctly but just drawn incorrectly.

On to the EPA article :)

cheers!
Ernst

]]>
By: Ernst http://www.codezealot.org/archives/153#comment-28806 Ernst Wed, 11 Apr 2012 06:30:19 +0000 http://www.codezealot.org/?p=153#comment-28806 Thanks for your reply! By drifting I mean that the points leave the polygon and lag behind if you move the polygon around. It’s perhaps a bit difficult to explain in text but it looks as if the closest points have a smaller radius of action.

That’s a good suggestion and thanks for your offer. I’ll check if the points fall onto the sum shape. Maybe there is an error I can spot.

I’ll let you know!

thanks,
Ernst

]]>
By: William http://www.codezealot.org/archives/153#comment-28758 William Tue, 10 Apr 2012 19:02:56 +0000 http://www.codezealot.org/?p=153#comment-28758 No I haven’t seen that behavior before. What do you mean by drift?

The first thing I would check is if the distance check is working correctly minus the closest points in all quadrants. Then I would make sure that the Minkowski points are correct. The Minkowski points should be the points on the Minkowski sum that form the edge that is closest to the origin (see Figure 6).

If you still can’t find the problem you are welcome to send me the code via or by posting it here.

William

]]>
By: Ernst http://www.codezealot.org/archives/153#comment-28739 Ernst Tue, 10 Apr 2012 14:02:05 +0000 http://www.codezealot.org/?p=153#comment-28739 Hi William,

First of all, thanks for the great articles you’ve put online!

I’ve been playing with an implementation in C#/WPF based on this text and the dyn4j code. Everything looks quite alright but there is an small issue with the closest point that you might be able to give me some hints on.

I have the following (default) quadrant setup;

4 | 1
——–
3 | 2

the origin (0,0) is in the middle of my screen. q1 = x > 0 && y > 0; q2 = x > 0 && y < 0 and so on.

The results look fine whenever I keep both polygons inside the first quadrant. i.e. all the vertices have a positive value. As soon as I move one or more shapes to a different region the closest points start to drift. Is this something you've seen before using this algorithm or am I overlooking a minus sign somewhere and just need to look harder?

Thanks!
Ernst

b.t.w. I'm in 2d as you might have guessed.

]]>
By: William http://www.codezealot.org/archives/153#comment-4968 William Tue, 08 Feb 2011 14:25:56 +0000 http://www.codezealot.org/?p=153#comment-4968 Yes, you are correct.

For the 3D case you can build a triangle (after building the line segment) by obtaining a normal of the line segment in the direction of the origin:

d = // choose some direction
// get the first point
Simplex.add(support(A, B, d);
// get the second point
Simplex.add(support(A, B -d);
// now we have a line segment
// perform the triple product to obtain a new search direction
a = Simplex[0];
b = Simplex[1];
ab = b - a;
ao = -a; // same thing as ORIGIN - a
d = tripleProduct(ab, ao, ab); // be careful here because if the origin lies on the line ab then this will yield the zero vector
// now get the last point to make the triangle
Simplex.add(support(A, B, d);
// now you can start the loop

Now that you have a triangle your next search direction would be the surface normal of the triangle in the direction of the origin. Then obtain a support point, then reduce the 4 points to 3.

]]>
By: Ray Zong http://www.codezealot.org/archives/153#comment-4947 Ray Zong Mon, 07 Feb 2011 14:56:24 +0000 http://www.codezealot.org/?p=153#comment-4947 So right now my understanding is:
If we have two objects in interaction, then we’ll always be able to locate at least one point giving a positive dot product in the direction we’re searching for. And for each point added in, we can generate a simplex to determine if it contains the origin. And eventually we’ll find such origin.
If the two objects are not in contact, we’ll soon jump out of the loop when we can not find any points giving positive “dot product”.
Is it correct?

One more question, I’m trying to do a 3D case. So I need to build a triangle first then add a point in the search direction to get a tetrahedron. How to get the first triangle? With the same method in 2D, I can easily find a line segment, then doing a triple cross product will give a third point and thus generating a triangle. Do you think this can be the triangle to start with? thanks.

]]>
By: William http://www.codezealot.org/archives/153#comment-4944 William Mon, 07 Feb 2011 13:50:47 +0000 http://www.codezealot.org/?p=153#comment-4944 No problem, these questions will help everyone who reads them.

As for question 1: You do not have to check if the simplex contains the origin. The simplex in the distance check is a line segment anyway and can only “contain” the origin if the origin lies on the line segment, in which case you must determine if this is considered a collision or not. You may have noticed that in my code I do check if the origin lies within the triangle (before throwing away one of the points). I do this because my distance method can be called by anyone, and they may not know that the distance method assumes that the shapes are separated. Otherwise I would remove that check.

As for question 2: Right, the termination case is a bit tricky. You know to terminate the loop when the new point you found via the support function is projected onto the search direction and that projection is not greater than zero.

So in iteration 1, you find c, the new point, to be (-11, -1). If we project this onto the search direction:

d.dot(-11, -1) = -0.32 * -11 + -0.95 * -1 = 4.47

It’s greater than zero so that means that we were able to move the simplex in the given direction.

So in iteration 2, you find c to be (-4, -1). If we project this onto the search direction:

d.dot(-4, -1) = 0.32 * -4 + -0.95 * -1 = 0.15

It’s greater than zero so that means that we were able to move the simplex in the given direction.

Now in iteration 3, you find c to be (1, 3) or (-4, -1). If we project this onto the search direction:

d.dot(1, 3) = 0.62 * 1 + -0.78 * 3 = -1.72 or
d.dot(-4, -1) = 0.62 * -4 + -0.78 * -1 = -1.7

Here we see that the projection of the point(s) is less than zero, this means that we cannot get any closer to the origin.

]]>
By: William http://www.codezealot.org/archives/153#comment-4942 William Mon, 07 Feb 2011 13:32:32 +0000 http://www.codezealot.org/?p=153#comment-4942 That’s a good observation. The reason they are done differently is because of the assumptions. In the first post we are making the assumption that the origin lies within the Minkowski sum, terminating when we verify this (or cannot verify). Because we need to know where the origin lies (by voronoi regions) and find a new search direction, we just put the two together.

Finding the distance is similar but slightly different. No longer are we checking if the simplex contains the origin since the assumption is that the Minkowski sum does not contain the origin. In addition, the simplex is a line segment, instead of a triangle, and therefore cannot contain the origin (if we ignore cases where the origin is on the line segment). Because of this we don’t need to worry about voronoi regions or where the origin lies. The search direction is always the normal of the line segment in the direction of the origin.

Given that, I chose to use P = AB.mult(t).add(A) which obtains the point on the line segment that is closest to the origin so that when the loop terminates I’ll be able to get the separation distance by simply getting the magnitude of P.

]]>
By: Ray Zong http://www.codezealot.org/archives/153#comment-4933 Ray Zong Mon, 07 Feb 2011 02:10:11 +0000 http://www.codezealot.org/?p=153#comment-4933 I’m trying to use this case to see how to jump out of the loop. Starting with A(1,3) and B(-9,10), then doing triple cross product ABxAOxAB give the direction (-0.573,-0.819). Then I use all the vertices on the edge to dot product with the direction vector. For 3 vertices give positive values and vertex (-11,-1) gives the largest one (Question 1: Here, should I check if the simplex contains the origin?).

So (-11,-1) is added on as the new point A, same as in your post. Then I do the triple cross product to find the direction (0.316, -0.949) to search. doing dot product of all vertices with the new searching direction gives all negative values. So, question 2, does it mean the loop should be terminated here? or should I keep on searching in another direction until it leads back to the vertex that has already been checked before? Cuz when I keep on doing triple cross product to find the new point, it leads me to (-4,-1), and then back to (1,3) where I started.

Thanks a lot for answering all my questions.

]]>
By: Ray Zong http://www.codezealot.org/archives/153#comment-4932 Ray Zong Mon, 07 Feb 2011 01:13:33 +0000 http://www.codezealot.org/?p=153#comment-4932 I notice that in this post, you first find the new point P = AB.mult(t).add(A), then the search in the direction of -P. While in the previous post, the direction is found by doing the triple cross product. What’s the reason for this? Thanks.

]]>