Sign in to follow this  

Distance from point to cone

This topic is 3673 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

I'm having a bit of trouble finding the shortest distance from a 3D point to the surface of an infinite cone defined by an apex, interior semi-angle, and opening axis. I have what I believe to be the solution for a double cone (one opening from either side of the apex), but can't quite wrap my head around how to restrict it to a single cone. Here's pseudocode for what I have thus far:
double Angle;  // radians
double Apex[3];
double Axis[3];
double Point[3];

//	send to origin
Point[0] -= Apex[0];
Point[1] -= Apex[1];
Point[2] -= Apex[2];
Apex[0] = 0.0;
Apex[1] = 0.0;
Apex[2] = 0.0;

//	get another point on the axis of the cone
double Point2[3] = { Apex[0] + Axis[0], Apex[1] + Axis[1], Apex[2] + Axis[2] };

//	get the vector from the second point to the given point
double V[3] = { Point[0] - Point2[0], Point[1] - Point2[1], Point[2] - Point2[2] };
	
//	find the distance from the cone's axis to the point
double Crossed[3] = CrossProduct(Axis, V);
double CrossedMagnitude = Magnitude(Crossed);
double AxisMagnitude = Magnitude(Axis);
double d = CrossedMagnitude / AxisMagnitude;

//	find orthogonal distance of point down axis via pythagoras
double V2[3] = { Apex[0] - Point[0], Apex[1] - Point[1], Apex[2] - Point[2] };
double p = sqrt((V2[0] * V2[0] + V2[1] * V2[1] + V2[2] * V2[2]) - (d * d));

//	we've reduced the problem to 2D trig
Distance = d * cos(Angle) - p * sin(Angle);
I feel confident that it works, because when I test it with a point cloud generated from a cone model, every point returns 0 +- 0.001. When I test with a point one unit above and below the apex, though, it gives me the same result, when one unit above the apex should give 1. This last fact led me to the conclusion that it's only working for double cones. What am I missing? -jouley

Share this post


Link to post
Share on other sites
I didn't check your existing code for correctness (since you stated it seems to be working ok), but as for the double-cone problem, if the point lies behind the plane formed by the apex and the cone axis, then the closest point is the apex.

Does that help at all?

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
I didn't check your existing code for correctness (since you stated it seems to be working ok), but as for the double-cone problem, if the point lies behind the plane formed by the apex and the cone axis, then the closest point is the apex.

Does that help at all?

I thought about this, but couldn't convince myself that it was true. For very very short and fat cone, a point out towards the base of the cone but still above the plane formed by the apex/axis would have a closest point somewhere on the cone closer to the edge, wouldn't it? I'll see if I can whip up some mspaint to illustrate...

Share this post


Link to post
Share on other sites
Quote:
Original post by jouley
Quote:
Original post by jyk
I didn't check your existing code for correctness (since you stated it seems to be working ok), but as for the double-cone problem, if the point lies behind the plane formed by the apex and the cone axis, then the closest point is the apex.

Does that help at all?

I thought about this, but couldn't convince myself that it was true. For very very short and fat cone, a point out towards the base of the cone but still above the plane formed by the apex/axis would have a closest point somewhere on the cone closer to the edge, wouldn't it? I'll see if I can whip up some mspaint to illustrate...
Yeah, you're right - I wasn't thinking clearly :)

Share this post


Link to post
Share on other sites
Quote:
Original post by ckin2001
This paper shows how to discount the fact that the point is part of the double cone -

http://www.geometrictools.com/Documentation/IntersectionLineCone.pdf

Hmm... It does deal with the double cone, but it also makes the assumption that the angle of the cone is acute. It then rids itself of the second cone with a simple dot product to check for being on the same side of the plane defined by the apex and the axis, as jyk mentioned above. This works for acute angles, but, unless I've missed something (if I have, please explain!), it's the obtuse ones I'm worried about.

Share this post


Link to post
Share on other sites
The closest distance can be found by doing:
c = (bSingleCone) ? acos(((Point-Apex).Axis)\(|Point-Apex|*|Axis|)) : acos(abs(((Point-Apex).Axis))\(|Point-Apex|*|Axis|)); // from dot product definition
if(abs(c - a) >= Pi/2)
return |Point-Apex|;
else
return |Point-Apex| * sin(abs(c - a));
Now some explanation. The angle 'c' is the angle between the Axis vector and the (Point-Apex) vector. But what's really important here whether or not the angle between 'c' and 'a' is obtuse, not just 'c' or 'a'. In the single-cone case, if this angle is obtuse, then the Apex is the closest point. Otherwise, the closest point is somewhere on the cone and we use some simple trigonometry. Note that abs(c - a) handles the case where the point is inside the cone. In the double-cone case, obtuse angles aren't an issue since you're always going to form an acute angle with either +Axis or -Axis. This is where the absolute value inside the acos() comes from, it reflects the symmetry of the problem and the fact that you always have an acute angle.

Share this post


Link to post
Share on other sites
Well, that certainly is a whole lot more simple! I see the trick, too, I think, about the important angle being that between the Axis and the Apex-Point. I also understand the abs(c-a) makes the result always positive, so removing the abs( ) will give a negative result for points inside the cone, which is the behavior I'm after.

Works like a charm, thanks!

Share this post


Link to post
Share on other sites

This topic is 3673 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