bool ON_Mesh::EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const { // virtual function default P = ON_UNSET_POINT; ON_COMPONENT_INDEX ci = objref.m_component_index; switch ( ci.m_type ) { case ON_COMPONENT_INDEX::mesh_vertex: if ( ci.m_index >= 0 && ci.m_index < m_V.Count() ) P = m_V[ci.m_index]; break; case ON_COMPONENT_INDEX::meshtop_vertex: if ( ci.m_index >= 0 && ci.m_index < m_top.m_topv.Count() ) { const ON_MeshTopologyVertex& topv = m_top.m_topv[ci.m_index]; if ( topv.m_v_count > 0 && topv.m_vi ) { int vi = topv.m_vi[0]; if ( vi >= 0 && vi < m_V.Count() ) P = m_V[vi]; } } break; case ON_COMPONENT_INDEX::meshtop_edge: if ( 5 == objref.m_evp.m_t_type && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] - 1.0) <= ON_SQRT_EPSILON ) { ON_Line L = m_top.TopEdgeLine(ci.m_index); if ( L.IsValid() ) { P = L.PointAt(objref.m_evp.m_t[0]); } } break; case ON_COMPONENT_INDEX::mesh_face: if ( 4 == objref.m_evp.m_t_type && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] + objref.m_evp.m_t[2] + objref.m_evp.m_t[3] - 1.0) <= ON_SQRT_EPSILON ) { if ( ci.m_index >= 0 && ci.m_index < m_F.Count() ) { const int* fvi = m_F[ci.m_index].vi; if ( fvi[0] < 0 || fvi[0] >= m_V.Count() ) break; if ( fvi[1] < 0 || fvi[1] >= m_V.Count() ) break; if ( fvi[2] < 0 || fvi[2] >= m_V.Count() ) break; if ( fvi[3] < 0 || fvi[3] >= m_V.Count() ) break; ON_3dPoint V[4]; V[0] = m_V[fvi[0]]; V[1] = m_V[fvi[1]]; V[2] = m_V[fvi[2]]; V[3] = m_V[fvi[3]]; P = objref.m_evp.m_t[0]*V[0] + objref.m_evp.m_t[1]*V[1] + objref.m_evp.m_t[2]*V[2] + objref.m_evp.m_t[3]*V[3]; } } break; default: // intentionally skipping other ON_COMPONENT_INDEX::TYPE enum values break; } return P.IsValid(); }
int ON_ArePointsOnLine( // 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_Line& line, // line to test double tolerance ) { double w; int i, j, k; if ( count < 1 ) return 0; if ( !line.IsValid() ) { ON_ERROR("line parameter not valid"); return 0; } if ( !bbox.IsValid() ) { ON_ERROR("bbox parameter not valid"); return 0; } if ( !ON_IsValid(tolerance) || tolerance < 0.0 ) { ON_ERROR("tolerance parameter not valid"); return 0; } if ( dim < 2 || dim > 3 ) { ON_ERROR("dim parameter not valid"); return 0; } if ( 0 == point ) { ON_ERROR("point parameter not valid"); return 0; } if ( stride < (is_rat?(dim+1):dim) ) { ON_ERROR("stride parameter not valid"); 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( line.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( line.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( line.ClosestPointTo( Q ) ) > tolerance ) { rc = 0; break; } point += stride; } } } return rc; }