Example #1
0
ON_BOOL32 ON_ArcCurve::SetEndPoint(ON_3dPoint end_point)
{
  if (IsCircle())
    return false;
  ON_BOOL32 rc = false;
  if ( m_dim == 3 || end_point.z == 0.0 )
  {
    ON_3dPoint P;
    ON_3dVector T;
    double t = Domain()[0];
    Ev1Der( t, P, T );
    ON_Arc a;
    rc = a.Create( P, T, end_point );
    if ( rc )
    {
      m_arc = a;
    }
    else {
      ON_3dPoint start_point = PointAt(Domain()[0]);
      if (end_point.DistanceTo(start_point) < ON_ZERO_TOLERANCE*m_arc.Radius()){
        //make arc into circle
        m_arc.plane.xaxis = start_point - m_arc.Center();
        m_arc.plane.xaxis.Unitize();
        m_arc.plane.yaxis = ON_CrossProduct(m_arc.Normal(), m_arc.plane.xaxis);
        m_arc.plane.yaxis.Unitize();
        m_arc.SetAngleRadians(2.0*ON_PI);
        rc = true;
      }
    }
  }
  return rc;  
}
Example #2
0
int ON_Intersect( 
                  const ON_Plane& plane, 
                  const ON_Arc& arc,
                  ON_3dPoint& point0,
                  ON_3dPoint& point1
                  )
{
	int rval = -1;
	ON_Line xline;
	double a,b;
	bool rc = ON_Intersect(plane, arc.Plane(), xline);
	if(rc)
	{
		rval = ON_Intersect(xline, arc, &a, point0, &b, point1); 
	}
	else
	{
		double d = plane.plane_equation.ValueAt( arc.StartPoint() );
		if(d<ON_ZERO_TOLERANCE)
			rval =3;
		else 
			rval = 0;
	}
	return rval;
}
Example #3
0
/* approximates a bezier curve with a set of circular arcs by dividing where
 * the bezier's deviation from its approximating biarc is at a maximum, then
 * recursively calling on the subsections until it is approximated to
 * tolerance by the biarc
 */
HIDDEN void
approx_bezier(const ON_BezierCurve& bezier, const ON_Arc& biarc, const struct bn_tol *tol, std::vector<ON_Arc>& approx)
{
    fastf_t t = 0.0, step = 0.0;
    fastf_t crv = 0.0, err = 0.0, max_t = 0.0, max_err = 0.0;
    ON_3dPoint test;
    ON_3dVector d1, d2;

    // walk the bezier curve at interval given by step
    for (t = 0; t <= 1.0; t += step) {
	bezier.Ev2Der(t, test, d1, d2);
	err = fabs((test - biarc.Center()).Length() - biarc.Radius());
	// find the maximum point of deviation
	if (err > max_err) {
	    max_t = t;
	    max_err = err;
	}
	crv = CURVATURE(d1, d2);
	// step size decreases as |crv| -> 1
	step = GETSTEPSIZE(1.0 - fabs(crv));
    }

    if (max_err + VDIVIDE_TOL < tol->dist) {
	// max deviation is less than the given tolerance, add the biarc approximation
	approx.push_back(biarc);
    } else {
	ON_BezierCurve head, tail;
	// split bezier at point of maximum deviation and recurse on the new subsections
	bezier.Split(max_t, head, tail);
	approx_bezier(head, make_biarc(head), tol, approx);
	approx_bezier(tail, make_biarc(tail), tol, approx);
    }
}
Example #4
0
/* approximates a bezier curve with a set of circular arcs.
 * returns approximation in carcs
 */
HIDDEN void
bezier_to_carcs(const ON_BezierCurve& bezier, const struct bn_tol *tol, std::vector<ON_Arc>& carcs)
{
    bool skip_while = true, curvature_changed = false;
    fastf_t inflection_pt, biarc_angle;
    ON_Arc biarc;
    ON_BezierCurve current, next;
    std::vector<ON_BezierCurve> rest;

    // find inflection point, if it exists
    if (bezier_inflection(bezier, inflection_pt)) {
	curvature_changed = true;
	bezier.Split(inflection_pt, current, next);
	rest.push_back(next);
    } else {
	current = bezier;
    }

    while (skip_while || !rest.empty()) {
    if (skip_while) skip_while = false;
    biarc = make_biarc(current);
    if ((biarc_angle = biarc.AngleRadians()) <= M_PI_2) {
	// approximate the current bezier segment and add its biarc
	// approximation to carcs
	approx_bezier(current, biarc, tol, carcs);
    } else if (biarc_angle <= M_PI) {
	// divide the current bezier segment in half
	current.Split(0.5, current, next);
	// approximate first bezier segment
	approx_bezier(current, biarc, tol, carcs);
	// approximate second bezier segment
	approx_bezier(next, biarc, tol, carcs);
    } else {
	fastf_t t = 1.0;
	ON_Arc test_biarc;
	ON_BezierCurve test_bezier;
	// divide the current bezier such that the first curve segment would
	// have an approximating biarc segment <=90 degrees
	do {
	    t *= 0.5;
	    current.Split(t, test_bezier, next);
	    test_biarc = make_biarc(test_bezier);
	} while(test_biarc.AngleRadians() > M_PI_2);

	approx_bezier(test_bezier, test_biarc, tol, carcs);
	current = next;
	skip_while = true;
	continue;
    }

    if (curvature_changed) {
	curvature_changed = false;
	current = rest.back();
	rest.pop_back();
	// continue even if we just popped the last element
	skip_while = true;
    }
    }
}
Example #5
0
ON_RevSurface* ON_Sphere::RevSurfaceForm( 
  bool bArcLengthParameterization,
  ON_RevSurface* srf 
  ) const
{
  if ( srf )
    srf->Destroy();
  ON_RevSurface* pRevSurface = NULL;
  if ( IsValid() )
  {
    ON_Arc arc;
    arc.plane.origin = plane.origin;
    arc.plane.xaxis = -plane.zaxis;
    arc.plane.yaxis =  plane.xaxis;
    arc.plane.zaxis = -plane.yaxis;
    arc.plane.UpdateEquation();
    arc.radius = radius;
    arc.SetAngleRadians(ON_PI);
    ON_ArcCurve* arc_curve = new ON_ArcCurve( arc, -0.5*ON_PI, 0.5*ON_PI );
    if ( srf )
      pRevSurface = srf;
    else
      pRevSurface = new ON_RevSurface();
    pRevSurface->m_angle.Set(0.0,2.0*ON_PI);
    pRevSurface->m_t = pRevSurface->m_angle;
    pRevSurface->m_curve = arc_curve;
    pRevSurface->m_axis.from = plane.origin;
    pRevSurface->m_axis.to = plane.origin + plane.zaxis;
    pRevSurface->m_bTransposed = false;
    pRevSurface->m_bbox.m_min = plane.origin;
    pRevSurface->m_bbox.m_min.x -= radius;
    pRevSurface->m_bbox.m_min.y -= radius;
    pRevSurface->m_bbox.m_min.z -= radius;
    pRevSurface->m_bbox.m_max = plane.origin;
    pRevSurface->m_bbox.m_max.x += radius;
    pRevSurface->m_bbox.m_max.y += radius;
    pRevSurface->m_bbox.m_max.z += radius;
    if ( bArcLengthParameterization )
    {
      double r = fabs(radius);
      if ( !(r > ON_SQRT_EPSILON) )
        r = 1.0;
      r *= ON_PI;
      pRevSurface->SetDomain(0,0.0,2.0*r);
      pRevSurface->SetDomain(1,-0.5*r,0.5*r);
    }
  }
  return pRevSurface;
}
Example #6
0
ON_RevSurface* ON_Sphere::RevSurfaceForm( ON_RevSurface* srf ) const
{
  if ( srf )
    srf->Destroy();
  ON_RevSurface* pRevSurface = NULL;
  if ( IsValid() )
  {
    ON_Arc arc;
    arc.plane.origin = plane.origin;
    arc.plane.xaxis = -plane.zaxis;
    arc.plane.yaxis =  plane.xaxis;
    arc.plane.zaxis = -plane.yaxis;
    arc.plane.UpdateEquation();
    arc.radius = radius;
    arc.SetAngleRadians(ON_PI);
    ON_ArcCurve* arc_curve = new ON_ArcCurve( arc, -0.5*ON_PI, 0.5*ON_PI );
    if ( srf )
      pRevSurface = srf;
    else
      pRevSurface = new ON_RevSurface();
    pRevSurface->m_angle.Set(0.0,2.0*ON_PI);
    pRevSurface->m_t = pRevSurface->m_angle;
    pRevSurface->m_curve = arc_curve;
    pRevSurface->m_axis.from = plane.origin;
    pRevSurface->m_axis.to = plane.origin + plane.zaxis;
    pRevSurface->m_bTransposed = false;
    pRevSurface->m_bbox.m_min = plane.origin;
    pRevSurface->m_bbox.m_min.x -= radius;
    pRevSurface->m_bbox.m_min.y -= radius;
    pRevSurface->m_bbox.m_min.z -= radius;
    pRevSurface->m_bbox.m_max = plane.origin;
    pRevSurface->m_bbox.m_max.x += radius;
    pRevSurface->m_bbox.m_max.y += radius;
    pRevSurface->m_bbox.m_max.z += radius;
  }
  return pRevSurface;
}
Example #7
0
int ON_Intersect(
      const ON_Line& line, 
      const ON_Arc& arc,
      double* line_t0,
      ON_3dPoint& arc_point0,
      double* line_t1,
      ON_3dPoint& arc_point1
      )
{
  ON_Circle c = arc;
  ON_3dPoint p[2];
  double t[2], a[2], s;
  ON_BOOL32 b[2] = {false,false};
  int i, xcnt = ON_Intersect( line, c, &t[0], p[0], &t[1], p[1] );
  if ( xcnt > 0 )
  {
    // make sure points are on the arc;
    ON_Interval arc_domain = arc.DomainRadians();
    for ( i = 0; i < xcnt; i++ )
    {
      b[i] = c.ClosestPointTo(p[i], &a[i]);
      if ( b[i] )
      {
        s = arc_domain.NormalizedParameterAt(a[i]);
        if ( s < 0.0 )
        {
          if ( s >= -ON_SQRT_EPSILON )
          {
            a[i] = arc_domain[0];
            p[i] = c.PointAt(a[i]);
            b[i] = line.ClosestPointTo( p[i], &t[i] );
          }
          else
            b[i] = false;
        }
        else if ( s > 1.0 )
        {
          if ( s <= 1.0+ON_SQRT_EPSILON )
          {
            a[i] = arc_domain[1];
            p[i] = c.PointAt(a[i]);
            b[i] = line.ClosestPointTo( p[i], &t[i] );
          }
          else
            b[i] = false;
        }
      }
    }
    if ( !b[0] && !b[1] )
      xcnt = 0;

    if ( xcnt == 2 )
    {
      if ( !b[1] )
        xcnt = 1;
      if ( !b[0] )
      {
        xcnt = 1;
        b[0] = b[1];
        t[0] = t[1];
        a[0] = a[1];
        p[0] = p[1];
        b[1] = 0;
      }
      if ( xcnt == 2 && t[0] == t[1] )
      {
        xcnt = 1;
        b[1] = 0;
        ON_3dPoint q = line.PointAt(t[0]);
        if ( p[0].DistanceTo(q) > p[1].DistanceTo(q) )
        {
          a[0] = a[1];
          t[0] = t[1];
          p[0] = p[1];
        }
      }
    }
    if  ( xcnt == 1 && !b[0] )
      xcnt = 0;
    if ( xcnt >= 1 )
    {
      if ( line_t0 )
        *line_t0 = t[0];
      arc_point0 = p[0];
    }
    if ( xcnt == 2 )
    {
      if ( line_t1 )
        *line_t1 = t[1];
      arc_point1 = p[1];
    }
  }
  return xcnt;
}
Example #8
0
static ON_BOOL32 NurbsCurveArc ( const ON_Arc& arc, int dim, ON_NurbsCurve& nurb )
{ 
  if ( !arc.IsValid() )
    return false;
  // makes a quadratic nurbs arc
  const ON_3dPoint center = arc.Center();
  double angle = arc.AngleRadians();
  ON_Interval dom = arc.DomainRadians();
  const double angle0 = dom[0];
  const double angle1 = dom[1];
  ON_3dPoint start_point = arc.StartPoint();
  //ON_3dPoint mid_point   = arc.PointAt(angle0 + 0.5*angle);
  ON_3dPoint end_point   = arc.IsCircle() ? start_point : arc.EndPoint();

  ON_4dPoint CV[9];
  double knot[10];

	double a, b, c, w, winv;
	double *cv;
	int    j, span_count, cv_count;

	a = (0.5 + ON_SQRT_EPSILON)*ON_PI;

	if (angle <= a)
		span_count = 1;
	else if (angle <= 2.0*a)
		span_count = 2;
	else if (angle <= 3.0*a)
		span_count = 4; // TODO - make a 3 span case
	else
		span_count = 4;

	cv_count = 2*span_count + 1;
	
	switch(span_count) {
	case 1:
    CV[0] = start_point;
    CV[1] = arc.PointAt(angle0 + 0.50*angle);
    CV[2] = end_point;
		break;
	case 2:
    CV[0] = start_point;
    CV[1] = arc.PointAt(angle0 + 0.25*angle);
    CV[2] = arc.PointAt(angle0 + 0.50*angle);
    CV[3] = arc.PointAt(angle0 + 0.75*angle);
    CV[4] = end_point;
		angle *= 0.5;
		break;
	default: // 4 spans
    CV[0] = start_point;
    CV[1] = arc.PointAt(angle0 + 0.125*angle);
    CV[2] = arc.PointAt(angle0 + 0.250*angle);
    CV[3] = arc.PointAt(angle0 + 0.375*angle);
    CV[4] = arc.PointAt(angle0 + 0.500*angle);
    CV[5] = arc.PointAt(angle0 + 0.625*angle);
    CV[6] = arc.PointAt(angle0 + 0.750*angle);
    CV[7] = arc.PointAt(angle0 + 0.875*angle);
    CV[8] = end_point;
		angle *= 0.25;
		break;
	}

	a = cos(0.5*angle);
	b = a - 1.0;
	//c = (radius > 0.0) ? radius*angle : angle;
  c = angle;

	span_count *= 2;
	knot[0] = knot[1] = angle0; //0.0;
	for (j = 1; j < span_count; j += 2) {
    CV[j].x += b * center.x;
    CV[j].y += b * center.y;
    CV[j].z += b * center.z;
    CV[j].w = a;
		CV[j+1].w = 1.0;
		knot[j+1] = knot[j+2] = knot[j-1] + c;
	}
  knot[cv_count-1] = knot[cv_count] = angle1;
  for ( j = 1; j < span_count; j += 2 ) {
    w = CV[j].w;
    winv = 1.0/w;
    a = CV[j].x*winv;
    b = ArcDeFuzz(a);
    if ( a != b ) {
      CV[j].x = b*w;
    }
    a = CV[j].y*winv;
    b = ArcDeFuzz(a);
    if ( a != b ) {
      CV[j].y = b*w;
    }
    a = CV[j].z*winv;
    b = ArcDeFuzz(a);
    if ( a != b ) {
      CV[j].z = b*w;
    }
  }

  nurb.m_dim = (dim==2) ? 2 : 3;
  nurb.m_is_rat = 1;
  nurb.m_order = 3;
  nurb.m_cv_count = cv_count;
  nurb.m_cv_stride = (dim==2 ? 3 : 4);
  nurb.ReserveCVCapacity( nurb.m_cv_stride*cv_count );
  nurb.ReserveKnotCapacity( cv_count+1 );
  for ( j = 0; j < cv_count; j++ ) {
    cv = nurb.CV(j);
    cv[0] = CV[j].x;
    cv[1] = CV[j].y;
    if ( dim == 2 ) {
      cv[2] = CV[j].w;
    }
    else {
      cv[2] = CV[j].z;
      cv[3] = CV[j].w;
    }
    nurb.m_knot[j] = knot[j];
  }
  nurb.m_knot[cv_count] = knot[cv_count];
  return true;
}