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; }
RH_C_FUNCTION ON_MassProperties* ON_Curve_AreaMassProperties(const ON_Curve* pCurve, double rel_tol, double abs_tol, double curve_planar_tol) { ON_MassProperties* rc = NULL; if( pCurve ) { ON_Plane plane; if( pCurve->IsPlanar(&plane, curve_planar_tol) && pCurve->IsClosed() ) { ON_BoundingBox bbox = pCurve->BoundingBox(); ON_3dPoint basepoint = bbox.Center(); basepoint = plane.ClosestPointTo(basepoint); rc = new ON_MassProperties(); bool getresult = pCurve->AreaMassProperties(basepoint, plane.Normal(), *rc, true, true, true, true, rel_tol, abs_tol); if( getresult ) { rc->m_mass = fabs(rc->m_mass); } else { delete rc; rc = NULL; } } } return rc; }
int ON_Intersect( // returns 0 = no intersections, // 1 = intersection = single point, // 2 = intersection = circle // If 0 is returned, returned circle has radius=0 // and center = point on sphere closest to plane. // If 1 is returned, intersection is a single // point and returned circle has radius=0 // and center = intersection point on sphere. const ON_Plane& plane, const ON_Sphere& sphere, ON_Circle& circle ) { int rc = 0; const ON_3dPoint sphere_center = sphere.plane.origin; const double sphere_radius = fabs(sphere.radius); double tol = sphere_radius*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; circle.plane = plane; ON_3dPoint plane_center = plane.ClosestPointTo(sphere_center); double d = plane_center.DistanceTo(sphere_center); if ( d >= sphere_radius-tol ) { rc = ( d <= sphere_radius-tol ) ? 1 : 0; circle.plane.origin = sphere.ClosestPointTo(plane_center); circle.plane.UpdateEquation(); circle.radius = 0.0; } else { d /= sphere_radius; circle.radius = sphere_radius*sqrt(1.0 - d*d); if ( circle.radius <= ON_ZERO_TOLERANCE ) { circle.radius = 0.0; rc = 1; } else rc = 2; } //circle.UpdatePoints(); return rc; }
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; }
// 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; }