ON_BOOL32 MyUserData::Transform( const ON_Xform& xform ) { // Optional: call the ON_UserData::Transform() if you want the // ON_UserData::m_userdata_xform value to be updated. ON_UserData::Transform(xform); // Transform any geometry you have in your class. ON_BOOL32 rc = m_my_line.Transform(xform); return rc; }
int ON_Intersect( const ON_Line& line, const ON_Circle& circle, double* line_t0, ON_3dPoint& circle_point0, double* line_t1, ON_3dPoint& circle_point1 ) { // transform to coordinate system where equation of circle // is x^2 + y^2 = R^2 and solve for line parameter(s). ON_Xform xform; xform.ChangeBasis( circle.plane, ON_xy_plane ); xform.ChangeBasis( ON_xy_plane, circle.plane ); ON_Line L = line; L.Transform(xform); double r = fabs(circle.radius); double tol = r*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; int xcnt; if ( fabs(L.from.x - L.to.x) <= tol && fabs(L.from.y - L.to.y) <= tol && fabs(L.from.z - L.to.z) > tol ) { xcnt = 0; } else { xcnt = Intersect2dLineCircle( L.from, L.to, r, tol, line_t0, line_t1 ); if ( xcnt == 3 ) xcnt = 1; } if ( xcnt == 0 ) { if ( L.ClosestPointTo( circle.Center(), line_t0 ) ) { xcnt = 1; *line_t1 = *line_t0; } } ON_3dPoint line_point1, line_point0 = line.PointAt(*line_t0); circle_point0 = circle.ClosestPointTo(line_point0); double d1, d0 = line_point0.DistanceTo(circle_point0); if ( xcnt == 2 ) { line_point1 = line.PointAt(*line_t1); circle_point1 = circle.ClosestPointTo(line_point1); d1 = line_point1.DistanceTo(circle_point1); } else { line_point1 = line_point0; circle_point1 = circle_point0; d1 = d0; } if ( xcnt==2 && (d0 > tol && d1 > tol) ) { xcnt = 1; if ( d0 <= d1 ) { *line_t1 = *line_t0; line_point1 = line_point0; circle_point1 = circle_point0; d1 = d0; } else { *line_t0 = *line_t1; line_point0 = line_point1; circle_point0 = circle_point1; d0 = d1; } } if ( xcnt == 1 && d0 > tol ) { // TODO: iterate to closest point } return xcnt; }
int ON_Intersect( // returns 0 = no intersections, // 1 = one intersection, // 2 = 2 intersections // 3 = line lies on cylinder // If 0 is returned, first point is point // on line closest to cylinder and 2nd point is the point // on the sphere closest to the line. // If 1 is returned, first point is obtained by evaluating // the line and the second point is obtained by evaluating // the cylinder. const ON_Line& line, const ON_Cylinder& cylinder, // if cylinder.height[0]==cylinder.height[1], // then infinite cyl is used. Otherwise // finite cyl is used. ON_3dPoint& A, ON_3dPoint& B // intersection point(s) returned here ) { ON_BOOL32 bFiniteCyl = true; int rc = 0; const double cylinder_radius = fabs(cylinder.circle.radius); double tol = cylinder_radius*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; ON_Line axis; axis.from = cylinder.circle.plane.origin + cylinder.height[0]*cylinder.circle.plane.zaxis; axis.to = cylinder.circle.plane.origin + cylinder.height[1]*cylinder.circle.plane.zaxis; if ( axis.Length() <= tol ) { axis.to = cylinder.circle.plane.origin + cylinder.circle.plane.zaxis; bFiniteCyl = false; } //ON_BOOL32 bIsParallel = false; double line_t, axis_t; if ( !ON_Intersect(line,axis,&line_t,&axis_t) ) { axis.ClosestPointTo( cylinder.circle.plane.origin, &axis_t ); line.ClosestPointTo( cylinder.circle.plane.origin, &line_t ); } ON_3dPoint line_point = line.PointAt(line_t); ON_3dPoint axis_point = axis.PointAt(axis_t); double d = line_point.DistanceTo(axis_point); if ( bFiniteCyl ) { if ( axis_t < 0.0 ) axis_t = 0.0; else if ( axis_t > 1.0 ) axis_t = 1.0; axis_point = axis.PointAt(axis_t); } if ( d >= cylinder_radius-tol) { rc = ( d <= cylinder_radius+tol ) ? 1 : 0; A = line_point; ON_3dVector V = line_point - axis_point; if ( bFiniteCyl ) { V = V - (V*cylinder.circle.plane.zaxis)*cylinder.circle.plane.zaxis; } V.Unitize(); B = axis_point + cylinder_radius*V; if ( rc == 1 ) { // check for overlap ON_3dPoint P = axis.ClosestPointTo(line.from); d = P.DistanceTo(line.from); if ( fabs(d-cylinder_radius) <= tol ) { P = axis.ClosestPointTo(line.to); d = P.DistanceTo(line.to); if ( fabs(d-cylinder_radius) <= tol ) { rc = 3; A = cylinder.ClosestPointTo(line.from); B = cylinder.ClosestPointTo(line.to); } } } } else { // transform to coordinate system where equation of cyl // is x^2 + y^2 = R^2 and solve for line parameter(s). ON_Xform xform; xform.Rotation( cylinder.circle.plane, ON_xy_plane ); ON_Line L = line; L.Transform(xform); const double x0 = L.from.x; const double x1 = L.to.x; const double x1mx0 = x1-x0; double ax = x1mx0*x1mx0; double bx = 2.0*x1mx0*x0; double cx = x0*x0; const double y0 = L.from.y; const double y1 = L.to.y; const double y1my0 = y1-y0; double ay = y1my0*y1my0; double by = 2.0*y1my0*y0; double cy = y0*y0; double t0, t1; int qerc = ON_SolveQuadraticEquation(ax+ay, bx+by, cx+cy-cylinder_radius*cylinder_radius, &t0,&t1); if ( qerc == 2 ) { // complex roots - ignore (tiny) imaginary part caused by computational noise. t1 = t0; } A = cylinder.ClosestPointTo(line.PointAt(t0)); B = cylinder.ClosestPointTo(line.PointAt(t1)); d = A.DistanceTo(B); if ( d <= ON_ZERO_TOLERANCE ) { A = line_point; ON_3dVector V = line_point - axis_point; if ( bFiniteCyl ) { V = V - (V*cylinder.circle.plane.zaxis)*cylinder.circle.plane.zaxis; } V.Unitize(); B = axis_point + cylinder_radius*V; rc = 1; } else rc = 2; } return rc; }