// Try to make up a 1st derivative if one is zero length
static void CookDerivativesHelper( ON_3dVector& du, ON_3dVector& dv, ON_3dVector& duu, ON_3dVector& duv, ON_3dVector& dvv)
{
  bool du_ok = du.LengthSquared() > ON_SQRT_EPSILON;
  bool dv_ok = dv.LengthSquared() > ON_SQRT_EPSILON;

  if( !du_ok || !dv_ok)
  {
    ON_3dVector normal;
    bool normal_ok = ON_EvNormal( 0, du, dv, duu, duv, dvv, normal ) ? true : false;
    if( normal_ok)
      normal_ok = normal.LengthSquared() > ON_SQRT_EPSILON;
   
    if( normal_ok)
    {
      if(( !du_ok) && ( dv_ok && normal_ok))
      {
        du = ON_CrossProduct( dv, normal);
        du_ok = du.Unitize();
        du *= (0.00390625*dv.Length());
      }
      if( du_ok && ( !dv_ok) && normal_ok)
      {
        dv = ON_CrossProduct( normal, du);
        dv_ok = dv.Unitize();
        dv *= (0.00390625*du.Length());
      }
    }
  }
}  
bool ON_PolyEdgeCurve::EvSrfTangent( 
        double t,
        bool bIsoDir,
        ON_3dPoint& srfpoint,
        ON_3dVector& srftangent,
        ON_3dVector& srfnormal
        ) const
{
  ON_3dPoint srfpt;
  ON_3dVector du, dv, duu, duv, dvv;
  bool rc = EvSrfDerivatives(t,srfpoint,du,dv,duu,duv,dvv);
  if (rc )
    rc = ON_EvNormal( 0, du, dv, duu, duv, dvv, srfnormal ) ? true : false;
  if (rc)
  {
    int segment_index = SegmentIndex(t);
    ON_PolyEdgeSegment* seg = SegmentCurve(segment_index);
    if ( seg )
    {
      if ( bIsoDir && seg->IsoType() == ON_Surface::not_iso )
        bIsoDir = false;
      
      ON_3dVector crvtangent = TangentAt(t);
      ON_3dVector binormal = ON_CrossProduct(crvtangent,srfnormal);
      binormal.Unitize();
      if ( seg->ReversedTrimDir() )
        binormal.Reverse();
      // at this point, binormal points "out" and is tangent
      // to the surface.
      if ( bIsoDir )
      {
        du.Unitize();
        dv.Unitize();
        double B_dot_du = binormal*du;
        double B_dot_dv = binormal*dv;
        if ( fabs(B_dot_dv) > fabs(B_dot_du) )
        {
          if (B_dot_dv < 0.0)
            dv.Reverse();
          srftangent = dv;
        }
        else
        {
          if (B_dot_du < 0.0)
            du.Reverse();
          srftangent = du;
        }
      }
      else
        srftangent = binormal;

      if ( seg && seg->m_face && seg->m_face->m_bRev )
        srfnormal.Reverse();
    }
    else
      rc = false;
  }
  return rc;
}
bool ON_PolyEdgeCurve::EvSrfNormalCurvature( 
          double t,
          ON_3dVector srftangent,
          ON_3dVector& srfnormalcurvature,
          ON_3dVector& srfnormal
          ) const
{
  ON_3dPoint srfpt;
  ON_3dVector du, dv, duu, duv, dvv;
  bool rc = EvSrfDerivatives(t,srfpt,du,dv,duu,duv,dvv);
  if (rc )
    rc = ON_EvNormal( 0, du, dv, duu, duv, dvv, srfnormal )?true:false;

  if( rc)
  {
    srfnormalcurvature = ON_NormalCurvature( du, dv, duu, duv, dvv, srfnormal, srftangent );
  }
  return rc;
}
Esempio n. 4
0
ON_BOOL32 ON_OffsetSurface::Evaluate(
    double s, double t,
    int der_count,
    int v_stride,
    double* v,
    int side,
    int* hint
) const
{
    int vv_stride = v_stride;
    double* vv = v;
    ON_3dVector srf_value[6];//, normal_value[3];
    if ( der_count < 2 )
    {
        vv = &srf_value[0].x;
        vv_stride = 3;
    }

    ON_BOOL32 rc = ON_SurfaceProxy::Evaluate(s,t,(der_count>2?der_count:2),vv_stride,vv,side,hint);

    if ( v != vv )
    {
        // save answer in v[] array
        v[0] = srf_value[0].x;
        v[1] = srf_value[0].y;
        v[2] = srf_value[0].z;
        if ( der_count > 0 )
        {
            v[v_stride]   = srf_value[1].x;
            v[v_stride+1] = srf_value[1].y;
            v[v_stride+2] = srf_value[1].z;
            v[2*v_stride]   = srf_value[2].x;
            v[2*v_stride+1] = srf_value[2].y;
            v[2*v_stride+2] = srf_value[2].z;
        }
    }
    else
    {
        srf_value[0] = v;
        srf_value[1] = v+v_stride;
        srf_value[2] = v+2*v_stride;
        srf_value[3] = v+3*v_stride;
        srf_value[4] = v+4*v_stride;
        srf_value[5] = v+5*v_stride;
    }

    if (rc)
    {
        double darray[21]; // 21 = ((5+1)*(5+2)/2) = enough room for der_count <= 5
        double* d = (der_count>5)
                    ? (double*)onmalloc(((der_count+1)*(der_count+2))/2*sizeof(d[0]))
                    : darray;
        rc = m_offset_function.EvaluateDistance(s,t,der_count,d);
        if (rc)
        {
            ON_3dVector N;
            ON_EvNormal(side,
                        srf_value[1], srf_value[2],
                        srf_value[3], srf_value[4], srf_value[5],
                        N);
            v[0] += d[0]*N.x;
            v[1] += d[0]*N.y;
            v[2] += d[0]*N.z;

            if ( der_count > 0 )
            {
                ON_3dVector Ns, Nt;
                ON_EvNormalPartials(srf_value[1], srf_value[2],
                                    srf_value[3], srf_value[4], srf_value[5],
                                    Ns, Nt);
                v[v_stride]   += d[0]*Ns.x + d[1]*N.x;
                v[v_stride+1] += d[0]*Ns.y + d[1]*N.y;
                v[v_stride+2] += d[0]*Ns.z + d[1]*N.z;

                v[2*v_stride]   += d[0]*Nt.x + d[2]*N.x;
                v[2*v_stride+1] += d[0]*Nt.y + d[2]*N.y;
                v[2*v_stride+2] += d[0]*Nt.z + d[2]*N.z;
            }
        }
        if ( d != darray )
            onfree(d);
    }

    return rc;
}
Esempio n. 5
0
ON_BOOL32
ON_Surface::EvNormal( // returns false if unable to evaluate
         double s, double t, // evaluation parameters (s,t)
         ON_3dPoint& point,  // returns value of surface
         ON_3dVector& ds, // first partial derivatives (Ds)
         ON_3dVector& dt, // (Dt)
         ON_3dVector& normal, // unit normal
         int side,       // optional - determines which side to evaluate from
                         //         0 = default
                         //         1 from NE quadrant
                         //         2 from NW quadrant
                         //         3 from SW quadrant
                         //         4 from SE quadrant
         int* hint       // optional - evaluation hint (int[2]) used to speed
                         //            repeated evaluations
         ) const
{
  // simple cross product normal - override to support singular surfaces
  ON_BOOL32 rc = Ev1Der( s, t, point, ds, dt, side, hint );
  if ( rc ) {
    const double len_ds = ds.Length();
    const double len_dt = dt.Length();

    // do not reduce the tolerance used here - there is a retry in the code
    // below.
    if ( len_ds >  ON_SQRT_EPSILON*len_dt && len_dt >  ON_SQRT_EPSILON*len_ds ) 
    {
      ON_3dVector a = ds/len_ds;
      ON_3dVector b = dt/len_dt;
      normal = ON_CrossProduct( a, b );
      rc = normal.Unitize();
    }
    else 
    {
      // see if we have a singular point 
      double v[6][3];
      int normal_side = side;
      ON_BOOL32 bOnSide = false;
      ON_Interval sdom = Domain(0);
      ON_Interval tdom = Domain(1);
		  if (s == sdom.Min()) {
			  normal_side = (normal_side >= 3) ? 4 : 1;
        bOnSide = true;
		  }
		  else if (s == sdom.Max()) {
			  normal_side = (normal_side >= 3) ? 3 : 2;
        bOnSide = true;
		  }
		  if (t == tdom.Min()) {
			  normal_side = (normal_side == 2 || normal_side == 3) ? 2 : 1;
        bOnSide = true;
		  }
		  else if (t == tdom.Max()) {
			  normal_side = (normal_side == 2 || normal_side == 3) ? 3 : 4;
        bOnSide = true;
		  }
      if ( !bOnSide )
      {
        // 2004 November 11 Dale Lear 
        //  Added a retry again with a more generous tolerance
        if ( len_ds >  ON_EPSILON*len_dt && len_dt >  ON_EPSILON*len_ds ) 
        {
          ON_3dVector a = ds/len_ds;
          ON_3dVector b = dt/len_dt;
          normal = ON_CrossProduct( a, b );
          rc = normal.Unitize();
        }
        else
        {
          rc = false;
        }
      }
      else {
        rc = Evaluate( s, t, 2, 3, &v[0][0], normal_side, hint );
        if ( rc ) {
	        rc = ON_EvNormal( normal_side, v[1], v[2], v[3], v[4], v[5], normal);
        }
      }
    }
  }
  if ( !rc ) {
    normal.Zero();
  }
  return rc;
}