Dart Documentationbox2d_htmlDistance

Distance class

This is non-static for faster pooling. To get an instance, use the SingletonPool rather than construct a distance object.

class Distance {
  int calls;
  int iters;
  int maxIters;

  /** Pool variables for use in distance calculation. */
  Simplex simplex;
  List<int> saveA;
  List<int> saveB;
  Vector closestPoint;
  Vector searchDirection;
  Vector temp;
  Vector normal;

  /**
   * Construct a new Distance object. For internal use only. Don't directly
   * invoke.
   */
  Distance._construct() :
    simplex = new Simplex(),
    saveA = new List<int>(3),
    saveB = new List<int>(3),
    closestPoint = new Vector(),
    searchDirection = new Vector(),
    temp = new Vector(),
    normal = new Vector(),
    calls = 0,
    iters = 0,
    maxIters = 20 { }

  /**
   * Compute the closest points between two shapes. Supports any combination of:
   * CircleShape and PolygonShape. The simplex cache is input/output.
   * On the first call set SimplexCache.count to zero.
   */
  void distance(DistanceOutput output, SimplexCache cache,
      DistanceInput input) {
    calls++;

    final DistanceProxy proxyA = input.proxyA;
    final DistanceProxy proxyB = input.proxyB;

    Transform transformA = input.transformA;
    Transform transformB = input.transformB;

    // Initialize the simplex.
    simplex.readCache(cache, proxyA, transformA, proxyB, transformB);

    // Get simplex vertices as an array.
    List<SimplexVertex> vertices = simplex.vertices;

    // These store the vertices of the last simplex so that we
    // can check for duplicates and prevent cycling.
    // (pooled above)
    int saveCount = 0;

    simplex.getClosestPoint(closestPoint);
    num distanceSqr1 = closestPoint.lengthSquared;
    num distanceSqr2 = distanceSqr1;

    // Main iteration loop
    int iter = 0;
    while (iter < maxIters) {

      // Copy simplex so we can identify duplicates.
      saveCount = simplex.count;
      for (int i = 0; i < saveCount; i++) {
        saveA[i] = vertices[i].indexA;
        saveB[i] = vertices[i].indexB;
      }

      switch (simplex.count) {
        case 1 :
          break;
        case 2 :
          simplex.solve2();
          break;
        case 3 :
          simplex.solve3();
          break;
        default :
          assert (false);
      }

      // If we have 3 points, then the origin is in the corresponding triangle.
      if (simplex.count == 3)
        break;

      // Compute closest point.
      simplex.getClosestPoint(closestPoint);
      distanceSqr2 = closestPoint.lengthSquared;

      distanceSqr1 = distanceSqr2;

      // get search direction;
      simplex.getSearchDirection(searchDirection);

      // Ensure the search direction is numerically fit.
      if (searchDirection.lengthSquared < Settings.EPSILON * Settings.EPSILON) {
        // The origin is probably contained by a line segment
        // or triangle. Thus the shapes are overlapped.

        // We can't return zero here even though there may be overlap.
        // In case the simplex is a point, segment, or triangle it is difficult
        // to determine if the origin is contained in the CSO or very close to
        // it.
        break;
      }

      // Compute a tentative new simplex vertex using support points.
      SimplexVertex vertex = vertices[simplex.count];

      Matrix22.mulTransMatrixAndVectorToOut(transformA.rotation,
          searchDirection.negateLocal(), temp);
      vertex.indexA = proxyA.getSupport(temp);
      Transform.mulToOut(transformA, proxyA.vertices[vertex.indexA],
          vertex.wA);
      // Vec2 wBLocal;
      Matrix22.mulTransMatrixAndVectorToOut(transformB.rotation,
          searchDirection.negateLocal(), temp);
      vertex.indexB = proxyB.getSupport(temp);
      Transform.mulToOut(transformB, proxyB.vertices[vertex.indexB],
          vertex.wB);
      vertex.w.setFrom(vertex.wB).subLocal(vertex.wA);

      // Iteration count is equated to the number of support point calls.
      ++iter;
      ++iters;

      // Check for duplicate support points. This is the main termination
      // criteria.
      bool duplicate = false;
      for (int i = 0; i < saveCount; ++i) {
        if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
          duplicate = true;
          break;
        }
      }

      // If we found a duplicate support point we must exit to avoid cycling.
      if (duplicate)
        break;

      // New vertex is ok and needed.
      ++simplex.count;
    }

    maxIters = Math.max(maxIters, iter);

    // Prepare output.
    simplex.getWitnessPoints(output.pointA, output.pointB);
    output.distance = MathBox.distance(output.pointA, output.pointB);
    output.iterations = iter;

    // Cache the simplex.
    simplex.writeCache(cache);

    // Apply radii if requested.
    if (input.useRadii) {
      num rA = proxyA.radius;
      num rB = proxyB.radius;

      if (output.distance > rA + rB && output.distance > Settings.EPSILON) {
        // Shapes are still no overlapped.
        // Move the witness points to the outer surface.
        output.distance -= rA + rB;
        normal.setFrom(output.pointB).subLocal(output.pointA);
        normal.normalize();
        temp.setFrom(normal).mulLocal(rA);
        output.pointA.addLocal(temp);
        temp.setFrom(normal).mulLocal(rB);
        output.pointB.subLocal(temp);
      } else {
        // Shapes are overlapped when radii are considered.
        // Move the witness points to the middle.
        output.pointA.addLocal(output.pointB).mulLocal(.5);
        output.pointB.setFrom(output.pointA);
        output.distance = 0.0;
      }
    }
  }
}

Constructors

new Distance._construct() #

Construct a new Distance object. For internal use only. Don't directly invoke.

Distance._construct() :
  simplex = new Simplex(),
  saveA = new List<int>(3),
  saveB = new List<int>(3),
  closestPoint = new Vector(),
  searchDirection = new Vector(),
  temp = new Vector(),
  normal = new Vector(),
  calls = 0,
  iters = 0,
  maxIters = 20 { }

Properties

int calls #

int calls;

Vector closestPoint #

Vector closestPoint;

int iters #

int iters;

int maxIters #

int maxIters;

Vector normal #

Vector normal;

final Type runtimeType #

inherited from Object

A representation of the runtime type of the object.

external Type get runtimeType;

List<int> saveA #

List<int> saveA;

List<int> saveB #

List<int> saveB;

Vector searchDirection #

Vector searchDirection;

Simplex simplex #

Pool variables for use in distance calculation.

Simplex simplex;

Vector temp #

Vector temp;

Operators

bool operator ==(other) #

inherited from Object

The equality operator.

The default behavior for all Objects is to return true if and only if this and other are the same object.

If a subclass overrides the equality operator it should override the hashCode method as well to maintain consistency.

bool operator ==(other) => identical(this, other);

Methods

void distance(DistanceOutput output, SimplexCache cache, DistanceInput input) #

Compute the closest points between two shapes. Supports any combination of: CircleShape and PolygonShape. The simplex cache is input/output. On the first call set SimplexCache.count to zero.

void distance(DistanceOutput output, SimplexCache cache,
    DistanceInput input) {
  calls++;

  final DistanceProxy proxyA = input.proxyA;
  final DistanceProxy proxyB = input.proxyB;

  Transform transformA = input.transformA;
  Transform transformB = input.transformB;

  // Initialize the simplex.
  simplex.readCache(cache, proxyA, transformA, proxyB, transformB);

  // Get simplex vertices as an array.
  List<SimplexVertex> vertices = simplex.vertices;

  // These store the vertices of the last simplex so that we
  // can check for duplicates and prevent cycling.
  // (pooled above)
  int saveCount = 0;

  simplex.getClosestPoint(closestPoint);
  num distanceSqr1 = closestPoint.lengthSquared;
  num distanceSqr2 = distanceSqr1;

  // Main iteration loop
  int iter = 0;
  while (iter < maxIters) {

    // Copy simplex so we can identify duplicates.
    saveCount = simplex.count;
    for (int i = 0; i < saveCount; i++) {
      saveA[i] = vertices[i].indexA;
      saveB[i] = vertices[i].indexB;
    }

    switch (simplex.count) {
      case 1 :
        break;
      case 2 :
        simplex.solve2();
        break;
      case 3 :
        simplex.solve3();
        break;
      default :
        assert (false);
    }

    // If we have 3 points, then the origin is in the corresponding triangle.
    if (simplex.count == 3)
      break;

    // Compute closest point.
    simplex.getClosestPoint(closestPoint);
    distanceSqr2 = closestPoint.lengthSquared;

    distanceSqr1 = distanceSqr2;

    // get search direction;
    simplex.getSearchDirection(searchDirection);

    // Ensure the search direction is numerically fit.
    if (searchDirection.lengthSquared < Settings.EPSILON * Settings.EPSILON) {
      // The origin is probably contained by a line segment
      // or triangle. Thus the shapes are overlapped.

      // We can't return zero here even though there may be overlap.
      // In case the simplex is a point, segment, or triangle it is difficult
      // to determine if the origin is contained in the CSO or very close to
      // it.
      break;
    }

    // Compute a tentative new simplex vertex using support points.
    SimplexVertex vertex = vertices[simplex.count];

    Matrix22.mulTransMatrixAndVectorToOut(transformA.rotation,
        searchDirection.negateLocal(), temp);
    vertex.indexA = proxyA.getSupport(temp);
    Transform.mulToOut(transformA, proxyA.vertices[vertex.indexA],
        vertex.wA);
    // Vec2 wBLocal;
    Matrix22.mulTransMatrixAndVectorToOut(transformB.rotation,
        searchDirection.negateLocal(), temp);
    vertex.indexB = proxyB.getSupport(temp);
    Transform.mulToOut(transformB, proxyB.vertices[vertex.indexB],
        vertex.wB);
    vertex.w.setFrom(vertex.wB).subLocal(vertex.wA);

    // Iteration count is equated to the number of support point calls.
    ++iter;
    ++iters;

    // Check for duplicate support points. This is the main termination
    // criteria.
    bool duplicate = false;
    for (int i = 0; i < saveCount; ++i) {
      if (vertex.indexA == saveA[i] && vertex.indexB == saveB[i]) {
        duplicate = true;
        break;
      }
    }

    // If we found a duplicate support point we must exit to avoid cycling.
    if (duplicate)
      break;

    // New vertex is ok and needed.
    ++simplex.count;
  }

  maxIters = Math.max(maxIters, iter);

  // Prepare output.
  simplex.getWitnessPoints(output.pointA, output.pointB);
  output.distance = MathBox.distance(output.pointA, output.pointB);
  output.iterations = iter;

  // Cache the simplex.
  simplex.writeCache(cache);

  // Apply radii if requested.
  if (input.useRadii) {
    num rA = proxyA.radius;
    num rB = proxyB.radius;

    if (output.distance > rA + rB && output.distance > Settings.EPSILON) {
      // Shapes are still no overlapped.
      // Move the witness points to the outer surface.
      output.distance -= rA + rB;
      normal.setFrom(output.pointB).subLocal(output.pointA);
      normal.normalize();
      temp.setFrom(normal).mulLocal(rA);
      output.pointA.addLocal(temp);
      temp.setFrom(normal).mulLocal(rB);
      output.pointB.subLocal(temp);
    } else {
      // Shapes are overlapped when radii are considered.
      // Move the witness points to the middle.
      output.pointA.addLocal(output.pointB).mulLocal(.5);
      output.pointB.setFrom(output.pointA);
      output.distance = 0.0;
    }
  }
}

new Distance._construct() #

Construct a new Distance object. For internal use only. Don't directly invoke.

Distance._construct() :
  simplex = new Simplex(),
  saveA = new List<int>(3),
  saveB = new List<int>(3),
  closestPoint = new Vector(),
  searchDirection = new Vector(),
  temp = new Vector(),
  normal = new Vector(),
  calls = 0,
  iters = 0,
  maxIters = 20 { }

int hashCode() #

inherited from Object

Get a hash code for this object.

All objects have hash codes. Hash codes are guaranteed to be the same for objects that are equal when compared using the equality operator ==. Other than that there are no guarantees about the hash codes. They will not be consistent between runs and there are no distribution guarantees.

If a subclass overrides hashCode it should override the equality operator as well to maintain consistency.

external int hashCode();

noSuchMethod(String name, List args) #

inherited from Object

noSuchMethod is invoked when users invoke a non-existant method on an object. The name of the method and the arguments of the invocation are passed to noSuchMethod. If noSuchMethod returns a value, that value becomes the result of the original invocation.

The default behavior of noSuchMethod is to throw a noSuchMethodError.

external Dynamic noSuchMethod(String name, List args);

const Object() #

inherited from Object

Creates a new Object instance.

Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.

const Object();

String toString() #

inherited from Object

Returns a string representation of this object.

external String toString();