Example #1
0
bool ON_SetKnotVectorDomain( int order, int cv_count, double* knot, double t0, double t1 )
{
  bool rc = false;
  if ( order < 2 || cv_count < order || 0 == knot || t0 >= t1 || !ON_IsValid(t0) || !ON_IsValid(t1) )
  {
    ON_ERROR("ON_SetKnotVectorDomain - invalid input");
  }
  else if (    knot[order-2] >= knot[cv_count-1] 
            || !ON_IsValid(knot[order-2]) 
            || !ON_IsValid(knot[cv_count-2]) )
  {
    ON_ERROR("ON_SetKnotVectorDomain - invalid input knot vector");
  }
  else
  {
    const ON_Interval oldd(knot[order-2],knot[cv_count-1]);
    const ON_Interval newd(t0,t1);
    if ( oldd != newd )
    {
      int i, knot_count = ON_KnotCount(order,cv_count);
      for ( i = 0; i < knot_count; i++ )
      {
        knot[i] = newd.ParameterAt(oldd.NormalizedParameterAt(knot[i]));
      }
    }
    rc = true;
  }
  return rc;
}
bool ON_Quaternion::IsNotZero() const
{
  return ( (0.0 != a || 0.0 != b || 0.0 != c || 0.0 != d) 
           && ON_IsValid(a)
           && ON_IsValid(b)
           && ON_IsValid(c) 
           && ON_IsValid(d)
         );
}
Example #3
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;
}
Example #4
0
int ON_Box::IsDegenerate( double tolerance ) const
{
  int rc = 0;
  // 0     box is not degenerate
  // 1     box is a rectangle (degenerate in one direction)
  // 2     box is a line (degenerate in two directions)
  // 3     box is a point (degenerate in three directions)
  // 4     box is not valid
  if ( !dx.IsIncreasing() || !dy.IsIncreasing() || !dz.IsIncreasing() )
  {
    rc = 4;
  }
  else
  {
    const ON_3dVector diag(dx.Length(),dy.Length(),dz.Length());
    if ( !ON_IsValid(tolerance) || tolerance < 0.0 )
    {
      // compute scale invarient tolerance
      tolerance = diag.MaximumCoordinate()*ON_SQRT_EPSILON;
    }
    if ( diag.x <= tolerance )
      rc++;
    if ( diag.y <= tolerance )
      rc++;
    if ( diag.z <= tolerance )
      rc++;
  }
  return rc;
}
Example #5
0
bool ON_Circle::IsValid() const
{
  bool rc = (    ON_IsValid(radius) 
              && radius > 0.0
              && plane.IsValid()
            );
  return rc;
}
Example #6
0
bool ON_Localizer::CreateSphereLocalizer( ON_3dPoint P, double r0, double r1 )
{
  Destroy();
  if ( P.IsValid()
       && ON_IsValid(r0)
       && ON_IsValid(r1)
       && r0 > 0.0
       && r1 > 0.0
       && r0 != r1 )
  {
    m_P = P;
    m_V.Zero();
    m_d.Set(r0,r1);
    m_type = sphere_type;
  }
  return (sphere_type == m_type);
}
Example #7
0
bool ON_Localizer::CreatePlaneLocalizer( ON_3dPoint P, ON_3dVector N, double h0, double h1 )
{
  Destroy();
  if ( P.IsValid()
       && N.IsValid()
       && N.Length() > 0.0
       && ON_IsValid(h0)
       && ON_IsValid(h1)
       && h0 != h1 )
  {
    m_V = N;
    m_V.Unitize();
    m_P.Set( -(m_V.x*P.x + m_V.y*P.y + m_V.z*P.z), 0.0, 0.0 );
    m_d.Set(h0,h1);
    m_type = plane_type;
  }
  return (plane_type == m_type);
}
Example #8
0
void ON_Light::SetSpotExponent( double e )
{
  // cos(h)^e = 0.5
  if ( e < 0.0 || !ON_IsValid(e) )
    m_spot_exponent = 0.0;
  else
    m_spot_exponent = e;
  m_hotspot = ON_UNSET_VALUE; // indicates hotspot should be computed from m_spot_exponent
}
Example #9
0
void ON_Light::SetHotSpot( double h )
{
  if ( h == ON_UNSET_VALUE || !ON_IsValid(h) )
    m_hotspot = ON_UNSET_VALUE;
  else if ( h <= 0.0 ) 
    m_hotspot = 0.0;
  else if ( h >= 1.0 )
    m_hotspot = 1.0;
  else
    m_hotspot = h;
}
Example #10
0
bool ON_Localizer::CreateCylinderLocalizer( ON_3dPoint P, ON_3dVector V, double r0, double r1 )
{
  Destroy();
  if (    P.IsValid() 
       && V.IsValid() 
       && V.Length() > 0.0 
       && ON_IsValid(r0) 
       && ON_IsValid(r1) 
       && r0 > 0.0
       && r1 > 0.0
       && r0 != r1 )
  {
    m_P = P;
    m_V = V;
    m_V.Unitize();
    m_d.Set(r0,r1);
    m_type = cylinder_type;
  }
  return (cylinder_type == m_type);
}
Example #11
0
double ON_X_EVENT::IntersectionTolerance( double intersection_tolerance )
{
  if ( intersection_tolerance <= 0.0 || !ON_IsValid(intersection_tolerance) )
  {
    intersection_tolerance = 0.001;
  }
  else if ( intersection_tolerance < 1.0e-6 )
  {
    intersection_tolerance = 1.0e-6;
  }
  return intersection_tolerance;
}
Example #12
0
double ON_X_EVENT::OverlapTolerance( double intersection_tolerance, double overlap_tolerance )
{
  if ( overlap_tolerance <= 0.0 || !ON_IsValid(overlap_tolerance) )
  {
    overlap_tolerance = 2.0*IntersectionTolerance(intersection_tolerance);
  }
  else if ( overlap_tolerance < 1.0e-6 )
  {
    overlap_tolerance = 1.0e-6;
  }
  return overlap_tolerance;
}
Example #13
0
bool ON_Light::GetSpotLightRadii( double* inner_radius, double* outer_radius ) const
{
  bool rc = IsSpotLight()?true:false;
  if (rc)
  {
    double angle = SpotAngleRadians();
    if ( !ON_IsValid(angle) || angle <= 0.0 || angle >= 0.5*ON_PI )
      angle = 0.25*ON_PI;
    double spot = HotSpot();
    if ( !ON_IsValid(spot) || spot < 0.0 || spot > 1.0 )
      spot = 0.5;
    double cone_height = Direction().Length();
    if ( !ON_IsValid(cone_height) || cone_height <= 0.0 )
      cone_height = 1.0;

    if ( outer_radius )
      *outer_radius = tan( angle) * cone_height;
    if ( inner_radius )
      *inner_radius = tan( angle * spot) * cone_height;
  }
  return rc;
}
Example #14
0
static void DumpDistanceABHelper( ON_TextLog& text_log, ON_3dPoint A, ON_3dPoint B )
{
  const double tinyd = 1.0e-14;
  double d = A.DistanceTo(B);
  text_log.Print("distance A to B");
  if ( !ON_IsValid(d) || d >= 1.0e-14 || d <= 0.0 )
  {
    text_log.Print(" = ");
  }
  else
  {
    // This prevents diff from compaining about tiny changes.
    text_log.Print(" < ");
    d = tinyd;
  }
  text_log.Print(d);
  text_log.Print("\n");
}
CRhinoCommand::result CCommandSampleDimStyleTextHeight::RunCommand( const CRhinoCommandContext& context )
{
  // Get the current dimstyle
  const CRhinoDimStyle& dimstyle = context.m_doc.m_dimstyle_table.CurrentDimStyle();

  ON_wString prompt;
  prompt.Format( L"New text height for \"%s\" dimension style", dimstyle.Name() );

  // Prompt for a new text height value
  CRhinoGetNumber gn;
  gn.SetCommandPrompt( prompt );
  gn.SetDefaultNumber( dimstyle.TextHeight() );
  gn.SetLowerLimit( 0.0, TRUE );
  gn.AcceptNothing();
  gn.GetNumber();
  if( gn.CommandResult() != CRhinoCommand::success )
    return gn.CommandResult();

  // New text height value
  double height = gn.Number();

  // Validate new value
  if( height != dimstyle.TextHeight() && ON_IsValid(height) && height > ON_SQRT_EPSILON )
  {
    int style_index = dimstyle.Index();

    // Copy everything from the dimension's dimstyle
    ON_DimStyle modified_dimstyle( context.m_doc.m_dimstyle_table[style_index] );

    // Modify the text height
    modified_dimstyle.SetTextHeight( height );

    // Modify the dimension style
    if( context.m_doc.m_dimstyle_table.ModifyDimStyle(modified_dimstyle, style_index) )
      context.m_doc.Redraw();
  }

  return CRhinoCommand::success;
}
Example #16
0
double ON_Light::HotSpot() const
{
  double h = m_hotspot;
  if ( h < 0.0 || h > 1.0 ) {
    // spotlight is using spot exponent interface
    if ( m_spot_exponent >= 65536.0 )
      h = 0.0;
    else if ( m_spot_exponent <= 0.0 || m_spot_angle <= 0.0 || m_spot_angle > 90.0 )
      h = 1.0;
    else {
      // compute HotSpot() from cos(h*angle)^e = hotspot_min
      double x, a, cos_ha;
      x = log_hotspot_min/m_spot_exponent; // note that x < 0.0
      if ( x < -690.0 ) {
        // prevent underflow.  cos_ha is close to zero so
        h = 1.0;
      }
      else 
      {
        cos_ha = exp(x);
        if (!ON_IsValid(cos_ha))  cos_ha =  0.0;
        else if ( cos_ha >  1.0 ) cos_ha =  1.0;
        else if ( cos_ha < -1.0 ) cos_ha = -1.0;
        a = SpotAngleRadians();
        h = acos(cos_ha)/a;
        if ( h < 0.0 )
          h = 0.0;
        else if ( h > 1.0 ) {
          // happens for smaller e
          h = 1.0;
        }
      }
    }
  }
  return h;
}
Example #17
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;
}
Example #18
0
ON_BOOL32 ON_Ellipse::IsCircle() const
{
  double r0 = radius[0];
  return ( ON_IsValid(r0) && fabs(r0-radius[1]) <= fabs(r0)*ON_ZERO_TOLERANCE && IsValid() ) ? true : false;
}
int ON_FindLocalMinimum(
                int (*f)(void*,double,double*,double*), void* farg,
                double ax, double bx, double cx,
                double rel_stepsize_tol, double abs_stepsize_tol, int max_it, 
                double *t_addr
                )
/* Use Brent's algorithm (with derivative) to Find a (local) minimum of a function
 *
 * INPUT:
 *   ax, bx, cx a bracketed minimum satisfying conditions 1 and 2.
 *      1) either ax < bx < cx or cx < bx < ax.
 *      2) f(bx) < f(ax) and f(bx) < f(ax).
 *   farg
 *      pointer passed to function f()
 *   f
 *      evaluation function with prototype
 *              int f(void* farg,double t,double* ft,double* dft)
 *      f(farg,t,&ft,&dft) should compute ft = value of function at t
 *      and dft = value of derivative at t.
 *      -1: failure
 *       0: success
 *       1: |f(x)| is small enough - TL_NRdbrent() will return *t_addr = x
 *          and the return code 1.
 *   rel_stepsize_tol, abs_stepsize_tol  (0 < rel_stepsize_tol < 1 and 0 < abs_stepsize_tol)
 *      rel_stepsize_tol is a fractional tolerance and abs_stepsize_tol is an absolute tolerance
 *      that determine the minimum step size for a given iteration.
 *        minimum delta t = rel_stepsize_tol*|t| + abs_stepsize_tol.
 *      When in doubt, use 
 *         rel_stepsize_tol = ON_EPSILON 
 *         abs_stepsize_tol = 1/2*(desired absolute precision for *t_addr).
 *   max_it ( >= 2)
 *      maximum number of iterations to permit (when in doubt use 100)
 *      Closest Point to bezier minimizations typically take < 30
 *      iterations.
 *
 * OUTPUT:
 *   *t_addr abcissa of a local minimum between ax and cx.
 *       0: failure
 *       1: success
 *       2: After max_iteration_cnt iterations the tolerance restrictions
 *          where not satisfied.  Try increasing max_it, rel_stepsize_tol and/or abs_stepsize_tol
 *          or use the value of (*t_addr) with extreme caution.
 */
{
  // See Numerical Recipes in C's dbrent() for a description of the basic algorithm
  int rc,ok1,ok2;
  double a,b,d,d1,d2,du,dv,dw,dx,e,fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm;

  d=e=0.0;

  if ( 0 == t_addr )
  {
    ON_ERROR("t_addr is NULL");
    return 0;
  }

  *t_addr = bx;

  if ( max_it < 2 )
  {
    ON_ERROR("max_it must be >= 2");
    return 0;
  }
  if ( !ON_IsValid(rel_stepsize_tol) || rel_stepsize_tol <= 0.0 || rel_stepsize_tol >= 1.0 )
  {
    ON_ERROR("rel_stepsize_tol must be strictly between 0.0 and 1.0");
    return 0;
  }
  if ( !ON_IsValid(abs_stepsize_tol) || abs_stepsize_tol <= 0.0 )
  {
    ON_ERROR("abs_stepsize_tol must be > 0");
    return 0;
  }

  a=(ax < cx ? ax : cx);
  b=(ax > cx ? ax : cx);
  x=w=v=bx;
  rc = f(farg,x,&fx,&dx);
  if (rc) {
     // f() returned nonzero return code which means we need to bailout
    if ( rc < 0 ) {
      ON_ERROR("ON_FindLocalMinimum() f() failed to evaluate.");
    }
    *t_addr = x;
    return rc>0 ? 1 : 0; // return 1 means f() said result is good enough, return = 0 means f() failed
  }
  fw=fv=fx;
  dw=dv=dx;
  while(max_it--) {
    xm=0.5*(a+b);
    tol1=rel_stepsize_tol*fabs(x)+abs_stepsize_tol;
    tol2=2.0*tol1;
    if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
      // further adjustments to x are smaller than stepsize tolerance
      *t_addr=x;
      return 1;
    }
    if (fabs(e) > tol1) {
      d1=2.0*(b-a);
      d2=d1;
      if (dw != dx) d1=(w-x)*dx/(dx-dw);
      if (dv != dx) d2=(v-x)*dx/(dx-dv);
      u1=x+d1;
      u2=x+d2;
      ok1 = (a-u1)*(u1-b) > 0.0 && dx*d1 <= 0.0;
      ok2 = (a-u2)*(u2-b) > 0.0 && dx*d2 <= 0.0;
      olde=e;
      e=d;
      if (ok1 || ok2) {
        if (ok1 && ok2)
          d=(fabs(d1) < fabs(d2) ? d1 : d2);
        else if (ok1)
          d=d1;
        else
          d=d2;
        if (fabs(d) <= fabs(0.5*olde)) {
          u=x+d;
          if (u-a < tol2 || b-u < tol2)
            {d = (xm >= x) ? tol1 : -tol1;}
        } else {
          d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
        }
      } else {
        d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
      }
    } else {
      d=0.5*(e=(dx >= 0.0 ? a-x : b-x));
    }
    if (fabs(d) >= tol1) {
      u=x+d;
      rc = f(farg,u,&fu,&du);
    }
    else {
      u = (d >= 0.0) ? x+tol1 : x-tol1;
      rc = f(farg,u,&fu,&du);
      if (rc >= 0 && fu > fx) {
        // tweaking x any more increases function value - x is a numerical minimum
        *t_addr=x;
        return 1;
      }
    }
    if (rc) {
      // f() returned nonzero return code which means we need to bailout
      if ( rc < 0 ) {
        ON_ERROR("ON_FindLocalMinimum() f() failed to evaluate.");
      }
      else {
        *t_addr = (fu < fx) ? u : x;
      }
      return rc>0 ? 1 : 0;
    }
    if (fu <= fx) {
      if (u >= x) a=x; else b=x;
      v=w;fv=fw;dv=dw;
      w=x;fw=fx;dw=dx;
      x=u;fx=fu;dx=du;
    } else {
      if (u < x) a=u; else b=u;
      if (fu <= fw || w == x) {
        v=w;fv=fw;dv=dw;
        w=u;fw=fu;dw=du;
      } else if (fu < fv || v == x || v == w) {
        v=u;fv=fu;dv=du;
      }
    }
  }
  *t_addr = x; // best known answer
  ON_ERROR("ON_FindLocalMinimum() failed to converge");
  return 2; // 2 means we failed to converge
}
bool ON_PolyEdgeCurve::EvSrfDerivatives(
        double t,
        ON_3dPoint& srfpoint,
        ON_3dVector& du,
        ON_3dVector& dv,
        ON_3dVector& duu,
        ON_3dVector& duv,
        ON_3dVector& dvv
        ) const
{
  bool rc = false;
  int segment_index = SegmentIndex(t);
  ON_PolyEdgeSegment* seg = SegmentCurve( segment_index );
  if ( seg )
  {
    ON_Interval pdom = SegmentDomain(segment_index);
    ON_Interval sdom = seg->Domain();
    double s = t;
    if ( sdom != pdom )
    {
      double x = pdom.NormalizedParameterAt(t);
      s = sdom.ParameterAt(x);
    }
    // s is the segment parameter at the polyedge parameter t
    // Get the corresponding surfaces parameters
    ON_2dPoint srf_uv = seg->SurfaceParameter(s);
    if ( ON_IsValid(srf_uv.x) )
    {
      if ( srf_uv.x == seg->m_evsrf_uv[0] && srf_uv.y == seg->m_evsrf_uv[1] )
      {
        rc = true;
        srfpoint = seg->m_evsrf_pt;
        du = seg->m_evsrf_du;
        dv = seg->m_evsrf_dv;
        duu = seg->m_evsrf_duu;
        duv = seg->m_evsrf_duv;
        dvv = seg->m_evsrf_dvv;
      }
      else if ( seg->m_surface )
      {
        rc = seg->m_surface->Ev2Der( 
                  srf_uv.x, srf_uv.y, 
                  srfpoint, 
                  du, dv, 
                  duu, duv, dvv, 
                  0, seg->m_evsrf_hint 
                  ) ? true : false;
        if ( rc )
        {
          CookDerivativesHelper( du, dv, duu, duv, dvv);
          seg->m_evsrf_uv[0] = srf_uv.x;
          seg->m_evsrf_uv[1] = srf_uv.y;
          seg->m_evsrf_pt = srfpoint;
          seg->m_evsrf_du = du;
          seg->m_evsrf_dv = dv;
          seg->m_evsrf_duu = duu;
          seg->m_evsrf_duv = duv;
          seg->m_evsrf_dvv = dvv;
        }
      }
    }
  }
  return rc;
}
Example #21
0
bool ON_OffsetSurfaceFunction::SetOffsetPoint(
    double s,
    double t,
    double distance,
    double radius
)
{
    bool rc = false;
    if ( ON_IsValid(s) && ON_IsValid(t) && ON_IsValid(distance) && ON_IsValid(radius) )
    {
        double u = m_domain[0].NormalizedParameterAt(s);

        // 14 Jan 2008, Mikko, TRR 29861:
        // Changing the clamping to happen when the
        // point is outside or nearly outside the domain.
        const double dTol = ON_SQRT_EPSILON; // tiny border around untrimmed edges

        if ( u < dTol)
        {
            s = m_domain[0][0];
            u = 0.0;
        }
        if ( u > 1.0-dTol)
        {
            s = m_domain[0][1];
            u = 1.0;
        }

        double v = m_domain[1].NormalizedParameterAt(t);
        if ( v < dTol)
        {
            t = m_domain[1][0];
            v = 0.0;
        }
        if ( v > 1.0-dTol)
        {
            t = m_domain[1][1];
            v = 1.0;
        }

        if ( u >= 0.0 && u <= 1.0 && v >= 0.0 && v <= 1.0 )
        {
            ON_OffsetSurfaceValue offset_value;
            offset_value.m_s = s;
            offset_value.m_t = t;
            offset_value.m_distance = distance;
            offset_value.m_radius = (radius > 0.0) ? radius : 0.0;
            offset_value.m_index = (int)((u + v*4096.0)*4096.0);
            int i;
            for ( i = 0; i < m_offset_value.Count(); i++ )
            {
                if ( m_offset_value[i].m_index == offset_value.m_index )
                {
                    m_offset_value[i] = offset_value;
                    break;
                }
            }
            if (i == m_offset_value.Count())
            {
                m_offset_value.Append(offset_value);
                m_bumps.SetCount(0);
                m_bValid = false;
            }
            rc = true;
        }
    }
    return rc;
}
Example #22
0
int ON_RowReduce( int row_count, 
                  int col_count,
                  double zero_pivot,
                  double** A, 
                  double** B, 
                  double pivots[2] 
                 )
{
  // returned A is identity, B = inverse of input A
  const int M = row_count;
  const int N = col_count;
  const size_t sizeof_row = N*sizeof(A[0][0]);
  int i, j, ii;
  double a, p, p0, p1;
  const double* ptr0;
  double* ptr1;

  if ( pivots )
  {
    pivots[0] = 0.0;
    pivots[1] = 0.0;
  }

  if ( zero_pivot <= 0.0 || !ON_IsValid(zero_pivot) )
    zero_pivot = 0.0;


  for ( i = 0; i < M; i++ )
  {
    memset(B[i],0,sizeof_row);
    if ( i < N )
      B[i][i] = 1.0;
  }

  p0 = p1 = A[0][0];

  for ( i = 0; i < M; i++ )
  {
    p = fabs(a = A[i][i]);
    if ( p < p0 ) p0 = p; else if (p > p1) p1 = p;
    if ( 1.0 != a )
    {
      if ( p <= zero_pivot || !ON_IsValid(a) )
      {
        break;
      }
      a = 1.0/a;

      //A[i][i] = 1.0; // no need to do this

      // The "ptr" voodoo is faster but does the same thing as
      //
      //for ( j = i+1; j < N; j++ )
      //  A[i][j] *= a;
      //      
      j = i+1;
      ptr1 = A[i] + j;
      j = N - j;
      while(j--) *ptr1++ *= a;
      
      // The "ptr" voodoo is faster but does the same thing as
      //
      //for ( j = 0; j <= i; j++ )
      //  B[i][j] *= a;
      //            
      ptr1 = B[i];
      j = i+1;
      while(j--) *ptr1++ *= a;
    }

    for ( ii = i+1; ii < M; ii++ )
    {
      a = A[ii][i];
      if ( 0.0 == a )
        continue;
      a = -a;
      
      //A[ii][i] = 0.0;  // no need to do this

      // The "ptr" voodoo is faster but does the same thing as
      //
      //for( j = i+1; j < N; j++ )
      //  A[ii][j] += a*A[i][j];
      //
      j = i+1;
      ptr0 = A[i] + j;
      ptr1 = A[ii] + j;
      j = N - j;
      while(j--) *ptr1++ += a* *ptr0++;

      for( j = 0; j <= i; j++ )
        B[ii][j] += a*B[i][j];
    }
  }

  if ( pivots )
  {
    pivots[0] = p0;
    pivots[1] = p1;
  }

  if ( i < M )
  {
    return i;
  }


  // A is now upper triangular with all 1s on diagonal 
  //   (That is, if the lines that say "no need to do this" are used.)
  // B is lower triangular with a nonzero diagonal
  for ( i = M-1; i >= 0; i-- )
  {
    for ( ii = i-1; ii >= 0; ii-- )
    {
      a = A[ii][i];
      if ( 0.0 == a )
        continue;
      a = -a;
      //A[ii][i] = 0.0; // no need to do this

      // The "ptr" voodoo is faster but does the same thing as
      //
      //for( j = 0; j < N; j++ )
      //  B[ii][j] += a*B[i][j];
      //
      ptr0 = B[i];
      ptr1 = B[ii];
      j = N;
      while(j--) *ptr1++ += a* *ptr0++;
    }
  }

  // At this point, A is trash.
  // If the input A was really nice (positive definite....)
  // the B = inverse of the input A.  If A was not nice,
  // B is also trash.
  return M;
}
void ON_Sum::Plus( double x, double dx )
{
  Plus(x);
  if ( ON_IsValid(dx) )
    m_sum_err += fabs(dx);
}
Example #24
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;
}
Example #25
0
bool ON_IsValidKnotVector( int order, int cv_count, const double* knot, ON_TextLog* text_logx )
{
  // If low bit of text_log pointer is 1, then ON_Error is not called when the
  // knot vector is invalid.
  const ON__INT_PTR lowbit = 1;
  const ON__INT_PTR hightbits = ~lowbit;
  bool bSilentError = ( 0 != (lowbit & ((ON__INT_PTR)text_logx)) );
  ON_TextLog* text_log = (ON_TextLog*)(((ON__INT_PTR)text_logx) & hightbits);

  const double *k0, *k1;
  int i;
  if ( order < 2 )
  {
    if ( text_log )
    {
      text_log->Print("Knot vector order = %d (should be >= 2 )\n",order);
    }
    return ON_KnotVectorIsNotValid(bSilentError);
  }
  if ( cv_count < order )
  {
    if ( text_log )
    {
      text_log->Print("Knot vector cv_count = %d (should be >= order=%d )\n",cv_count,order);
    }
    return ON_KnotVectorIsNotValid(bSilentError);
  }
  if ( knot == NULL )
  {
    if ( text_log )
    {
      text_log->Print("Knot vector knot array = NULL.\n");
    }
    return ON_KnotVectorIsNotValid(bSilentError);
  }

  for ( i = 0; i < cv_count+order-2; i++ )
  {
    if ( !ON_IsValid(knot[i]) )
    {
      if ( text_log )
      {
        text_log->Print("Knot vector knot[%d]=%g is not valid.\n",i,knot[i]);
      }
      return ON_KnotVectorIsNotValid(bSilentError);
    }
  }

  if ( !(knot[order-2] < knot[order-1]) )
  {
    if ( text_log )
    {
      text_log->Print("Knot vector order=%d and knot[%d]=%g >= knot[%d]=%g (should have knot[order-2] < knot[order-1]).\n",
                       order,order-2,knot[order-2],order-1,knot[order-1]);
    }
    return ON_KnotVectorIsNotValid(bSilentError);
  }
  if ( !(knot[cv_count-2] < knot[cv_count-1]) )
  {
    if ( text_log )
    {
      text_log->Print("Knot vector cv_count=%d and knot[%d]=%g >= knot[%d]=%g (should have knot[cv_count-2] < knot[cv_count-1]).\n",
                       cv_count,cv_count-2,knot[cv_count-2],cv_count-1,knot[cv_count-1]);
    }
    return ON_KnotVectorIsNotValid(bSilentError);
  }

  // entire array must be monotone increasing
  k0 = knot;
  k1 = knot+1;
  i = order + cv_count - 3;
  while (i--) {
    if ( !(*k1 >= *k0) )
    {
      if ( text_log )
      {
        text_log->Print("Knot vector must be increasing but knot[%d]=%g > knot[%d]=%g\n",
                         order+cv_count-4-i, *k0, order+cv_count-3-i, *k1 );
      }
      return ON_KnotVectorIsNotValid(bSilentError);
    }
    k0++;
    k1++;
  }

  // must have knot[i+order-1] > knot[i]
  k0 = knot;
  k1 = knot + order - 1;
  i = cv_count-1;
  while(i--) {
    if ( !(*k1 > *k0) )
    {
      if ( text_log )
      {
        text_log->Print("Knot vector order = %d but knot[%d]=%g >= knot[%d]=%g\n",
                         order, cv_count-2-i, *k0, cv_count-1-i, *k1 );
      }
      return ON_KnotVectorIsNotValid(bSilentError);
    }
    k0++;
    k1++;
  }

  return true;
}
Example #26
0
void ON_Layer::SetPlotWeight(double plot_weight_mm)
{
  m_plot_weight_mm = (ON_IsValid(plot_weight_mm))
                   ? plot_weight_mm
                   : 0.0;
}
Example #27
0
int ON_Brep::SplitEdgeAtParameters(
  int edge_index,
  int edge_t_count,
  const double* edge_t
  )
{
  // Default kink_tol_radians MUST BE ON_PI/180.0.
  //
  // The default kink tol must be kept in sync with the default for 
  // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace().
  // See comments in TL_Brep::SplitKinkyFace() for more details.

  if (0 == edge_t_count)
    return 0;
  if (0 == edge_t)
    return 0;
  if (edge_index < 0 || edge_index >= m_E.Count()) 
    return 0;
  ON_BrepEdge& E = m_E[edge_index];
  if (E.m_c3i < 0) 
    return 0;
  ON_Curve* curve = m_C3[E.m_c3i];
  if (!curve) 
    return 0;

  ON_Interval Edomain;
  if ( !E.GetDomain(&Edomain.m_t[0],&Edomain.m_t[1]) )
    return 0;
  if ( !Edomain.IsIncreasing() )
    return 0;

  // get a list of unique and valid splitting parameters
  ON_SimpleArray<double> split_t(edge_t_count);
  {
    for (int i = 0; i < edge_t_count; i++)
    {
      double e = edge_t[i];
      if ( !ON_IsValid(e) )
      {
        ON_ERROR("Invalid edge_t[] value");
        continue;
      }
      if ( e <= Edomain.m_t[0] )
      {
        ON_ERROR("edge_t[] <= start of edge domain");
        continue;
      }
      if ( e >= Edomain.m_t[1] )
      {
        ON_ERROR("edge_t[] >= end of edge domain");
        continue;
      }
      split_t.Append(e);
    }
    if ( split_t.Count() > 1 )
    {
      // sort split_t[] and remove duplicates
      ON_SortDoubleArray( ON::heap_sort, split_t.Array(), split_t.Count() );
      int count = 1;
      for ( int i = 1; i < split_t.Count(); i++ )
      {
        if ( split_t[i] > split_t[count-1] )
        {
          if ( i > count )
            split_t[count] = split_t[i];
          count++;
        }
      }
      split_t.SetCount(count);
    }
  }

  if (split_t.Count() <= 0) 
    return 0;

  // Reverse split_t[] so the starting segment of the original
  // edge m_E[edge_index] is the one at m_E[edge_index].
  split_t.Reverse();

  ON_Curve* new_curve = TuneupSplitteeHelper(m_E[edge_index].ProxyCurve());
  if ( 0 != new_curve )
  {
    m_E[edge_index].m_c3i = AddEdgeCurve(new_curve);
    m_E[edge_index].SetProxyCurve(new_curve);
    new_curve = 0;
  }

  int eti, ti;
  int successful_split_count = 0;
  for (int i=0; i<split_t.Count(); i++)
  {
    double t0, t1;
    m_E[edge_index].GetDomain(&t0, &t1);
    if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) 
      break;

    //6 Dec 2002 Dale Lear:
    //   I added the relative edge_split_s and trm_split_s tests to detect
    //   attempts to trim a nano-gnats-wisker off the end of a trim.
    double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]);
    double trim_split_s = 0.5;

    if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON )
    {
      // this split is not possible
      continue;
    }
    
    if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON)
    {
      // this split is not possible
      continue;
    }

    // trim_t[] = corresponding trim parameters
    ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count());

    for ( eti = 0; eti < m_E[edge_index].m_ti.Count(); eti++)
    {
      ti = m_E[edge_index].m_ti[eti];
      if ( ti < 0 || ti >= m_T.Count() )
        continue;
      ON_BrepTrim& trim = m_T[ti];
      if ( 0 == i )
      {
        // On the first split, make sure the trim curve is up to snuff.
        new_curve = TuneupSplitteeHelper(trim.ProxyCurve());
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
          new_curve = 0;
        }
      }
      double t = ON_UNSET_VALUE;
      if (!GetTrimParameter(ti, split_t[i], &t) || !ON_IsValid(t))
        break;
      trim_t.Append(t);
      const ON_Interval trim_domain = trim.Domain();
      trim_split_s = trim_domain.NormalizedParameterAt(t);
      if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE )
        break;

      if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE )
        break;
    }

    if ( trim_t.Count() != m_E[edge_index].m_ti.Count() )
      continue;

    if (!SplitEdge(edge_index, split_t[i], trim_t))
    {
      continue;
    }

    // SplitEdge generally adjusts proxy domains instead
    // of trimming the orginal curve. These DuplicateCurve()
    // calls make a new curve whose domain exactly matches
    // the edge.
    for ( int epart = 0; epart < 2; epart++ )
    {
      ON_BrepEdge* newE = (0 == epart) ? &m_E[edge_index] : m_E.Last();
      if ( 0 == newE )
        continue;
      new_curve = TuneupEdgeOrTrimRealCurve(*newE,true);
      if (new_curve)
      {
        newE->m_c3i = AddEdgeCurve(new_curve);
        newE->SetProxyCurve(new_curve);
      }
      for ( eti = 0; eti < newE->m_ti.Count(); eti++ )
      {
        ti = newE->m_ti[eti];
        if ( ti < 0 || ti >= m_T.Count() )
          continue;
        ON_BrepTrim& trim = m_T[ti];
        new_curve = TuneupEdgeOrTrimRealCurve(trim,false);
        if (new_curve)
        {
          trim.m_c2i = AddTrimCurve(new_curve);
          trim.SetProxyCurve(new_curve);
        }
      }
    }

    successful_split_count++;
  }

  return successful_split_count;
}
Example #28
0
bool ON_Sphere::IsValid() const
{
  return ( ON_IsValid(radius) && radius > 0.0 && plane.IsValid() ) ? true : false;
}
Example #29
0
void ON_SpaceMorph::SetTolerance(double tolerance)
{
  m_tolerance = (ON_IsValid(tolerance) && tolerance > 0.0 ) 
              ? tolerance
              : 0.0;
}
bool ON_OffsetSurfaceFunction::SetOffsetPoint(
  double s,
  double t,
  double distance,
  double radius
  )
{
  bool rc = false;
  if ( ON_IsValid(s) && ON_IsValid(t) && ON_IsValid(distance) && ON_IsValid(radius) )
  {
    double u = m_domain[0].NormalizedParameterAt(s);
    if (u >= -0.01 && u <= 0.0 )
    {
      s = m_domain[0][0];
      u = 0.0;
    }
    if (u >= 1.0 && u <= 1.01 )
    {
      s = m_domain[0][1];
      u = 1.0;
    }

    double v = m_domain[1].NormalizedParameterAt(t);
    if (v >= -0.01 && v <= 0.0 )
    {
      t = m_domain[1][0];
      v = 0.0;
    }
    if (v >= 1.0 && v <= 1.01 )
    {
      t = m_domain[1][1];
      v = 1.0;
    }

    if ( u >= 0.0 && u <= 1.0 && v >= 0.0 && v <= 1.0 )
    {
      ON_OffsetSurfaceValue offset_value;
      offset_value.m_s = s;
      offset_value.m_t = t;
      offset_value.m_distance = distance;
      offset_value.m_radius = (radius > 0.0) ? radius : 0.0;
      offset_value.m_index = (int)((u + v*4096.0)*4096.0);
      int i;
      for ( i = 0; i < m_offset_value.Count(); i++ )
      {
        if ( m_offset_value[i].m_index == offset_value.m_index )
        {
          m_offset_value[i] = offset_value;
          break;
        }
      }
      if (i == m_offset_value.Count())
      {
        m_offset_value.Append(offset_value);
        m_bumps.SetCount(0);
        m_bValid = false;
      }
      rc = true;
    }
  }
  return rc;
}