// ============================================================================= int Mesh2DUtils::last_nonlarger_knotvalue_ix(const Mesh2D&m, Direction2D d, double par) // ============================================================================= { const double* a = m.knotsBegin(d); const double* b = m.knotsEnd(d); double tol = 1.0e-8; // if (par < a[0] && par >= a[0]-tol) // par = a[0]; // if (par > b[-1] && par <= b[-1]+tol) // par = b[-1]; // searching for last nonlarger knotvalue using bisection for (int diff = (b-a)/2; diff != 0; diff = (b-a)/2) { if (par < a[0]+tol && par >= a[0]-tol) par = a[0]; if (par > b[-1]-tol && par <= b[-1]+tol) par = b[-1]; const double* mid = a + diff; ( (*mid > par) ? b : a) = mid; } if (b == m.knotsEnd(d)) --b; if (fabs(par-b[0]) < tol && fabs(par-a[0]) > tol) return (b - m.knotsBegin(d)); else return (a - m.knotsBegin(d)); // if index becomes negative, it signalizes that 'par' // is smaller than even the first knot value }
//============================================================================== // if 'b' can be split at least once in the mesh 'm', split it once, and return the // result through 'b1' and 'b2'. The function never carries out more than one split, // even when several splits are possible. bool LRBSpline2DUtils::try_split_once(const LRBSpline2D& b, const Mesh2D& mesh, LRBSpline2D*& b1, LRBSpline2D*& b2) //============================================================================== { const int umin = b.suppMin(XFIXED); const int vmin = b.suppMin(YFIXED); const int umax = b.suppMax(XFIXED); const int vmax = b.suppMax(YFIXED); const vector<int> m_kvec_u = derive_knots(mesh, XFIXED, umin, umax, vmin, vmax); const vector<int> m_kvec_v = derive_knots(mesh, YFIXED, vmin, vmax, umin, umax); // @@ The assertions below should always hold if function is called with correct // argument. When code is properly debugged and tested, they can be taken away for // efficiency (asserts should go away anyway when compiling in optimized mode). // Alternatively, if it is a concern that users might call this function with wrong // argument, the assertions could be replaced by exception-throwing 'if'-statements. assert(std::includes(m_kvec_u.begin(), m_kvec_u.end(), b.kvec(XFIXED).begin(), b.kvec(XFIXED).end())); assert(std::includes(m_kvec_v.begin(), m_kvec_v.end(), b.kvec(YFIXED).begin(), b.kvec(YFIXED).end())); if (num_inner_knots(m_kvec_u) > num_inner_knots(b.kvec(XFIXED))) { // Since we know that m_kvec_u contains more elements than b.kvec(XFIXED) and since // we know that the latter is included in the former, we know that there must be at least // one knot in 'm_kvec_u' that is not found in b.kvec(XFIXED). We can therefore call // the following function without risking an exception to be thrown. const int new_ix = find_uncovered_inner_knot(m_kvec_u, b.kvec(XFIXED)); // @@@ VSK. Cannot set pointers to the new bsplines before it is placed in the // global array. Will the position of the element change when a bspline is removed? split_function(b, mesh, XFIXED, mesh.knotsBegin(XFIXED), new_ix, b1, b2); return true; } else if (num_inner_knots(m_kvec_v) > num_inner_knots(b.kvec(YFIXED))) { // same comment as above const int new_ix = find_uncovered_inner_knot(m_kvec_v, b.kvec(YFIXED)); split_function(b, mesh, YFIXED, mesh.knotsBegin(YFIXED), new_ix, b1, b2); return true; } // No splits possible return false; }