0
votes

I am attempting to find the closest point on a finite plane to that is defined by 3 points in 3d space with edges perpendicular and parallel to one another. a fourth point (p) is where I am attempting to calculate the distance from.

Currently, I am projecting the point onto the 'infinite' plane that is defined by the normal of the 3 points and testing whether the projected point is within the bounds of the finite plane. IF it is not, I calculate the closest point on each each and select the minimum. If it is within the bounds of the plane, I just use the distance as determined by the equation to plane.

At the moment my calculations are off for testing that the projected point is within the bounds of the plane.

To test that the correct calculations are being done elsewhere, I am also testing for the closest point of each edge of the planes to the point in question. I have a 'useInfinite' variable, that I am using to test that the 'infinite plane' and distance from has been calculated properly ( which also appears fine ).

This is currently being written in blinkscript with positional data that has been rendered into an image for testing.

I have attached an image that shows the lines where the plane bounds are supposed to be. The shaded area is what is currently being calculated as the bounds of the plane.

Is there a better / more accurate or more appropriate way (under these conditions) to test the distance to a finite plane as I cant figure out what I have done incorrectly with these equations.

/*
 a, b, c:  points on a plane
 p: point to calculate distance from plane
*/
  float distanceFromPlane(float3 a, float3 b, float3 c,  float3 p)  {

    float3 ba = b - a;
    float3 ca = c - a;

    // distance from infinite plane
    float3 N = cross(ba, ca);
    float3 n = normalize(N);
    float3 v = a - p;

    float dist = fabs(dot(v, n));

    // if bounded plane
    if (!useInfinite) {
      // closest coplanar point to plane
      float3 pl_cp = p - (dist * n);

      float3 pa = a - pl_cp;

      float l = dot(a, ba);
      float m = dot(pa, ba);
      float o = dot(b, ba);

      float q = dot(a, ca);
      float r = dot(pa, ca);
      float s = dot(c, ca);


      //test if coplanar point is in bounds
      if (!(
          (l <= m && m <= o) && (q <= r && r <= s)
         ))  {

          /* draw lines to test shaded area is in bounds */

          // distance to closest edge
          float3 d = c + b - a; // 4th corner of rect

          // closest point on each edge
          float labp = length(p - closestPoint(a, b, p));
          float lacp = length(p - closestPoint(a, c, p));
          float lbdp = length(p - closestPoint(b, d, p));
          float lcdp = length(p - closestPoint(c, d, p));

          // find minimum closest edge point
          dist = min(labp, lacp);
          dist = min(dist, lbdp);
          dist = min(dist, lcdp);
      }
    }
  dist -= expand;
  if (dist < 0.001f) dist = 0.001f;

  return dist;
}

render showing distance calculations and incorrect summation of bounded planes - the drawn box of lines is the correct location

1

1 Answers

0
votes

What do such scalar products: l = dot(a, ba), o, q, s mean?

As far as I understand, abc is triangle with right angle a, and you want to determine whether pl_cp lies inside rectangle abcd.

Calculations of pl_cp are correct. Then you can represent pa vector as linear combination of basis vectors ba and ca

Edit:
I have used pa = pl_cp - a to make it consistent with ba and ca

pa = u * ba + v * ca

u = dot(pa, ba) / dot(ba, ba)
v = dot(pa, ca) / dot(ca, ca)

If u and v values lie in range 0..1, then point pl_cp is inside rectangle.

If you actually need the closest edge, it might be found using u and v values (to compare distances, multiply by ba, ca lengths)