Fork me on GitHub
  • Jump To … +
    GUI.pde Line.pde LineFitter.pde Math.pde Path.pde PathSimplifier.pde PolylineSimplification.pde SimplePathHull.pde
  • ¶

    Math Utilities

  • ¶
  • ¶

    Geometry Class

  • ¶

    Provides elementary geometrical operations

    public static final class Geometry
    {
  • ¶

    Computes the per product (aka. cross product) of two vectors

      public static float per(PVector u, PVector v) {
        return u.x * v.y - v.x * u.y;
      }
  • ¶

    Produces a vector spanned between two points

      public static PVector span(PVector a, PVector b) {
        return PVector.sub(b, a);
      }
  • ¶

    Tests which side of line a given point lies at.

    • Returns positive value if p is on the left side of line through a and b.

    • Returns negative value if p is on the right side of line through a and b.

    • Returns 0 if a, b and p are colinear.

      public static float side(PVector a, PVector b, PVector p) {
        return per(span(a, b), span(a, p));
      }
  • ¶

    Computes the squared distance between two points

      public static float distSq(PVector a, PVector b) {
        float dx = a.x - b.x;
        float dy = a.y - b.y;
        return dx * dx + dy * dy;
      }
  • ¶

    Tests whether segments ab and cd intersect

      public static boolean intersect(PVector a, PVector b, PVector c, PVector d) {
  • ¶

    The segments intersect only if the endpoints of one are on opposite sides of the other (both ways)

        PVector ab = span(a, b), ac = span(a, c), ad = span(a, d);
        float sab = per(ab, ac) * per(ab, ad);
        if (sab > 0)
          return false;
        PVector cd = span(c, d), cb = span(c, b);
        float scd = per(cd, ac) * per(cd, cb);
  • ¶

    Note that ac is used instead of ca in the above line, thus reversing the following condition

        if (scd < 0)
          return false;
  • ¶

    When the points are colinear, we have to check if the segments overlap

        if (sab == 0 && scd == 0) {
          float abSq = ab.magSq();
          return ac.magSq() <= abSq || ad.magSq() < abSq;
        }
        return true;
      }
  • ¶

    Returns a projection of point onto a line

      public static PVector project(PVector p, Line l) {
        float t = -(l.a * p.x + l.b * p.y + l.c) / (l.a * l.a + l.b * l.b);
        return new PVector(p.x + t * l.a, p.y + t * l.b);
      }
  • ¶

    Returns the intersection point of two lines. The result may contain ifinities if the lines are parallel, or NaNs if they are identical.

      public static PVector intersection(Line l1, Line l2) {
        float a11 = l1.a, a12 = l1.b, b1 = -l1.c;
        float a21 = l2.a, a22 = l2.b, b2 = -l2.c;
  • ¶

    We now solve a linear equation Ax = b, where A = [a11 a12; a21 a22], x = [x1; x2] b = [b1; b2]. We use Gaussian elimination method with full pivot selection.

  • ¶

    We rearrange the equation so that the pivot is a11

        boolean swapResult = false;
        if (max(abs(a11), abs(a12)) < max(abs(a21), abs(a22))) {
          float tmp;
          tmp = a11; a11 = a21; a21 = tmp;
          tmp = a12; a12 = a22; a22 = tmp;
          tmp = b1; b1 = b2; b2 = tmp;
        }
        if (abs(a11) < abs(a12)) {
          float tmp;
          tmp = a11; a11 = a12; a12 = tmp;
          tmp = a21; a21 = a22; a22 = tmp;
          swapResult = true;
        }
    
        a22 -= a12 * a21 / a11;
        b2 -= b1 * a21 / a11;
        float x2 = b2 / a22;
        float x1 = (b1 - a12 * x2) / a11;
    
        return swapResult ? new PVector(x2, x1) : new PVector(x1, x2);
      }
    }
  • ¶

    Gets the smallest of five values

    public static float min(float x1, float x2, float x3, float x4, float x5) {
      return min(min(x1, x2, x3), min(x4, x5));
    }
  • ¶

    Gets the biggest of five values

    public static float max(float x1, float x2, float x3, float x4, float x5) {
      return max(max(x1, x2, x3), max(x4, x5));
    }
  • ¶

    Truncates value to given range

    public static float clamp (float x, float a, float b) {
      if (x < a)
        return a;
      else if (b < x)
        return b;
      else return x;
    }
  • ¶

    Truncates value to given range

    public static final int clamp (int x, int a, int b) {
      if (x < a)
        return a;
      else if (b < x)
        return b;
      else return x;
    }
  • ¶

    Determines whether a PVector contains infinities or NaNs

    public static final boolean isSingular(PVector v) {
      return Float.isInfinite(v.x) || Float.isNaN(v.x)
          || Float.isInfinite(v.y) || Float.isNaN(v.y);
    }