예제 #1
0
bool ON_PlaneSurface::CreatePseudoInfinitePlane( 
        const ON_Plane& plane,
        int point_count,
        const ON_3dPoint* point_list,
        double padding
        )
{
  if ( !plane.IsValid() )
    return false;
  if ( point_count < 1 )
    return false;
  if ( 0 == point_list )
    return false;
  if ( !ON_IsValid(padding) || padding < 0.0 )
    return false;

  ON_Interval plane_domain[2];
  double s, t;
  s = ON_UNSET_VALUE;
  t = ON_UNSET_VALUE;
  if ( !plane.ClosestPointTo( point_list[0], &s, &t ) || !ON_IsValid(s) || !ON_IsValid(t) )
    return 0;
  plane_domain[0].m_t[1] = plane_domain[0].m_t[0] = s;
  plane_domain[1].m_t[1] = plane_domain[1].m_t[0] = t;
  
  for ( int i = 1; i < point_count; i++ )
  {
    s = ON_UNSET_VALUE;
    t = ON_UNSET_VALUE;
    if ( !plane.ClosestPointTo( point_list[i], &s, &t ) || !ON_IsValid(s) || !ON_IsValid(t) )
      return 0;
    if ( s < plane_domain[0].m_t[0] ) plane_domain[0].m_t[0] = s; else if ( s > plane_domain[0].m_t[1] ) plane_domain[0].m_t[1] = s;
    if ( t < plane_domain[1].m_t[0] ) plane_domain[1].m_t[0] = t; else if ( t > plane_domain[1].m_t[1] ) plane_domain[1].m_t[1] = t;
  }

  s = padding*plane_domain[0].Length() + padding;
  if ( !(s > 0.0) && !plane_domain[0].IsIncreasing() )
    s = 1.0;
  plane_domain[0].m_t[0] -= s;
  plane_domain[0].m_t[1] += s;

  t = padding*plane_domain[1].Length() + padding;
  if ( !(t > 0.0) && !plane_domain[1].IsIncreasing() )
    t = 1.0;
  plane_domain[1].m_t[0] -= t;
  plane_domain[1].m_t[1] += t;

  m_plane = plane;
  m_domain[0] = plane_domain[0];
  m_domain[1] = plane_domain[1];
  m_extents[0] = plane_domain[0];
  m_extents[1] = plane_domain[1];

  return IsValid()?true:false;
}
예제 #2
0
RH_C_FUNCTION ON_MassProperties* ON_Curve_AreaMassProperties(const ON_Curve* pCurve, double rel_tol, double abs_tol, double curve_planar_tol)
{
  ON_MassProperties* rc = NULL;
  if( pCurve )
  {
    ON_Plane plane;
    if( pCurve->IsPlanar(&plane, curve_planar_tol) && pCurve->IsClosed() )
    {
      ON_BoundingBox bbox = pCurve->BoundingBox();
      ON_3dPoint basepoint = bbox.Center();
      basepoint = plane.ClosestPointTo(basepoint);
      rc = new ON_MassProperties();
      bool getresult = pCurve->AreaMassProperties(basepoint, plane.Normal(), *rc, true, true, true, true, rel_tol, abs_tol);
      if( getresult )
      {
        rc->m_mass = fabs(rc->m_mass);
      }
      else
      {
        delete rc;
        rc = NULL;
      }
    }
  }
  return rc;
}
예제 #3
0
int ON_Intersect( // returns 0 = no intersections, 
                  // 1 = intersection = single point, 
                  // 2 = intersection = circle
                  // If 0 is returned, returned circle has radius=0
                  // and center = point on sphere closest to plane.
                  // If 1 is returned, intersection is a single
                  // point and returned circle has radius=0
                  // and center = intersection point on sphere.
                 const ON_Plane& plane, const ON_Sphere& sphere, ON_Circle& circle
                  )
{
  int rc = 0;
  const ON_3dPoint sphere_center = sphere.plane.origin;
  const double sphere_radius = fabs(sphere.radius);
  double tol = sphere_radius*ON_SQRT_EPSILON;
  if ( tol < ON_ZERO_TOLERANCE )
    tol = ON_ZERO_TOLERANCE;

  circle.plane = plane;

  ON_3dPoint plane_center = plane.ClosestPointTo(sphere_center);
  double d = plane_center.DistanceTo(sphere_center);

  if ( d >= sphere_radius-tol ) {
    rc = ( d <= sphere_radius-tol ) ? 1 : 0;
    circle.plane.origin = sphere.ClosestPointTo(plane_center);
    circle.plane.UpdateEquation();
    circle.radius = 0.0;
  }
  else {
    d /= sphere_radius;
    circle.radius = sphere_radius*sqrt(1.0 - d*d);
    if ( circle.radius <= ON_ZERO_TOLERANCE ) {
      circle.radius = 0.0;
      rc = 1;
    }
    else
      rc = 2;
  }
  //circle.UpdatePoints();    
  return rc;
}
예제 #4
0
int ON_ArePointsOnPlane( // returns 0=no, 1 = yes, 2 = pointset is (to tolerance) a single point on the line
        int dim,     // 2 or 3
        int is_rat,
        int count, 
        int stride, const double* point,
        const ON_BoundingBox& bbox, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point)
        const ON_Plane& plane,  // line to test
        double tolerance
        )
{
  double w;
  int i, j, k;

  if ( count < 1 )
    return 0;
  if ( !plane.IsValid() )
  {
    ON_ERROR("plane parameter is not valid");
    return 0;
  }
  if ( !bbox.IsValid() )
  {
    ON_ERROR("bbox parameter is not valid");
    return 0;
  }
  if ( !ON_IsValid(tolerance) || tolerance < 0.0 )
  {
    ON_ERROR("tolerance must be >= 0.0");
    return 0;
  }
  if ( dim < 2 || dim > 3 )
  {
    ON_ERROR("dim must be 2 or 3");
    return 0;
  }
  if ( stride < (is_rat?(dim+1):dim) )
  {
    ON_ERROR("stride parameter is too small");
    return 0;
  }
  if ( 0 == point )
  {
    ON_ERROR("point parameter is null");
    return 0;
  }

  int rc = 0;

  if ( tolerance == 0.0 ) {
    tolerance = bbox.Tolerance();
  }

  ON_3dPoint Q;

  // test bounding box to quickly detect the common coordinate axis cases
  rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1;
  for ( i = 0; rc && i < 2; i++ ) {
    Q.x = bbox[i].x;
    for ( j = 0; rc && j < 2; j++) {
      Q.y = bbox[j].y;
      for ( k = 0; rc && k < 2; k++) {
        Q.z = bbox[k].z;
        if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance )
          rc = 0;
      }
    }
  }

  if ( !rc ) {
    // test points one by one
    Q.Zero();
    rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1;
    if ( is_rat ) {
      for ( i = 0; i < count; i++ ) {
        w = point[dim];
        if ( w == 0.0 ) {
          ON_ERROR("rational point has zero weight");
          return 0;
        }
        ON_ArrayScale( dim, 1.0/w, point, &Q.x );
        if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) {
          rc = 0;
          break;
        }
        point += stride;
      }
    }
    else {
      for ( i = 0; i < count; i++ ) {
        memcpy( &Q.x, point, dim*sizeof(Q.x) );
        if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) {
          rc = 0;
          break;
        }
        point += stride;
      }
    }
  }

  return rc;
}
예제 #5
0
// Copied from opennurbs_intersect.cpp but with a bug fix.
// We can remove it once the bug is fixed in OpenNurbs and once 
// Grasshopper has dropped Rhino4 support.
int PS_Intersect(
        const ON_Plane& plane,
        const ON_Sphere& sphere, 
        ON_Circle& circle
        )
{
  // 16 April 2011 Dale Lear
  //   Prior to this date, this function did not return the correct answer.

  int rc = 0;
  const double sphere_radius = fabs(sphere.radius);
  double tol = sphere_radius*ON_SQRT_EPSILON;
  if ( !(tol >= ON_ZERO_TOLERANCE) )
    tol = ON_ZERO_TOLERANCE;
  const ON_3dPoint sphere_center = sphere.Center();
  ON_3dPoint circle_center = plane.ClosestPointTo(sphere_center);
  double d = circle_center.DistanceTo(sphere_center);

  circle.radius = 0.0;

  if ( ON_IsValid(sphere_radius) && ON_IsValid(d) && d <= sphere_radius + tol )
  {
    if ( sphere_radius > 0.0 )
    {
      d /= sphere_radius;
      d = 1.0 - d*d;
      // The d > 4.0*ON_EPSILON was picked by testing spheres with
      // radius = 1 and center = (0,0,0).  Do not make 4.0*ON_EPSILON 
      // any smaller and please discuss changes with Dale Lear.
      circle.radius = (d > 4.0*ON_EPSILON) ? sphere_radius*sqrt(d) : 0.0;
    }
    else
      circle.radius = 0.0;

    if ( circle.radius <= ON_ZERO_TOLERANCE )
    {
      // return a single point
      rc = 1;
      
      circle.radius = 0.0;

      //  When tolerance is in play, put the point on the sphere.
      //  If the caller prefers the plane, then they can adjust the
      //  returned answer to get the plane.
      ON_3dVector R = circle_center - sphere_center;
      double r0 = R.Length();
      if ( r0 > 0.0 )
      {
        R.Unitize();
        ON_3dPoint C1 = sphere_center + sphere_radius*R;
        double r1 = C1.DistanceTo(sphere_center);
        if ( fabs(sphere.radius-r1) < fabs(sphere.radius-r0) )
          circle_center = C1;
      }
    }
    else 
    {
      // return a circle
      rc = 2;
    }
  }

  // Update circle's plane here in case the input plane 
  // is the circle's plane member.
  circle.plane = plane;
  circle.plane.origin = circle_center;
  circle.plane.UpdateEquation();

  return rc;
}