POV-Ray : Newsgroups : povray.off-topic : Math question (inside box) Server Time
12 Oct 2026 01:41:37 EDT (-0400)
  Math question (inside box) (Message 1 to 19 of 19)  
From: Patrick Elliott
Subject: Math question (inside box)
Date: 4 Aug 2013 17:50:17
Message: <51fecc99$1@news.povray.org>
Hunted around on the net and found something for 2D, but I think I got 
something wrong trying to do the 3D. Actually, I am semi-sure I know 
what I screwed up, but not how to fix it. lol But, I figured I would 
maybe, instead, ask here instead, on the chance there is a better solution.

Basically though, I have an object, its position, and its rotation, and 
I want to create a "test box" in which to work out where someone is, 
but I want it to still work, regardless of whether or not the object is 
say, rotated 35 degrees in all directions, placing my "test box" some 
place other than at nice 90 angles from the normal axis.

Now the method I had tried was:

main(){
integer left = 0;
integer right = 2;
integer length = 5;
integer top = 1.5;
integer bottom = 1.5;

//Assuming that the "front" is in the Y direction.
  integer boxlen = llGetScale().y / 2;
  vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
  vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
  vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
  vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
  if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
    //do other stuff, or, else, the stuff you do if they are "not" in 
the box.
}

integer triangleArea(vector A, vector B, vector C)
{
   //This is where I am screwing up.. I need to test A.z, B.z and C.z,
   //for one of the planes, but I am testing x and y in both cases, which
   //won't work.
   return(C.x*B.y-B.x*C.y)-(C.x*A.y-A.x*C.y)+(B.x*A.y-A.x*B.y);
}

integer isInsideSquare(vector A, vector B, vector C, vector D, vector P)
{
   if(triangleArea(A,B,P)>0 || triangleArea(B,C,P)>0 || 
triangleArea(C,D,P)>0 || triangleArea(D,A,P)>0)
       return FALSE;
     else
       return TRUE;
}

integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector bbox4)
{
   vector P = llDectectedPos(0);
   vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
   vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
   vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
   vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
   vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
   vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
   vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
   vector D2 = <bbox3.x,bbox3.y,bbox3.z>;
   return (isIntegerSquare(A1, B1, C1, D1, P) & isIntegerSquare(A2, B2, 
C2, D2));
}


I am 99% sure that what I failed to think about is that since one of the 
"sides" is vertical, I am testing its x and y in both cases, and thus, 
stupidly, not testing the z. Otherwise, the code works, supposedly, 
because, if your test point isn't "inside the box", one or more of the 
area calculations will end up with a negative sign.

In any case, I need to redo the code, if I want to do this, and simplify 
things a lot at well.

But, what I was wondering is.. is there some other way to do this? Some 
way that takes into account the rotation, and what amounts to a sort of 
"is this inside of the bounding box" calculation, without having to 
rotation/unrotate various things, to get the same result? Because, as 
things stand, either I need to reposition the object I am testing, or I 
need to reposition the corner of my invisible box, which I am testing 
for them to be in. And, while one is less annoying than the other.. they 
are still both annoying. lol


Post a reply to this message

From: Le Forgeron
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 03:52:55
Message: <51ff59d7$1@news.povray.org>
Le 04/08/2013 23:50, Patrick Elliott a écrit :
> Hunted around on the net and found something for 2D, but I think I got
> something wrong trying to do the 3D. Actually, I am semi-sure I know
> what I screwed up, but not how to fix it. lol But, I figured I would
> maybe, instead, ask here instead, on the chance there is a better solution.
> 
> Basically though, I have an object, its position, and its rotation, and
> I want to create a "test box" in which to work out where someone is, but
> I want it to still work, regardless of whether or not the object is say,
> rotated 35 degrees in all directions, placing my "test box" some place
> other than at nice 90 angles from the normal axis.

Why would you want to handle such box, when the interest of such code is
precisely to reduce the workload by looking only at the axes.


> 
> Now the method I had tried was:
> 
> main(){
> integer left = 0;
> integer right = 2;
> integer length = 5;
> integer top = 1.5;
> integer bottom = 1.5;
> 
> //Assuming that the "front" is in the Y direction.
>  integer boxlen = llGetScale().y / 2;
>  vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>  vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>  vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
>  vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
>  if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
>    //do other stuff, or, else, the stuff you do if they are "not" in the
> box.
> }
> 
> integer triangleArea(vector A, vector B, vector C)
> {
>   //This is where I am screwing up.. I need to test A.z, B.z and C.z,
>   //for one of the planes, but I am testing x and y in both cases, which
>   //won't work.
>   return(C.x*B.y-B.x*C.y)-(C.x*A.y-A.x*C.y)+(B.x*A.y-A.x*B.y);
> }
> 
> integer isInsideSquare(vector A, vector B, vector C, vector D, vector P)
> {
>   if(triangleArea(A,B,P)>0 || triangleArea(B,C,P)>0 ||
> triangleArea(C,D,P)>0 || triangleArea(D,A,P)>0)
>       return FALSE;
>     else
>       return TRUE;
> }
> 

Did you understand how it is supposed to work in 2D ? I mean the
previous two functions are using oriented triangles and area computation
(signed result) to know if P is inside ABCD.

When P is inside ABCD, ABP, BCP, CDP, DAP all have the same sign for
their area. As soon as P is outside the square, one area at least has a
negative result.

The nice thing about it is that the four points A,B,C & D only need to
be ordered in the rotating order and can be anywhere in the plane (it
does not have to be an axis-aligned square).

But it only works in 2D.


> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector bbox4)
> {
>   vector P = llDectectedPos(0);
>   vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>   vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>   vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>   vector D1 = <bbox1.x,bbox1.y,bbox1.z>;

>   vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
>   vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
>   vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
>   vector D2 = <bbox3.x,bbox3.y,bbox3.z>;

>   return (isIntegerSquare(A1, B1, C1, D1, P) & isIntegerSquare(A2, B2,
> C2, D2));
> }
> 

I do not understand the expectation here. You seems to transform the box
as two parallel to Z plane squares (axis-aligned), and then check if the
projection of P is inside the projections of both these squares.

There is plenty of situations where it will provide false positives, as
well as false negatives.

> 
> I am 99% sure that what I failed to think about is that since one of the
> "sides" is vertical, I am testing its x and y in both cases, and thus,
> stupidly, not testing the z. Otherwise, the code works, supposedly,
> because, if your test point isn't "inside the box", one or more of the
> area calculations will end up with a negative sign.

signed area calculation is only good for 2D. The extension in 3D would
need to compute the volume of a pyramid (with a triangle base) and the
maths are not to be friendly

> 
> In any case, I need to redo the code, if I want to do this, and simplify
> things a lot at well.
> 
> But, what I was wondering is.. is there some other way to do this? Some
> way that takes into account the rotation, and what amounts to a sort of
> "is this inside of the bounding box" calculation, without having to
> rotation/unrotate various things, to get the same result? Because, as
> things stand, either I need to reposition the object I am testing, or I
> need to reposition the corner of my invisible box, which I am testing
> for them to be in. And, while one is less annoying than the other.. they
> are still both annoying. lol

If you do not intend to limit yourself to a axis-aligned box, why not
instead use a sphere ?

you transform only 1 point (the center)(if you only have rotation and
translation), and then just compute the distance of the center to P (to
compare against the radius). And to avoid slow squared root, compare the
squared distance (euclidian) to the squared radius.

If you have more than rotation & translation (such as scaling and
shearing), you might need to transform the radius too (at which point,
it's better to consider 1 center and the 8 corners of the box, to
finally only kept as radius the distance from the center to the most
faraway corner)
(the box is originally the box that encloses the minimal sphere. at the
end, the radius is the radius of the sphere that encloses the
transformed box. Thus, it is bigger than the strict covering sphere, but
it is safe)

-- 
Just because nobody complains does not mean all parachutes are perfect.


Post a reply to this message

From: scott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 04:44:33
Message: <51ff65f1$1@news.povray.org>
>   vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>   vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>   vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
>   vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;

Do you mean "pos.x + right" in that last line?

> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector bbox4)
> {
>    vector P = llDectectedPos(0);
>    vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>    vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>    vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>    vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
 >    vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
 >    vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
 >    vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
 >    vector D2 = <bbox3.x,bbox3.y,bbox3.z>;

If you substitute in your values for bbox1-4 from above you get the 
following (I left out the pos.x,pos.y,pos.z):

A1 = <-left  , boxlen , -bottom>
B1 = < right , boxlen , -bottom>
C1 = < right , boxlen , -bottom>
D1 = <-left  , boxlen , -bottom>

A2 = <-left  , boxlen+length , -bottom>
B2 = < right , boxlen+length , -bottom>
C2 = < right , boxlen+length , -bottom>
D2 = <-left  , boxlen+length , -bottom>

Is this really what you are expecting?

If you are trying to see if a point is inside a box, then it might be 
simpler to think of the box as being bounded by 6 infinite planes (one 
for each face), then testing which side of each plane the point is on. 
If it's on the "inside" of all 6 planes then it's inside the box.


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 05:15:48
Message: <51ff6d44$1@news.povray.org>
On 8/5/2013 12:52 AM, Le_Forgeron wrote:
> Le 04/08/2013 23:50, Patrick Elliott a écrit :
>> Hunted around on the net and found something for 2D, but I think I got
>> something wrong trying to do the 3D. Actually, I am semi-sure I know
>> what I screwed up, but not how to fix it. lol But, I figured I would
>> maybe, instead, ask here instead, on the chance there is a better solution.
>>
>> Basically though, I have an object, its position, and its rotation, and
>> I want to create a "test box" in which to work out where someone is, but
>> I want it to still work, regardless of whether or not the object is say,
>> rotated 35 degrees in all directions, placing my "test box" some place
>> other than at nice 90 angles from the normal axis.
>
> Why would you want to handle such box, when the interest of such code is
> precisely to reduce the workload by looking only at the axes.
>
>
Yeah, well. I kind of thought maybe there was some way that I just 
wasn't seeing.

>>
>> Now the method I had tried was:
>>
>> main(){
>> integer left = 0;
>> integer right = 2;
>> integer length = 5;
>> integer top = 1.5;
>> integer bottom = 1.5;
>>
>> //Assuming that the "front" is in the Y direction.
>>   integer boxlen = llGetScale().y / 2;
>>   vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>>   vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>>   vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
>>   vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
>>   if (isInsideBox(bbox1, bbox2, bbox3, bbox4))
>>     //do other stuff, or, else, the stuff you do if they are "not" in the
>> box.
>> }
>>
>> integer triangleArea(vector A, vector B, vector C)
>> {
>>    //This is where I am screwing up.. I need to test A.z, B.z and C.z,
>>    //for one of the planes, but I am testing x and y in both cases, which
>>    //won't work.
>>    return(C.x*B.y-B.x*C.y)-(C.x*A.y-A.x*C.y)+(B.x*A.y-A.x*B.y);
>> }
>>
>> integer isInsideSquare(vector A, vector B, vector C, vector D, vector P)
>> {
>>    if(triangleArea(A,B,P)>0 || triangleArea(B,C,P)>0 ||
>> triangleArea(C,D,P)>0 || triangleArea(D,A,P)>0)
>>        return FALSE;
>>      else
>>        return TRUE;
>> }
>>
>
> Did you understand how it is supposed to work in 2D ? I mean the
> previous two functions are using oriented triangles and area computation
> (signed result) to know if P is inside ABCD.
>
> When P is inside ABCD, ABP, BCP, CDP, DAP all have the same sign for
> their area. As soon as P is outside the square, one area at least has a
> negative result.
>
> The nice thing about it is that the four points A,B,C & D only need to
> be ordered in the rotating order and can be anywhere in the plane (it
> does not have to be an axis-aligned square).
>
> But it only works in 2D.
>
Umm. Not sure how to explain this, but, yeah, I did. I just.. screwed up 
on the coordinates. lol Umm. Let me put it this way. You are looking at 
two boxes one is laying flat, along the XY, the other is lying flat on 
the XZ (or the YZ, which I don't think necessarily matters). So.. in one 
case if the location of the thing being tested was <1,2,3>, then P 
"should be" <1,2>, and for the other plane, it should be <1,3>, with the 
corners of the two boxes, on those planes, taken from the XY, or the XZ, 
as needed.

Or, that was what I envisioned in my own head. lol Obviously, I screwed 
up from the very start.

>
>> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector bbox4)
>> {
>>    vector P = llDectectedPos(0);
>>    vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>>    vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>>    vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>>    vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
>
>>    vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
>>    vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
>>    vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
>>    vector D2 = <bbox3.x,bbox3.y,bbox3.z>;
>
>>    return (isIntegerSquare(A1, B1, C1, D1, P) & isIntegerSquare(A2, B2,
>> C2, D2));
>> }
>>
>
> I do not understand the expectation here. You seems to transform the box
> as two parallel to Z plane squares (axis-aligned), and then check if the
> projection of P is inside the projections of both these squares.
>
> There is plenty of situations where it will provide false positives, as
> well as false negatives.
>
Yeah, as I said, I fowled up. In actuality, what happens, due to the 
code being wrong, is that P is *never* inside the box.

>>
>> I am 99% sure that what I failed to think about is that since one of the
>> "sides" is vertical, I am testing its x and y in both cases, and thus,
>> stupidly, not testing the z. Otherwise, the code works, supposedly,
>> because, if your test point isn't "inside the box", one or more of the
>> area calculations will end up with a negative sign.
>
> signed area calculation is only good for 2D. The extension in 3D would
> need to compute the volume of a pyramid (with a triangle base) and the
> maths are not to be friendly
>
No doubt.

>>
>> In any case, I need to redo the code, if I want to do this, and simplify
>> things a lot at well.
>>
>> But, what I was wondering is.. is there some other way to do this? Some
>> way that takes into account the rotation, and what amounts to a sort of
>> "is this inside of the bounding box" calculation, without having to
>> rotation/unrotate various things, to get the same result? Because, as
>> things stand, either I need to reposition the object I am testing, or I
>> need to reposition the corner of my invisible box, which I am testing
>> for them to be in. And, while one is less annoying than the other.. they
>> are still both annoying. lol
>
> If you do not intend to limit yourself to a axis-aligned box, why not
> instead use a sphere ?
>
The reason is that I need the specific shape. Ok, I will attach an 
example. There is a safe, against a wall, and a counter, which is green, 
the transparent box is the "valid" area for someone to be able to access 
the safe, with the guy inside it being "allowed", and the two "red" 
figures not. There is no way to use a sphere, without detecting as 
"valid" people standing in the wrong places. Its the precise reason why 
I didn't just use the simpler method of figuring out, "Is this person 
standing in the +X direction, and within N meters of the object. That 
method would have failed to detect people, in the safe where, instead, a 
garage door, for example, if they stood at the "edge" of the door, since 
they might not be "close enough", without making the detection range 
much larger than I wanted (i.e., a 15 meter door, should detect 5 meters 
"in front of" the door, no matter where on the door, but since is using 
"center of the door", it would fail to detect someone standing against 
it, but 7 meters from the center).

However... I occurs to me that I might be able to use one plane, and a 
distance.. So, as long as the position was rotated, to match a plane 
that is align to XY (or, actually, due to how the world works, XZ), then 
I can test if its in "that" box, and then merely do:

float dist = llVecDist(llGetPos(), P);
if (dist < maxdist & dist > mindist)
{
   //Rest of the code.
}

Thus, only testing "one" box, and only on that single plane.

Then again, I screwed up the last idea so badly... lol


Post a reply to this message


Attachments:
Download 'example.png' (22 KB)

Preview of image 'example.png'
example.png


 

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 05:17:19
Message: <51ff6d9f$1@news.povray.org>
On 8/5/2013 1:44 AM, scott wrote:
>>   vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>>   vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>>   vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z - bottom>;
>>   vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
>
> Do you mean "pos.x + right" in that last line?
>
>> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector
>> bbox4)
>> {
>>    vector P = llDectectedPos(0);
>>    vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>>    vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>>    vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>>    vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
>  >    vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
>  >    vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
>  >    vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
>  >    vector D2 = <bbox3.x,bbox3.y,bbox3.z>;
>
> If you substitute in your values for bbox1-4 from above you get the
> following (I left out the pos.x,pos.y,pos.z):
>
> A1 = <-left  , boxlen , -bottom>
> B1 = < right , boxlen , -bottom>
> C1 = < right , boxlen , -bottom>
> D1 = <-left  , boxlen , -bottom>
>
> A2 = <-left  , boxlen+length , -bottom>
> B2 = < right , boxlen+length , -bottom>
> C2 = < right , boxlen+length , -bottom>
> D2 = <-left  , boxlen+length , -bottom>
>
> Is this really what you are expecting?
>
> If you are trying to see if a point is inside a box, then it might be
> simpler to think of the box as being bounded by 6 infinite planes (one
> for each face), then testing which side of each plane the point is on.
> If it's on the "inside" of all 6 planes then it's inside the box.
>
lol What part of, "I know I screwed up the math.", did people miss. ;)

Seriously though, Le_Fogeron says it wouldn't work anyway... :p


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 05:18:43
Message: <51ff6df3$1@news.povray.org>
On 8/5/2013 2:15 AM, Patrick Elliott wrote:
> However... I occurs to me that I might be able to use one plane, and a
> distance.. So, as long as the position was rotated, to match a plane
> that is align to XY (or, actually, due to how the world works, XZ), then
> I can test if its in "that" box, and then merely do:
>
> float dist = llVecDist(llGetPos(), P);
> if (dist < maxdist & dist > mindist)
> {
>    //Rest of the code.
> }
>
> Thus, only testing "one" box, and only on that single plane.
>
> Then again, I screwed up the last idea so badly... lol

And, speaking of which.. again, I forget that the "distance" won't work 
for objects wider, or taller, than the distance... Sigh...


Post a reply to this message

From: scott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 07:35:43
Message: <51ff8e0f$1@news.povray.org>
>> Thus, only testing "one" box, and only on that single plane.
>>
>> Then again, I screwed up the last idea so badly... lol
>
> And, speaking of which.. again, I forget that the "distance" won't work
> for objects wider, or taller, than the distance... Sigh...

Make your bounding box the value of "distance" bigger than the bounding 
box of the object's geometry. That way you are checking for people 
within "distance" from the *edge* of the object, not from the centre.


Post a reply to this message

From: scott
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 07:38:14
Message: <51ff8ea6$1@news.povray.org>
On 05/08/2013 10:17, Patrick Elliott wrote:
> On 8/5/2013 1:44 AM, scott wrote:
>>>   vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>>>   vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>>>   vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z -
>>> bottom>;
>>>   vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
>>
>> Do you mean "pos.x + right" in that last line?
>>
>>> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector
>>> bbox4)
>>> {
>>>    vector P = llDectectedPos(0);
>>>    vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>>>    vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>>>    vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>>>    vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
>>  >    vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
>>  >    vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
>>  >    vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
>>  >    vector D2 = <bbox3.x,bbox3.y,bbox3.z>;
>>
>> If you substitute in your values for bbox1-4 from above you get the
>> following (I left out the pos.x,pos.y,pos.z):
>>
>> A1 = <-left  , boxlen , -bottom>
>> B1 = < right , boxlen , -bottom>
>> C1 = < right , boxlen , -bottom>
>> D1 = <-left  , boxlen , -bottom>
>>
>> A2 = <-left  , boxlen+length , -bottom>
>> B2 = < right , boxlen+length , -bottom>
>> C2 = < right , boxlen+length , -bottom>
>> D2 = <-left  , boxlen+length , -bottom>
>>
>> Is this really what you are expecting?
>>
>> If you are trying to see if a point is inside a box, then it might be
>> simpler to think of the box as being bounded by 6 infinite planes (one
>> for each face), then testing which side of each plane the point is on.
>> If it's on the "inside" of all 6 planes then it's inside the box.
>>
> lol What part of, "I know I screwed up the math.", did people miss. ;)

I was really having trouble trying to understand what you actually 
wanted to do! I don't know which parts of the above are math screw ups 
or what you actually want to do...

There are much easier, well documented, ways for doing bounding box 
tests, you don't need to go into splitting it up to squares and 
triangles and measuring areas as you seem to have done. If that's what 
you want to do?


Post a reply to this message

From: Le Forgeron
Subject: Re: Math question (inside box)
Date: 5 Aug 2013 07:43:05
Message: <51ff8fc9@news.povray.org>
Le 05/08/2013 11:17, Patrick Elliott a écrit :
> On 8/5/2013 1:44 AM, scott wrote:
>>>   vector bbox1 = <pos.x - left, pos.y + boxlen, pos.z - bottom>;
>>>   vector bbox2 = <pos.x + right, pos.y + boxlen, pos.z + top>;
>>>   vector bbox3 = <pos.x - left, pos.y + boxlen + length, pos.z -
>>> bottom>;
>>>   vector bbox4 = <pos.x - right, pos.y + boxlen + length, pos.z + top>;
>>
>> Do you mean "pos.x + right" in that last line?
>>
>>> integer isInsideBox(vector bbox1, vector bbox2, vector bbox3, vector
>>> bbox4)
>>> {
>>>    vector P = llDectectedPos(0);
>>>    vector A1 = <bbox1.x,bbox2.y,bbox1.z>;
>>>    vector B1 = <bbox2.x,bbox2.y,bbox1.z>;
>>>    vector C1 = <bbox2.x,bbox1.y,bbox1.z>;
>>>    vector D1 = <bbox1.x,bbox1.y,bbox1.z>;
>>  >    vector A2 = <bbox3.x,bbox4.y,bbox3.z>;
>>  >    vector B2 = <bbox4.x,bbox4.y,bbox3.z>;
>>  >    vector C2 = <bbox4.x,bbox3.y,bbox3.z>;
>>  >    vector D2 = <bbox3.x,bbox3.y,bbox3.z>;
>>
>> If you substitute in your values for bbox1-4 from above you get the
>> following (I left out the pos.x,pos.y,pos.z):
>>
>> A1 = <-left  , boxlen , -bottom>
>> B1 = < right , boxlen , -bottom>
>> C1 = < right , boxlen , -bottom>
>> D1 = <-left  , boxlen , -bottom>
>>
>> A2 = <-left  , boxlen+length , -bottom>
>> B2 = < right , boxlen+length , -bottom>
>> C2 = < right , boxlen+length , -bottom>
>> D2 = <-left  , boxlen+length , -bottom>
>>
>> Is this really what you are expecting?
>>
>> If you are trying to see if a point is inside a box, then it might be
>> simpler to think of the box as being bounded by 6 infinite planes (one
>> for each face), then testing which side of each plane the point is on.
>> If it's on the "inside" of all 6 planes then it's inside the box.

That's a good idea.

>>
> lol What part of, "I know I screwed up the math.", did people miss. ;)
> 
> Seriously though, Le_Fogeron says it wouldn't work anyway... :p

The test against 6 planes would work, and is easy if it is axis aligned.
If it is rotated, you have "just" to apply the same maths, it's just the
formula which become a bit harder (a plane equation is ax+by+cz+d = 0,
one side of the plane is wherer ax+by+cz+d > 0, and the other side is <0)
There is an infinity of 4D vector <a,b,c,d> to match a single plane
(indeed, if V is such vector, k.V is also another vector)
(also notice that if V is such vector, -V is the same plane but with the
inversion of the sides)
So, instead of thinking "corner of box" (8) to be grouped in
squares/side, you should have to think "plane's equation" (6).

Notice that scaling & shearing leaves plane as plane, so even if you
were to use a sheared box (such as a truncated pyramid), it would still
works.

What I said was that extending the "smart" 2D triangle-based-tests to 3D
are to be a nightmare.



-- 
Just because nobody complains does not mean all parachutes are perfect.


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 00:00:02
Message: <520074c2$1@news.povray.org>
On 8/5/2013 4:35 AM, scott wrote:
>>> Thus, only testing "one" box, and only on that single plane.
>>>
>>> Then again, I screwed up the last idea so badly... lol
>>
>> And, speaking of which.. again, I forget that the "distance" won't work
>> for objects wider, or taller, than the distance... Sigh...
>
> Make your bounding box the value of "distance" bigger than the bounding
> box of the object's geometry. That way you are checking for people
> within "distance" from the *edge* of the object, not from the centre.
Only, then it detecting them too far away, when standing directly in 
front of it. If I want someone to be able to open a door from 5 meters, 
it should be 5 meters, regardless of where they are, when they do it. 
Or, in the specific case that led me to hunt for a solution, they can't 
be a) on the wrong side of a counter, b) farther than 3 meters from the 
safe, c) outside the building (i.e., behind the thing), or d) standing 
on the other side of the wall, near the safe (SL lets you pan you camera 
through things, with some of its controls, so you can't stop them 
clicking the thing, through a wall. This means a very narrow range of 
"usable" space, and distance. And the "alley" I need to test, is not 
much wider than the safe itself.

I could have gotten by with a fairly simple "angle" test, and distance, 
to see if they where close enough, in this specific case. But, not so 
with something bigger, like my hypothetical garage door.

Hmm. There is a possibility though..

avPos = llDetectedPos(0);
cPos = llGetPos(0);
ab = llGetAngleBetween(avPos, cPos);
TestDistance = ???(ab) * 5;

I.e., make the angle determine the "distance" so that every point in the 
detection range will "always" be the same distance from the object. Ur.. 
What would be the math for drawing a straight line, using a string, 
attached to a immobile peg exactly? lol


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 00:11:20
Message: <52007768$1@news.povray.org>
On 8/5/2013 4:38 AM, scott wrote:
> There are much easier, well documented, ways for doing bounding box
> tests, you don't need to go into splitting it up to squares and
> triangles and measuring areas as you seem to have done. If that's what
> you want to do?
>
Yeah, basically. What I searched google for was, basically, "Find if 
point is in a box". And, well, adding "in 3D" didn't seem to help much. 
lol I completely forgot to search on "bounding box". :p

My actual theory here though, if its more understandable, was like.. If 
you had an aquarium, which you could look into, from any two sides, and 
a 90 degree angle from each other, but you couldn't get around to any of 
the other sides, and you needed to "prove" mathematically, that an 
object in it was "actually" in the aquarium, and not outside.

So, logically, you take two sides, that are at 90 degrees from each 
other, than mathematically test of you can "see" the object from those 
two sides, "inside" of the rectangle each side represented.

In principle, this should work. What I screwed up with was that I need 
two sets of calculations. One set is other original, from here (if your 
mouse is in the box, the box turns red):

http://www.emanueleferonato.com/2012/03/09/algorithm-to-determine-if-a-point-is-inside-a-square-with-mathematics-no-hit-test-involved/

Then, completely screwed up, by trying to reuse the same exact 
equations, for both sides (or, rather, the same "components" of the 
vectors).


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 00:20:50
Message: <520079a2@news.povray.org>
On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>
> The test against 6 planes would work, and is easy if it is axis aligned.
 > ...
> What I said was that extending the "smart" 2D triangle-based-tests to 3D
> are to be a nightmare.
>
Still not seeing why two planes wouldn't, see my "is it in the aquarium" 
explanation from my reply to scott.

But, in any case, I think there may be a simpler solution, which, like 
my original thought, only requires "adjusting" the location of the 
object being tested for, by canceling its apparent rotation (or, rather, 
getting it lined up so its where the box would be, if the box wasn't 
rotated either), and, it doesn't require a box at all, just an angle 
test, and a distance (which depends on the angle). It does require some 
checking, to make sure they are actually within the allowed angles, but..

Hmm. Actually, now that I think of it, that also have issues.. I am 
thinking I need to check the distance, as per "directly in front" of 
something, like a big door, but the "center" might be, itself, several 
meters over the ground, so.. I need draw a "wall" with a piece of chalk, 
on string, attached to a fixed "center point", not just a line... Sigh.. 
Why does 3D have to get so complicated? lol


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 01:40:10
Message: <52008c3a@news.povray.org>
On 8/5/2013 9:00 PM, Patrick Elliott wrote:

> avPos = llDetectedPos(0);
> cPos = llGetPos(0);
> ab = llGetAngleBetween(avPos, cPos);
> TestDistance = ???(ab) * 5;

Range = 5;
TestDistance = (Range - x * cos(ab)))/sin(ab);

So.. How do I get that to make a "wall" instead of just a 2D line? Use z 
in a second one, then check both?

Uh, coordinate system they use is Z = up.

No, wait, that just give me a plain, without telling me if its inside 
the box on that plane.. Sigh.. Right back to having to test if its in 
the box... Suppose, combining the two..

:head-> desk, head-> desk, head-> desk, head-> desk, head-> desk, ouch!: lol


Post a reply to this message

From: Le Forgeron
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 02:16:34
Message: <520094c2$1@news.povray.org>
Le 06/08/2013 06:20, Patrick Elliott a écrit :
> On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>>
>> The test against 6 planes would work, and is easy if it is axis aligned.
>> ...
>> What I said was that extending the "smart" 2D triangle-based-tests to 3D
>> are to be a nightmare.
>>
> Still not seeing why two planes wouldn't, see my "is it in the aquarium"
> explanation from my reply to scott.

the "Aquarium" is using projections (2) and has hidden implication (the
projections are at 90° angle).

you could as well use only 1 projections and an additional "distance
from point to its projection".
Your main issue so far is projecting on arbitrary rotated plane/square.
and it won't be easy.

> 
> But, in any case, I think there may be a simpler solution,

Simpler than evaluating the sign of 6 first-degree equations ?
P(x,y,z) the point to test,
 Vn(An,Bn,Cn,Dn) [n:1 to 6], the 4D vector representing the planes of
the box (oriented so that inside is >0)
 are all signs of x.An+y.Bn+z.Cn+Dn positive ?

the plane XY at height z=10 is <0,0,1,-10> (or in the opposite direction
<0,0,-1,10> ), where is the difficulty ?

-- 
Just because nobody complains does not mean all parachutes are perfect.


Post a reply to this message

From: scott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 06:19:11
Message: <5200cd9f$1@news.povray.org>
> Or, in the specific case that led me to hunt for a solution, they can't
> be a) on the wrong side of a counter, b) farther than 3 meters from the
> safe, c) outside the building (i.e., behind the thing), or d) standing
> on the other side of the wall, near the safe (SL lets you pan you camera
> through things, with some of its controls, so you can't stop them
> clicking the thing, through a wall. This means a very narrow range of
> "usable" space, and distance. And the "alley" I need to test, is not
> much wider than the safe itself.

Sounds to me like you just have to bite the bullet and define a custom 
bounding box (or group of bounding boxes if the shape you want isn't a 
box) for each object.

FWIW most 3D games work like this, each object has the geometry, and 
then also some form of bounding object (far less complex than the 
geometry) for the purposes of collision detection. It looks like you 
want something similar, a bounding object that defines the space within 
which you can interact with the object.


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 21:19:24
Message: <5201a09c$1@news.povray.org>
On 8/6/2013 3:19 AM, scott wrote:
>> Or, in the specific case that led me to hunt for a solution, they can't
>> be a) on the wrong side of a counter, b) farther than 3 meters from the
>> safe, c) outside the building (i.e., behind the thing), or d) standing
>> on the other side of the wall, near the safe (SL lets you pan you camera
>> through things, with some of its controls, so you can't stop them
>> clicking the thing, through a wall. This means a very narrow range of
>> "usable" space, and distance. And the "alley" I need to test, is not
>> much wider than the safe itself.
>
> Sounds to me like you just have to bite the bullet and define a custom
> bounding box (or group of bounding boxes if the shape you want isn't a
> box) for each object.
>
> FWIW most 3D games work like this, each object has the geometry, and
> then also some form of bounding object (far less complex than the
> geometry) for the purposes of collision detection. It looks like you
> want something similar, a bounding object that defines the space within
> which you can interact with the object.
>
>
Yeah, that was.. kind of what I thought I was doing, just.. really 
badly. lol


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 6 Aug 2013 22:07:01
Message: <5201abc5$1@news.povray.org>
On 8/5/2013 11:16 PM, Le_Forgeron wrote:
> Le 06/08/2013 06:20, Patrick Elliott a écrit :
>> On 8/5/2013 4:43 AM, Le_Forgeron wrote:
>>>
>>> The test against 6 planes would work, and is easy if it is axis aligned.
>>> ...
>>> What I said was that extending the "smart" 2D triangle-based-tests to 3D
>>> are to be a nightmare.
>>>
>> Still not seeing why two planes wouldn't, see my "is it in the aquarium"
>> explanation from my reply to scott.
>
> the "Aquarium" is using projections (2) and has hidden implication (the
> projections are at 90° angle).
>
> you could as well use only 1 projections and an additional "distance
> from point to its projection".
> Your main issue so far is projecting on arbitrary rotated plane/square.
> and it won't be easy.
>
>>
>> But, in any case, I think there may be a simpler solution,
>
> Simpler than evaluating the sign of 6 first-degree equations ?
> P(x,y,z) the point to test,
>   Vn(An,Bn,Cn,Dn) [n:1 to 6], the 4D vector representing the planes of
> the box (oriented so that inside is >0)
>   are all signs of x.An+y.Bn+z.Cn+Dn positive ?
>
> the plane XY at height z=10 is <0,0,1,-10> (or in the opposite direction
> <0,0,-1,10> ), where is the difficulty ?
>
Ah, I see. Your looking at 'ax + by + cz - d = 0' It should be - for the 
last term, right, to be correct, or is it + because of what you are 
trying to do with it? The dots, instead of * threw me there, for a second.

Hmm.. I need to work out "where" the planes are, to test them, and that 
means the vector normal for it, which is dependent on the object 
rotation, right? So.. Which, if I am right, means I don't need to even 
know where the corners are (which was a "big") problem, when the thing 
was rotated.

norm = llVecNorm(<1,0,0> * llGetRot() * dist);

would give me "one" plane, and I can get another from that too, with a 
farther/shorter distance, where the results are <norm.x, norm.y, norm.z, 
dist> and <norm.x2, norm.y2, norm.z2, dist2>, but the I need to find the 
vector normals for the other four sides.

Mind, such a test could handle even non-box results, like trapezoids, 
but requires.. Ah, I know.. I need to just add in a rotation for the 
axis I want to test my other "sides" against, which are at:

llVecNorm(<1,0,0> * llGetRot() * <90,0,0> * dist3);
llVecNorm(<1,0,0> * llGetRot() * <90,90,0> * dist4);
llVecNorm(<1,0,0> * llGetRot() * <90, 180,0> * dist5);
llVecNorm(<1,0,0> * llGetRot() * <90,270,0> * dist6);

(or the quaternion equivalent, since Euler will go batshit if I try to 
rotate two axis at once, using their conversion functions...)

Realizing that,
dist1 = from the door/object.
dist2 = length of bounding box.
dist3 = left distance, from center of bounding box.
dist4 = up distance, from center of bounding box.
dist5 = right distance, from center of bounding box.
dist6 = down distance, from center of bounding box.

Or.. which ever directions those are.. ;) It doesn't matter though, 
since its still going to be right, I think. Unless I got the 90 degree 
angle I need to also twist around wrong, somehow). Yeah, that is doable, 
I think.

Hmm. Wait, that gives me planes, but.. how does the test happen? 
Actually, I think you may have really lost me, or I missed something, or 
you assumed I had a clue about something I didn't, or.. something.. lol


Post a reply to this message

From: scott
Subject: Re: Math question (inside box)
Date: 7 Aug 2013 05:11:52
Message: <52020f58$1@news.povray.org>
> Mind, such a test could handle even non-box results, like trapezoids,
> but requires.. Ah, I know.. I need to just add in a rotation for the
> axis I want to test my other "sides" against, which are at:

Indeed, the multiple-planes approach can handle any convex object. If 
you want a concave object (eg an "L" shape) you need to split it up in 
to multiple boxes and test each one separately.

> Hmm. Wait, that gives me planes, but.. how does the test happen?
> Actually, I think you may have really lost me, or I missed something, or
> you assumed I had a clue about something I didn't, or.. something.. lol

Once you've got the equations for your planes (ie Ax+By+Cz+D=0) then you 
plug in your point position for xyz and evaluate the result.

If the result is 0 then the point is exactly on the plane, if it's >0 
it's on one side, <0 the other side.

So for example suppose your "right" plane is at a distance 5 along the X 
axis, your plane equation would be 1*x + 0*y + 0*z - 5

Now you can take some points and plug it into that equation:

P=(0,1,2) gives 1*0 + 0*1 + 0*2 -5 = -5 (negative, so on left of plane)

P=(10,5,4) gives 1*10 + 0*5 + 0*4 -5 = 5 (positive, so on right of plane)

You just need to check that your point is on the "inside" of each of the 
6 planes that make up your box, then you know for sure it is inside the box.

Your other plane equations for the box might be:

-1*x + 0*y + 0*z - 3 (left plane)
  0*x + 1*y + 0*z - 2 (top plane)
  0*x - 1*y + 0*z - 0 (bottom plane)
  0*x + 0*y + 1*z - 4 (front plane)
  0*x + 0*y - 1*z - 1 (back plane)

Slightly off-topic I know, but those are the same numbers you can use in 
the POV "plane" object :-)


Post a reply to this message

From: Patrick Elliott
Subject: Re: Math question (inside box)
Date: 8 Aug 2013 02:55:57
Message: <520340fd$1@news.povray.org>
On 8/7/2013 2:11 AM, scott wrote:
>> Mind, such a test could handle even non-box results, like trapezoids,
>> but requires.. Ah, I know.. I need to just add in a rotation for the
>> axis I want to test my other "sides" against, which are at:
>
> Indeed, the multiple-planes approach can handle any convex object. If
> you want a concave object (eg an "L" shape) you need to split it up in
> to multiple boxes and test each one separately.
>
>> Hmm. Wait, that gives me planes, but.. how does the test happen?
>> Actually, I think you may have really lost me, or I missed something, or
>> you assumed I had a clue about something I didn't, or.. something.. lol
>
> Once you've got the equations for your planes (ie Ax+By+Cz+D=0) then you
> plug in your point position for xyz and evaluate the result.
>
> If the result is 0 then the point is exactly on the plane, if it's >0
> it's on one side, <0 the other side.
>
> So for example suppose your "right" plane is at a distance 5 along the X
> axis, your plane equation would be 1*x + 0*y + 0*z - 5
>
> Now you can take some points and plug it into that equation:
>
> P=(0,1,2) gives 1*0 + 0*1 + 0*2 -5 = -5 (negative, so on left of plane)
>
> P=(10,5,4) gives 1*10 + 0*5 + 0*4 -5 = 5 (positive, so on right of plane)
>
> You just need to check that your point is on the "inside" of each of the
> 6 planes that make up your box, then you know for sure it is inside the
> box.
>
> Your other plane equations for the box might be:
>
> -1*x + 0*y + 0*z - 3 (left plane)
>   0*x + 1*y + 0*z - 2 (top plane)
>   0*x - 1*y + 0*z - 0 (bottom plane)
>   0*x + 0*y + 1*z - 4 (front plane)
>   0*x + 0*y - 1*z - 1 (back plane)
>
> Slightly off-topic I know, but those are the same numbers you can use in
> the POV "plane" object :-)
>
Ah. OK. That make perfect sense. Definitely need, one of these days, to 
take more math. lol Though, honestly, I have always had much the same 
problem with "equations" as with function calls. Remembering what I want 
to do (or, say.. the function name) is the easy part, its all the fiddly 
bits, which make it work, like.. the actual written equation, or the 
parameters for the call, which screwed me up. lol

Hmm. I do, in this case, since there are "at origin", need to also do:

AVPos = llDetectedPos(0) - llGetPos();

I think, so that the "location" I am testing against is actually based 
on where the box is, not some other place. Otherwise, I would have to 
"add" that position, to all the values. After all, its not at the 
origin, but the equations "assume" that it is.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.