Exemplo n.º 1
0
int ON_CurveProxy::IsPolyline(
      ON_SimpleArray<ON_3dPoint>* pline_points,
      ON_SimpleArray<double>* pline_t
      ) const
{
  ON_SimpleArray<double> tmp_t;

  if ( pline_points )
    pline_points->SetCount(0);
  if ( pline_t )
    pline_t->SetCount(0);
  if ( !m_real_curve_domain.IsIncreasing() )
    return 0;
  if ( !m_real_curve )
    return 0;
  const ON_Interval cdom = m_real_curve->Domain();
  if ( !cdom.Includes(m_real_curve_domain) )
    return 0;

  // See if the "real" curve is a polyline
  int rc = 0;
  if ( m_real_curve_domain == cdom )
  {
    // proxy uses entire curve
    rc = m_real_curve->IsPolyline(pline_points,pline_t);
    if ( rc < 2 )
      rc = 0;

    if ( pline_points && pline_points->Count() != rc)
    {
      // The pline_points info is bogus, clear everything and
      // return 0.
      pline_points->SetCount(0);
      if ( pline_t )
        pline_t->SetCount(0);
      rc = 0;
    }

    if ( pline_t && pline_t->Count() != rc)
    {
      // The pline_t info is bogus, clear everything and
      // return 0.
      pline_t->SetCount(0);
      if ( pline_points )
        pline_points->SetCount(0);
      rc = 0;
    }

    if ( rc )
    {
      if ( m_bReversed )
      {
        if ( pline_points )
          pline_points->Reverse();
        if ( pline_t )
          pline_t->Reverse();
      }

      if ( pline_points && IsClosed() && pline_points->Count() > 3 )
      {
        // 27 February 2003 Dale Lear
        //     If proxy curve says it's closed, then
        //     make sure end point of returned polyline
        //     is exactly equal to start point.
        *pline_points->Last() = *pline_points->First();
      }
      
      if ( pline_t && (m_bReversed || m_real_curve_domain != m_this_domain) )
      {
        int i;
        for ( i = 0; i < rc; i++ )
        {
          (*pline_t)[i] = ThisCurveParameter( (*pline_t)[i] );
        }
      }
    }
  }
  else
  {
    // 12 December 2003 Dale Lear
    //   We have to extract a sub curve for the test, because
    //   the region in question may be a polyline and the unused
    //   portion may not be a polyline.  This tends to happen
    //   when the "real" curve is a polycurve that contains 
    //   a polyline and the polycurve has been parametrically
    //   trimmed during a brep operation (like a boolean).
    //
    // The ON_CurveProxy::DuplicateCurve() scope is critical
    // because there are situation where people derive a 
    // class from ON_CurveProxy, and override the virtual
    // DuplicateCurve().  In this situation I rely on getting
    // the result returned by ON_CurveProxy::DuplicateCurve().
    ON_Curve* temp_curve = ON_CurveProxy::DuplicateCurve();
    if ( temp_curve )
    {
      rc = temp_curve->IsPolyline(pline_points,pline_t);
      delete temp_curve;
    }
  }

  return rc;
}
Exemplo n.º 2
0
// override of virtual ON_Curve::Split
ON_BOOL32 ON_CurveProxy::Split(
    double t,
    ON_Curve*& left_side,
    ON_Curve*& right_side
  ) const
{
  ON_BOOL32 rc = false;
  if ( m_this_domain.IsIncreasing() && m_real_curve_domain.IsIncreasing() && m_this_domain.Includes(t,true) )
  {
    double crv_t = RealCurveParameter(t);
    if ( m_real_curve_domain.Includes(crv_t,true) )
    {
      ON_CurveProxy* left_proxy = 0;
      ON_CurveProxy* right_proxy = 0;
      if ( left_side )
      {
        left_proxy = ON_CurveProxy::Cast(left_side);
        if ( !left_proxy )
          return false;
      }
      if ( right_side )
      {
        right_proxy = ON_CurveProxy::Cast(right_side);
        if ( !right_proxy )
          return false;
        if ( right_side == left_side )
          return false;
      }

      bool bRev = m_bReversed;

      ON_Interval left_real_dom, right_real_dom;
      if ( bRev )
      {
        left_real_dom.Set(crv_t,m_real_curve_domain[1]);
        right_real_dom.Set(m_real_curve_domain[0],crv_t);
      }
      else
      {
        left_real_dom.Set(m_real_curve_domain[0],crv_t);
        right_real_dom.Set(crv_t,m_real_curve_domain[1]);
      }

      ON_Interval left_this_dom(m_this_domain[0],t);
      ON_Interval right_this_dom(t,m_this_domain[1]);

      if (    left_real_dom.IsIncreasing() 
           && right_real_dom.IsIncreasing()
           && left_this_dom.IsIncreasing()
           && right_this_dom.IsIncreasing()
           )
      {
        // note well that left_proxy or right_proxy might also be this
        const ON_Curve* real_crv = m_real_curve;
        if ( real_crv )
        {
          ON_Interval d = real_crv->Domain();
          if ( !d.Includes(left_real_dom) )
            return false;
          if ( !d.Includes(right_real_dom) )
            return false;
        }

        if ( !left_proxy )
          left_proxy = new ON_CurveProxy();
        if ( !right_proxy )
          right_proxy = new ON_CurveProxy();

        left_proxy->SetProxyCurve( real_crv, left_real_dom );
        right_proxy->SetProxyCurve( real_crv, right_real_dom );

        if ( bRev )
        {
          left_proxy->Reverse();
          right_proxy->Reverse();
        }

        left_proxy->SetDomain(left_this_dom[0],left_this_dom[1]);
        right_proxy->SetDomain(right_this_dom[0],right_this_dom[1]);

        if (!left_side) left_side = left_proxy;
        if (!right_side) right_side = right_proxy;

        rc = true;
      }
    }
  }
  return rc;
}
Exemplo n.º 3
0
bool ON_Arc::GetNurbFormParameterFromRadian(double RadianParameter, double* NurbParameter ) const
{
	if(!IsValid() || NurbParameter==NULL) 
		return false;

  ON_Interval ADomain = DomainRadians();

  double endtol = 10.0*ON_EPSILON*(fabs(ADomain[0]) + fabs(ADomain[1]));

  double del = RadianParameter - ADomain[0];
	if(del <= endtol && del >= -ON_SQRT_EPSILON)
  {
		*NurbParameter=ADomain[0];
		return true;
	} 
  else {
    del = ADomain[1] - RadianParameter;
    if(del <= endtol && del >= -ON_SQRT_EPSILON){
		  *NurbParameter=ADomain[1];
		  return true;
    }
	}

	if( !ADomain.Includes(RadianParameter ) )
		return false;


	ON_NurbsCurve crv;

	if( !GetNurbForm(crv))
		return false;

	//Isolate a bezier that contains the solution
	int cnt = crv.SpanCount();	
	int si =0;	//get span index
	int ki=0;		//knot index
	double ang = ADomain[0];
	ON_3dPoint cp;
	cp = crv.PointAt( crv.Knot(0) ) - Center();
	double x = ON_DotProduct(Plane().Xaxis(),cp);
	double y = ON_DotProduct(Plane().Yaxis(),cp);
	double at = atan2( y, x);	//todo make sure we dont go to far

	for( si=0, ki=0; si<cnt; si++, ki+=crv.KnotMultiplicity(ki) ){
		cp = crv.PointAt( crv.Knot(ki+2)) - Center();
		x = ON_DotProduct(Plane().Xaxis(),cp);
		y = ON_DotProduct(Plane().Yaxis(),cp);
		double at2 = atan2(y,x);
		if(at2>at)
			ang+=(at2-at);
		else
			ang += (2*ON_PI + at2 - at);
		at = at2;
		if( ang>RadianParameter)
			break;
	} 

	// Crash Protection trr#55679
	if( ki+2>= crv.KnotCount())
	{
		 *NurbParameter=ADomain[1];
		 return true;		
	}
	ON_Interval BezDomain(crv.Knot(ki), crv.Knot(ki+2));

	ON_BezierCurve bez;
	if(!crv.ConvertSpanToBezier(ki,bez))
		return false;

 	ON_Xform COC;
	COC.ChangeBasis( ON_Plane(),Plane());   

	
	bez.Transform(COC);	// change coordinates to circles local frame
	double a[3];							// Bez coefficients of a quadratic to solve
	for(int i=0; i<3; i++)
		a[i] = tan(RadianParameter)* bez.CV(i)[0] - bez.CV(i)[1];

	//Solve the Quadratic
	double descrim = (a[1]*a[1]) - a[0]*a[2];
	double squared = a[0]-2*a[1]+a[2];
	double tbez;
	if(fabs(squared)> ON_ZERO_TOLERANCE){
		ON_ASSERT(descrim>=0);
		descrim = sqrt(descrim);
		tbez = (a[0]-a[1] + descrim)/(a[0]-2*a[1]+a[2]);
		if( tbez<0 || tbez>1){
			double tbez2 = (a[0]-a[1]-descrim)/(a[0] - 2*a[1] + a[2]);
			if( fabs(tbez2 - .5)<fabs(tbez-.5) )
				tbez = tbez2;
		}

		ON_ASSERT(tbez>=-ON_ZERO_TOLERANCE && tbez<=1+ON_ZERO_TOLERANCE);
	}
	else{
		// Quadratic degenerates to linear
		tbez = 1.0;
		if(a[0]-a[2])
			tbez = a[0]/(a[0]-a[2]);
	}	
	if(tbez<0)
		tbez=0.0;
	else if(tbez>1.0)
		tbez=1.0;


		//Debug ONLY Code  - check the result
//		double aa = a[0]*(1-tbez)*(1-tbez)  + 2*a[1]*tbez*(1-tbez) + a[2]*tbez*tbez;
//		double tantheta= tan(RadianParameter);
//		ON_3dPoint bezp;
//		bez.Evaluate(tbez, 0, 3, bezp);
//		double yx = bezp.y/bezp.x;


	*NurbParameter = BezDomain.ParameterAt(tbez);
	return true;

}