Example #1
0
double R3SignedDistance(const R3Plane& plane, const R3Box& box)
{
  // Return signed distance from plane to box
  int ix = (plane.Normal().X() > 0) ? 0 : 1;
  int iy = (plane.Normal().Y() > 0) ? 0 : 1;
  int iz = (plane.Normal().Z() > 0) ? 0 : 1;
  double d1 = R3SignedDistance(plane, box.Corner(ix, iy, iz));
  if (d1 >= 0) return d1;
  double d2 = R3SignedDistance(plane, box.Corner(1-ix, 1-iy, 1-iz));
  if (d2 < 0) return d2;
  else return 0.0;
}
Example #2
0
RNClassID R3Span::
Clip(const R3Plane& plane)
{
    // Characterize endpoints with respect to plane
    RNScalar d1 = R3SignedDistance(plane, Start());
    RNScalar d2 = R3SignedDistance(plane, End());

    // Clip span to plane
    if (RNIsNegative(d1)) {
	if (RNIsNegative(d2)) {
	    // Both points are below plane ???
	    Reset(Start(), Start());
	    return RN_NULL_CLASS_ID;
	}
	else if (RNIsPositive(d2)) {
	    // Start is below, end is above -- move start to plane
	    Reset((Start() * d2 + End() * -d1) / (d2 - d1), End());
	    return R3_SPAN_CLASS_ID;
	}
	else {
	    // Start is below, end is on -- move start to end
	    Reset(End(), End());
	    return R3_POINT_CLASS_ID;
	}
    }
    else if (RNIsPositive(d1)) {
	if (RNIsNegative(d2)) {
	    // Start is above, end is below -- move end to plane
	    Reset(Start(), (Start() * -d2 + End() * d1) / (d1 - d2));
	    return R3_SPAN_CLASS_ID;
	}
	else {
	    // Start is above, end is on or above
	    return R3_SPAN_CLASS_ID;
	}
    }
    else {
	if (RNIsNegative(d2)) {
	    // Start is on, end is below -- move end to start
	    Reset(Start(), Start());
	    return R3_POINT_CLASS_ID;
	}
	else {
	    // Start is on, end is on or above
	    return R3_SPAN_CLASS_ID;
	}
    }
}
Example #3
0
void R3Point::
Project(const R3Plane& plane)
{
    // Move point to closest point on plane
    RNScalar d = R3SignedDistance(plane, *this);
    *this += plane.Normal() * -d;
}
Example #4
0
void R3Point::
Mirror(const R3Plane& plane)
{
    // Mirror point across plane
    RNScalar d = R3SignedDistance(plane, *this);
    *this += plane.Normal() * (-2.0 * d);
}
Example #5
0
double R3Distance(const R3Plane& plane, const R3Box& box)
{
  // Return distance from plane to box
  double d = R3SignedDistance(plane, box);
  if (d > 0) return d;
  else if (d < 0) return -d;
  else return 0.0;
}
Example #6
0
double R3Distance(const R3Plane& plane1, const R3Plane& plane2)
{
  // Return distance from plane to plane
  double d = R3SignedDistance(plane1, plane2);
  if (d > 0) return d;
  else if (d < 0) return -d;
  else return 0.0;
}
Example #7
0
double R3Distance(const R3Line& line, const R3Plane& plane)
{
  // Return distance from line to plane
  double d = R3SignedDistance(plane, line);
  if (d > 0) return d;
  else if (d < 0) return -d;
  else return 0.0;
}
Example #8
0
double R3Distance(const R3Ray& ray, const R3Plane& plane)
{
  // Return distance from ray to plane
  double d = R3SignedDistance(plane, ray);
  if (d > 0) return d;
  else if (d < 0) return -d;
  else return 0.0;
}
Example #9
0
double R3Distance(const R3Point& point, const R3Plane& plane)
{
  // Return distance from point to plane
  double d = R3SignedDistance(plane, point);
  if (d > 0) return d;
  else if (d < 0) return -d;
  else return 0.0;
}
Example #10
0
double R3SignedDistance(const R3Plane& plane, const R3Line& line)
{
  // Return signed distance from plane to line
  if (plane.Normal().Dot(line.Vector()) == 0) {
    // Plane and line are parallel
    return R3SignedDistance(plane, line.Point());
  }
  else {
    // Plane and line are not parallel
    return 0.0;
  }
}
Example #11
0
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Circle& circle)
{
    // Return whether halfspace contains circle
    RNScalar d = R3SignedDistance(halfspace.Plane(), circle.Center());
    if (RNIsNegative(d)) return FALSE;
    else if (RNIsGreater(d, circle.Radius())) return TRUE;
    else {
        RNScalar cos_theta = halfspace.Plane().Normal().Dot(circle.Normal());
	if (cos_theta < 0.0) cos_theta = halfspace.Plane().Normal().Dot(-circle.Normal());
	return (RNIsGreaterOrEqual(d, cos_theta * circle.Radius()));
    }
}
Example #12
0
double R3SignedDistance(const R3Plane& plane, const R3Segment& segment)
{
  // Return signed distance from plane to segment
  double d1 = R3SignedDistance(plane, segment.Start());
  if (d1 > 0) {
    // Start point is above plane
    double d2 = R3SignedDistance(plane, segment.End());
    if (d2 > 0) return ((d1 > d2) ? d2 : d1);
    else return 0.0;
  }
  else if (d1 < 0) {
    // Start point is below plane
    double d2 = R3SignedDistance(plane, segment.End());
    if (d2 < 0) return ((d1 > d2) ? d1 : d2);
    else return 0.0;
  }
  else {
    // Start point is on plane
    return 0.0;
  }
}
Example #13
0
RNBoolean R3Contains(const R3Triangle& triangle, const R3Point& point)
{
    // Check whether triangle bounding shape contains point
    if (!R3Contains(triangle.Box(), point)) return FALSE;

    // Check whether triangle plane contains point
    if (!R3Contains(triangle.Plane(), point)) return FALSE;

    // Compute whether point is on correct side of each edge
    const R3Point& p0 = triangle.Vertex(0)->Position();
    const R3Point& p1 = triangle.Vertex(1)->Position();
    const R3Point& p2 = triangle.Vertex(2)->Position();
    R3Plane h01(p1, triangle.Normal(), p1 - p0);
    if (RNIsNegative(R3SignedDistance(h01, point))) return FALSE;
    R3Plane plane01(p1, triangle.Normal(), p1 - p0);
    if (RNIsNegative(R3SignedDistance(plane01, point))) return FALSE;
    R3Plane plane12(p2, triangle.Normal(), p2 - p1);
    if (RNIsNegative(R3SignedDistance(plane12, point))) return FALSE;
    R3Plane plane20(p0, triangle.Normal(), p0 - p2);
    if (RNIsNegative(R3SignedDistance(plane20, point))) return FALSE;

    // Triangle contains point
    return TRUE;
}
Example #14
0
double R3SignedDistance(const R3Plane& plane, const R3Ray& ray)
{
  // Return signed distance from plane to ray
  double d1 = R3SignedDistance(plane, ray.Start());
  if (d1 > 0) {
    // Start point is above plane
    double dot = ray.Vector().Dot(plane.Normal());
    if (dot < 0) return 0.0;
    else return d1;
  }
  else if (d1 < 0) {
    // Start point is below plane
    double dot = ray.Vector().Dot(plane.Normal());
    if (dot > 0) return 0.0;
    else return d1;
  }
  else {
    // Start point is on plane
    return 0.0;
  }
}
Example #15
0
void R3MeshSearchTree::
FindAll(const R3Point& query_position, const R3Vector& query_normal, RNArray<R3MeshIntersection *>& hits,
  RNScalar min_distance_squared, RNScalar max_distance_squared,
  int (*IsCompatible)(const R3Point&, const R3Vector&, R3Mesh *, R3MeshFace *, void *), void *compatible_data,
  R3MeshFace *face) const
{
  // Check distance to plane
  const R3Plane& plane = mesh->FacePlane(face);
  RNScalar plane_signed_distance = R3SignedDistance(plane, query_position);
  RNScalar plane_distance_squared = plane_signed_distance * plane_signed_distance;
  if (plane_distance_squared >= max_distance_squared) return;

  // Check distance to bounding box
  RNScalar bbox_distance_squared = DistanceSquared(query_position, mesh->FaceBBox(face), max_distance_squared);
  if (bbox_distance_squared >= max_distance_squared) return;

  // Check compatibility
  if (IsCompatible) {
    if (!(*IsCompatible)(query_position, query_normal, mesh, face, compatible_data)) return;
  }

  // Get face vertices
  R3MeshVertex *v0 = mesh->VertexOnFace(face, 0);
  R3MeshVertex *v1 = mesh->VertexOnFace(face, 1);
  R3MeshVertex *v2 = mesh->VertexOnFace(face, 2);

  // Get vertex positions
  const R3Point& p0 = mesh->VertexPosition(v0);
  const R3Point& p1 = mesh->VertexPosition(v1);
  const R3Point& p2 = mesh->VertexPosition(v2);

  // Project query point onto face plane
  const R3Vector& face_normal = mesh->FaceNormal(face);
  R3Point plane_point = query_position - plane_signed_distance * face_normal;

  // Check sides of edges
  R3Vector e0 = p1 - p0;
  e0.Normalize();
  R3Vector n0 = mesh->FaceNormal(face) % e0;
  R3Plane s0(p0, n0);
  RNScalar b0 = R3SignedDistance(s0, plane_point);
  R3Vector e1 = p2 - p1;
  e1.Normalize();
  R3Vector n1 = mesh->FaceNormal(face) % e1;
  R3Plane s1(p1, n1);
  RNScalar b1 = R3SignedDistance(s1, plane_point);
  R3Vector e2 = p0 - p2;
  e2.Normalize();
  R3Vector n2 = mesh->FaceNormal(face) % e2;
  R3Plane s2(p2, n2);
  RNScalar b2 = R3SignedDistance(s2, plane_point);

  // Initialize hit info
  R3MeshIntersection hit;
  hit.type = R3_MESH_NULL_TYPE;

  // Consider plane_point's position in relation to edges of the triangle
  if ((b0 >= 0) && (b1 >= 0) && (b2 >= 0)) {
    // Point is inside face
    if (plane_distance_squared >= min_distance_squared) {
      hit.type = R3_MESH_FACE_TYPE;
      hit.vertex = NULL;
      hit.edge = NULL;
      hit.face = face;
      hit.point = plane_point;
      hit.t = sqrt(plane_distance_squared);
    }
  }
  else {
    // Point is outside face -- check each edge
    if (b0 < 0) {
      // Outside edge0
      R3Vector edge_vector = p1 - p0;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p0;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p0);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v0;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p0;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p1);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v1;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p1;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p0 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 0);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
    if (b1 < 0) {
      // Outside edge1
      R3Vector edge_vector = p2 - p1;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p1;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p1);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v1;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p1;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p2);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v2;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p2;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p1 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 1);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
    if (b2 < 0) {
      // Outside edge2
      R3Vector edge_vector = p0 - p2;
      RNScalar edge_length = edge_vector.Length();
      if (edge_length > 0) {
        edge_vector /= edge_length;
        R3Vector point_vector = plane_point - p2;
        RNScalar t = edge_vector.Dot(point_vector);
        if (t <= 0) {
          RNScalar distance_squared = DistanceSquared(query_position, p2);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v2;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p2;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else if (t >= edge_length) {
          RNScalar distance_squared = DistanceSquared(query_position, p0);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_VERTEX_TYPE;
            hit.vertex = v0;
            hit.edge = mesh->EdgeOnVertex(hit.vertex, face);
            hit.face = face;
            hit.point = p0;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
        else {
          R3Point point = p2 + t * edge_vector;
          RNScalar distance_squared = DistanceSquared(query_position, point);
          if ((distance_squared >= min_distance_squared) && (distance_squared < max_distance_squared)) {
            hit.type = R3_MESH_EDGE_TYPE;
            hit.vertex = NULL;
            hit.edge = mesh->EdgeOnFace(face, 2);
            hit.face = face;
            hit.point = point;
            hit.t = sqrt(distance_squared);
            max_distance_squared = distance_squared;
          }
        }
      }
    }
  }

  // Insert hit
  if (hit.type != R3_MESH_NULL_TYPE) {
    hits.Insert(new R3MeshIntersection(hit));
  }
}
Example #16
0
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Sphere& sphere)
{
    // Return whether halfspace contains sphere 
    RNLength d = R3SignedDistance(halfspace.Plane(), sphere.Center());
    return RNIsGreaterOrEqual(d, sphere.Radius());
}
Example #17
0
RNBoolean R3Contains(const R3Halfspace& halfspace, const R3Point& point)
{
    // Return whether halfspace contains point
    return (RNIsPositiveOrZero(R3SignedDistance(halfspace.Plane(), point)));
}
Example #18
0
RNBoolean R3Contains(const R3Plane& plane, const R3Point& point)
{
    // Return whether plane contains point
    return RNIsZero(R3SignedDistance(plane, point));
}