Jump to content

Detect if a point is within an upright prism


primerib1
 Share

Recommended Posts

  • Given a volume in the shape of an upright prism whose base is a parallelogram that lies flat/parallel to the world XY plane (plane of constant Z)
  • The parallelogram defined by an origin vector, and 2 adjacent vertices (vertex1 and vertex2) all with the same Z as origin,
  • And the prism additionally have a height
  • Then the following function will return TRUE if a 3D coordinate (vector) pos is within the prism:
integer InPrism(vector origin, vector vertex1, vector vertex2, float height, vector pos) {
    float m = pos.z - origin.z;
    if ((m < 0.0) || (m > height)) return FALSE;

    float a = vertex1.x - origin.x;
    float b = vertex2.x - origin.x;
    float c = pos.x - origin.x;
    float d = vertex1.y - origin.y;
    float e = vertex2.y - origin.y;
    float f = pos.y - origin.y;

    float divider = (a * e) - (b * d);

    m = ((c * e) - (b * f)) / divider;
    if ((m < 0.0) || (m > 1.0)) return FALSE;
    m = ((a * f) - (c * d)) / divider;
    if ((m < 0.0) || (m > 1.0)) return FALSE;

    return TRUE;
}

What is this useful for?

Well, probably can be used in place of a multitude of invisiprims all with their own script all doing their own llVolumeDetect() ...

 

EDIT: HOW IT WORKS

First, it finds out if pos is between the lower bound and upper bound of the prism.

Then, limiting to the 2D (X, Y) plane, it finds out the 2D vector for each of: O-V1, O-V2, O-pos

Then, it orthogonalizes the O-pos vector into multiples of O-V1 and O-V2, let's call this m1 and m2.

pos is within the parallelogram if and only if 0 < m1 < 1.0 and 0 < m2 < 1.0

The case where pos is on the edge of the parallelogram is kinda finicky to match (floating point accuracy limit), so the test is for inequality only.

 

Edited by primerib1
  • Thanks 1
Link to comment
Share on other sites

Posted (edited)

Here's an example how I used this to detect people inside of designated stall areas in my stable:

list STALLS = [
    <13.6, 122.8, 115.0>, <13.6, 120.0, 0.0>, <37.3, 122.8, 0.0>, 50,
    <13.7, 128.7, 115.0>, <13.7, 131.5, 0.0>, <28.5, 128.7, 0.0>, 50
];

integer InStalls(vector pos) {
    vector origin;
    vector vertex1;
    vector vertex2;
    float height;
    integer i = -1;
    do {
        origin = llList2Vector(STALLS, ++i);
        vertex1 = llList2Vector(STALLS, ++i);
        vertex2 = llList2Vector(STALLS, ++i);
        height = llList2Float(STALLS, ++i);
        if (InPrism(origin, vertex1, vertex2, height, pos)) return TRUE;
    } while (i < 7);
    return FALSE;
}

1 script, zero invisiprims, to watch over 2 disconnected areas of dissimilar sizes.

Edited by primerib1
  • Like 1
Link to comment
Share on other sites

  • primerib1 changed the title to Detect if a point is within an upright prism
  • 3 weeks later...
On 3/4/2024 at 7:07 PM, primerib1 said:

Here's an example how I used this to detect people inside of designated stall areas in my stable:

list STALLS = [
    <13.6, 122.8, 115.0>, <13.6, 120.0, 0.0>, <37.3, 122.8, 0.0>, 50,
    <13.7, 128.7, 115.0>, <13.7, 131.5, 0.0>, <28.5, 128.7, 0.0>, 50
];

integer InStalls(vector pos) {
    vector origin;
    vector vertex1;
    vector vertex2;
    float height;
    integer i = -1;
    do {
        origin = llList2Vector(STALLS, ++i);
        vertex1 = llList2Vector(STALLS, ++i);
        vertex2 = llList2Vector(STALLS, ++i);
        height = llList2Float(STALLS, ++i);
        if (InPrism(origin, vertex1, vertex2, height, pos)) return TRUE;
    } while (i < 7);
    return FALSE;
}

1 script, zero invisiprims, to watch over 2 disconnected areas of dissimilar sizes.

Do note that for the "vertex1" and "vertex2" vectors, I purposefully set their Z value to 0.0, because the Z value for the vertices are ignored anyways.

Link to comment
Share on other sites

On 3/4/2024 at 7:03 PM, primerib1 said:

EDIT: HOW IT WORKS

First, it finds out if pos is between the lower bound and upper bound of the prism.

Then, limiting to the 2D (X, Y) plane, it finds out the 2D vector for each of: O-V1, O-V2, O-pos

Then, it orthogonalizes the O-pos vector into multiples of O-V1 and O-V2, let's call this m1 and m2.

pos is within the parallelogram if and only if 0 < m1 < 1.0 and 0 < m2 < 1.0

The case where pos is on the edge of the parallelogram is kinda finicky to match (floating point accuracy limit), so the test is for inequality only.

In theory, steps 2 and on can also be used to orthogonalize the Origin-Pos vector in 3D space, allowing detection for a non-upright prism volume.

But the maths become so complex it gave me a headache ... plus

  1. Performance tanks due to how much float calculation is happening
  2. Debugging is a nightmare
  3. There is not much need to detect a pos in a non-upright-prism volume

So I optimized the scenario and the code for an upright prism volume instead. Which covers like, probably 95% of use cases...

Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...