Mmm, so hDistance is the magnitude of my (lookat - eyevector) and pDistance is the magnitude of the test vector(px, py pz).
What is Distance?
Thanks
Main Topics
Browse All TopicsI want to be able to determine whether a point is inside a cone.
I have three vectors (eyePosition), (eyeDirection) and (Test Point) which are all relative to the origin.
I want a cone of length l and the angle between the diagonal sides to be alpha (both of which can be modified). I know you can use the dot product to find this answer out but my implementation seems to be giving me quite weird results.
Math Theory
My idea is that two vectors A and B where A is the vector from eyePosition to Test Point and B is the axis of the cone pointing towards eyeDir*l.
That if acos(A.B / |A||B|) < 0.5 * alpha then the point can be in the cone.
And for a stricter definition if the dot product of A.B is <= length of the axis (l) then the point is definitely inside the cone.
Is that correct?
My C Code is as such
int insideLightCone(double x, double y, double z, double px, double py, double pz,
double ang, double height) {
double dotP = dotProduct(x * height, y*height, z*height, px, py, pz);
cDistance = (eyex - px) * (eyex - px) + (eyey - py) * (eyey - py) + (eyez - pz) * (eyez - pz);
double magOfVecs = magnitude(x*height, y*height, z*height) * magnitude(px, py, pz);
double theta = acos(dotP / magOfVecs);
return ((theta <= 0.5 * ang) && (cDistance <= height));
}
I'm not sure any of this code or math is correct so I am asking for help.
Thanks
neutrinohunter
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
I am actually using this for a cone based lighting system and my output comes as such:
http://img265.imageshack.u
The lit vertices correspond to the points that exist within the cone. But not all the vertices are lit within the cone which exists from the viewpoint.
Are you sure my math is correct?
Should all my vectors be normalised? Or none at all if any?
Thanks
jamie
I can't really follow your example code. Here is some code that will hopefully be clear to you.
vec is a structure with .x, .y, and .z members.
apex is the location of the apex of the cone, the pointy bit.
axis is a unit vector (normalized so that magnitude == 1) pointing from the apex to the center of the base disc.
halfcossq is (cos(alpha/2))^2. If you precalculate this then you don't need to do trig for every single point tested.
p is the point we're testing to see if it's inside the cone.
boolean pointInCone(vec apex, vec axis, double height, double halfcossq,
double p) {
vec pdiff = vec(p.x - apex.x, p.y - apex.y, p.z - apex.z);
double d= axis.x * pdiff.x + axis.y *pdiff.y + axis.z * pdiff.z;
if (d < 0 || d > height) return false; // above the apex or below the base
// we want to know if acos(d / magnitude(pdiff)) < alpha/2.
// applying cos reverses the sign of the comparison. No real improvement,
// since it trades a cos for an acos. However, it sets up other tradeoffs.
// d/magnitude(pdiff) > cos(alpha/2)
// this trades a multiply for a divide, a good deal
// d > cos(alpha/2) * magnitude(pdiff)
// this trades a multiply for a sqrt, another good deal
// d^2 > cos(alpha/2)^2 * magnitude(pdiff)^2
return (d*d > halfcossq * (pdiff.x*pdiff.x + pdiff.y*pdiff.y + pdiff.z*pdiff.z));
}
My understanding is that you want to find if "test point" is at a distance not greater then "l" from "eye position" and within an angle of "alpha"/2 from the "eye position"-"eye direction" vector.
Given
e="eye position"
d="eye direction" (not necessarily normalized)
t="test point"
The first test is
(t-e) . (t-e)<=l^2 (note that "." is dot-product)
So your math is correct but your cdistance is, actually, the square of the distance (you might have to compare it with square of "height" - but I'm not sure what "height" is)
The second test is
(t-e) . d >= length(t-e) * cos(alpha/2)
You can divide this last test by length(t-e) and take the acos of both sides to get it in the same form you used (acos(A.B / |A||B|) < 0.5 * alpha ) which is correct. However I'd avoid using acos and prefer my form as, with my form, you can precompute cos (alpha/2) and use it for testing multiple points (with your form, you should computer the acos for each test point).
So your "acos(A.B / |A||B|) < 0.5 * alpha " is correct (just take the ac
Sorry for the long reply, not had access to a computer for a few days
Ozo: The picture was supposed to demonstrate a circular or jagged shaped conical shape on an area of terrain.
If my code was working right, it should check whether points in my view (demonstrated by the blue crosshair) are in distance, then they should be illuminated, so it would look like a dark room and some one turns on a torch.
I was doing this with my code.
if (coneLighting && insideLightCone(vec[0], vec[1], vec[2], p1.x-eyex, p1.y-eyey, p1.z-eyez, ANG, coneLength))
Where vec was a normalised array of floats corresponding to a normalised lookat vector. p1 would be the test point, coneLength (or i described height as well) would be the length of the cone from the apex to the center of the base and ANG would be the angle between the two diagonal sides of a cone.
Somehow I think I incorrectly encoded what you said, i'll try again in a second.
Also I'm searching for a flashlight effect, if a sphere sector could produce a similar effect I would be welcome to listen to it.
NovaDenizen
I tried your method and got a similar effect to Ozo's so am trying to track down errors and see if my code is buggering something up somewhere. But yes, I agree your form although probably harder to see is probably a lot more efficient than calling acos() for 10000 points.
Ibertacco
Yes, I basically just want to have a cone which is my eye position and determine whether a point at a distance d away is inside the cone. Obviously this cone can be translated or rotated about the y and x to show movement as if I look down on the floor or to the skys.
You speak of two tests, does this refer to the similar math I describe?
Thanks for all your input, ill have another look at what I have done and see if its a stupid mistake I've done somewhere.
Neutrinohunter
I mentioned two tests because my understanding was that you wanted to verify if a point is inside an infinite cone of a given angle and within a given distance (which are 2 tests).
Actually I'm not sure why you want to test for the distance if what you are looking for is a "torch"/spotlight effect (maybe the idea is that the torch can't get too far? - in this case the distance check I proposed is more appropriate than the finite cone idea, but doesn't really change much).
Still, in your code, next to last line (the "return" line), you should compare cdistance with square of height as in:
return ((theta <= 0.5 * ang) && (cDistance <= height*height));
Have you tried with the change I suggested? Beside fixing a math error it also seems to match the wrong results you get in the posted images. The posted image shows a "donut" of light around some mountains. The black area inside the donut can indeed be caused by not squaring height when you compare it with cdistance (in fact, as I'vee already pointed out, cdistance is not really the distance, but the square of the distance).
Try with this code (Note that I"m assuming that (x,y,z) is normalized as it seems from your code, correct?):
int insideLightCone(double x, double y, double z, double px, double py, double pz, double ang, double height) {
double hsquared = height*height;
double cosangle = cos(0.5*ang);
cDistance = (eyex - px) * (eyex - px) + (eyey - py) * (eyey - py) + (eyez - pz) * (eyez - pz);
return(cDistance<=hsquared
}
As you can see, hsquared and cosangle don't change unless you change the cone size/angle, so you could avoid computing them for each poiint....
Also in your code, cDistance seems to be a global var? (otherwise it would be better to add a "double" in front of "cDistance ="). If you use cDistance in other parts of your code, be careful that it still is not really the distance but the square of it
Originally cDistance was going to be a method of determining a colour for a vertex based on the intensity of the light eminating from the apex of the cone. At the moment, it isn't being used but it was being used in a manner: glColor3f(1.0 / (1.0 + cDistance)) for the illumination of a vertex inside the cone.
Ozo: Basically I was doing
/* Ncenter# is the normalised look at vector
P1 is the TestPoint
eye# is the position of the observer
*/
if (insideLightCone(ncenterx,
set colour of the test point to white i.e glColor3f(1.0,1.0,1.0);
else
set colour to black i.e glColor3f(0.0,0.0,0.0);
Ibertacco: I just get a black screen. Though I'm wondering why you are doing:
eyex - px since px = testp.x - eyex so basically I am getting back testp.x, if this was supposed to be the parameter x rather than eyex then I get an effect which is better. But the shape is only very small and doesn't change on movement of my lookat vector, which it is programmed to do.
http://img519.imageshack.u
Sorry, I believed px/py/pz was the test point.
So, now, my understanding is that:
x,y,z is the cone axis direction, normalized
px,py,pz is testpoint - eyeposition
ang, is the cone aperture angle
height is the light maximum distance
and the revised code is:
int insideLightCone(double x, double y, double z, double px, double py, double pz, double ang, double height) {
double hsquared = height*height;
double cosangle = cos(0.5*ang);
cDistance = px*px + py*py + pz*pz;
return(cDistance<=hsquared
}
Yes, that is correct, however unfortunately I get no cone shape with that code so I'm not sure whats effecting my results.
I'm not sure how familiar you are with OpenGL, but the idea was to set a colour of a point to fully illuminated if was inside the cone and it seems that no point I have falls within the cone, however that shouldn't be the case. My angle is at around 60 degrees and my coneLength is at around 30 (since my whole scene of size (100, 20,100) in the approriate dimensions.
Business Accounts
Answer for Membership
by: ozoPosted on 2007-07-20 at 08:52:51ID: 19532283
you might want
double dotP = dotProduct(x , y, z, px, py, pz);
double hDistance = magnitude(x, y, z);
double pDistance = magnitude(px, py, pz);
cDistance = dotP / hDistance;
double theta = acos(dotP / (Distance * pDistance));
return ((theta <= 0.5 * ang) && (cDistance <= height)) && cDistance > 0;