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; }
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; }