Sign in to follow this  

How to determine closest point on plane vs aabb

This topic is 824 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi there,

how do i determine the closest point from a plane to a axis aligned box in 2D?
The plane does already have the normal which may not be not axis-aligned.

I know how to do the closest point against plane, against box, against circle, against line segment but not this one.
Also i know the concept of using the minkowski sum, but this wont work in this case either sad.png

In my current state i cant find a solution, even though i am sure that its easy.

Does anyone have some tips for me?

Thanks in advance,
Final

Share this post


Link to post
Share on other sites

how do i determine the closest point from a plane to a axis aligned box in 2D?


I was with you until "in 2D". Can you explain what you want, as precisely as possible?


In case the plane are not axis aligned, it seems that the edge which are closest to the plane are the closest one...
 
plane_aabb.png

And when plane are axis aligned:

plane_aabb_2.png Edited by Finalspace

Share this post


Link to post
Share on other sites
If the AABB is always axis aligned (which, by definition, it is), then all you have to do is use your plane's normal to determine which faces/edges/vertices to test.

If the normal has exactly three nonzero components, then test against the two corresponding vertices.
If the normal has exactly two nonzero components, then test against the two parallel edges (using two components of either vertex of that edge).
If the normal has exactly one nonzero component, then test against the two parallel faces (using one component of any vertex of that face).
Else, explode in a massive ball of fire.

If you only want to find faces/edges/vertices with normals pointing towards your plane, then you only have to test one feature instead of two. If you're treating your plane as double-sided, then you test the near and far features (the features on the opposite sides of the box). Edited by Nypyren

Share this post


Link to post
Share on other sites

If the AABB is always axis aligned (which, by definition, it is), then all you have to do is use your plane's normal to determine which faces/edges/vertices to test.

If the normal has exactly three nonzero components, then test against the two corresponding vertices.
If the normal has exactly two nonzero components, then test against the two parallel edges (using two components of either vertex of that edge).
If the normal has exactly one nonzero component, then test against the two parallel faces (using one component of any vertex of that face).
Else, explode in a massive ball of fire.

If you only want to find faces/edges/vertices with normals pointing towards your plane, then you only have to test one feature instead of two. If you're treating your plane as double-sided, then you test the near and far features (the features on the opposite sides of the box).

 

What wait? This seems like SAT... i just need to project all 4 box vertices to the normal and use the vertices which projection are the nearest...

And using this vertex to get the closest point are just like point vs plane... 

 

In the other case i must first check if the plane are axis aligned with the box, then i just can use the box center and its extend... hmm... yeah this may work.

 

Oh wait, there is a easier way - if two vertices have the same projected distance then its axis aligned. So basically all boils down to projection...

 

Thanks!!!

Edited by Finalspace

Share this post


Link to post
Share on other sites

And here my resulting code - Thanks for that hint!

		Vec2f[] vertices = new Vec2f[4];
		vertices[0] = new Vec2f(bodyB.pos.x + box.radius.x, bodyB.pos.y + box.radius.y);
		vertices[1] = new Vec2f(bodyB.pos.x - box.radius.x, bodyB.pos.y + box.radius.y);
		vertices[2] = new Vec2f(bodyB.pos.x - box.radius.x, bodyB.pos.y - box.radius.y);
		vertices[3] = new Vec2f(bodyB.pos.x + box.radius.x, bodyB.pos.y - box.radius.y);
		Vec2f nearestVertexA = vertices[0];
		Vec2f nearestVertexB = null;
		float nearestDistance = nearestVertexA.dot(normal);
		boolean axisAligned = false;
		for (int i = 1; i < vertices.length; i++) {
			Vec2f v = vertices[i];
			float p = v.dot(normal);
			if (p < nearestDistance) {
				nearestDistance = p;
				nearestVertexA = v;
			} else if (p == nearestDistance) {
				nearestVertexB = v;
				axisAligned = true;
			}
		}
		
		Vec2f planePoint = plane.getPoint();
		Vec2f distanceToPlane = new Vec2f(nearestVertexA).sub(planePoint);
		float projDistance = distanceToPlane.dot(normal);
		Vec2f closestPoint = new Vec2f();

		if (axisAligned) {
			float projRadius = Math.abs(box.radius.dot(normal));
			float d = projRadius + projDistance;
			closestPoint.set(bodyB.pos).addMultScalar(normal, -d);
		} else {
			closestPoint.set(nearestVertexA).addMultScalar(normal, -projDistance);
		}

Share this post


Link to post
Share on other sites

Just get the support point on the box in the negative direction of the plane normal. This will give you both the closest point and penetration

 

Using support points seems to be exactly the same as projecting the vertices against the normal, but searching for the greatest distance instead. Plugging in a negative normal into that gives me the exact same result i have right now -> the vertex with the smallest distance...

 

I dont see any difference...

Edited by Finalspace

Share this post


Link to post
Share on other sites

I don't understand why you want to return the projected center in case the plane is axis aligned. The vertices should be equally good. Here is how I would break this up. Maybe it helps.

Vector3 ClosestPointOnPlane( Bounds3 aabb, Plane plane )
{
    Vector3 support = aabb->Support( -plane.m_Normal );
    return plane.Project( support );
}

Vector3 Bounds3::Support( Vector3 v )
{
    Vector support;
    support.x = v.x < 0 ? m_Min.x : m_Max.x;
    support.x = v.y < 0 ? m_Min.y : m_Max.y;
    support.x = v.z < 0 ? m_Min.z : m_Max.z;

    return support;
}

Vector Plane::Project( Vector3 p )
{
    float distance = dot( m_Normal, p ) - m_Offset;
    return p - distance * m_Normal;
}

Edited by Dirk Gregorius

Share this post


Link to post
Share on other sites

This topic is 824 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this