bool FixedNumPoints::operator() (const Streamline<>& in, Streamline<>& out) const { // Perform an explicit calculation of streamline length // From this, derive the spline position of each sample assert (in.size() > 1); out.clear(); out.index = in.index; out.weight = in.weight; value_type length = 0.0; vector<value_type> steps; for (size_t i = 1; i != in.size(); ++i) { const value_type dist = (in[i] - in[i-1]).norm(); length += dist; steps.push_back (dist); } steps.push_back (value_type(0)); Math::Hermite<value_type> interp (hermite_tension); Streamline<> temp (in); const size_t s = temp.size(); temp.insert (temp.begin(), temp[0] + (temp[0] - temp[ 1 ])); temp.push_back ( temp[s] + (temp[s] - temp[s-1])); value_type cumulative_length = value_type(0); size_t input_index = 0; for (size_t output_index = 0; output_index != num_points; ++output_index) { const value_type target_length = length * output_index / value_type(num_points-1); while (input_index < s && (cumulative_length + steps[input_index] < target_length)) cumulative_length += steps[input_index++]; if (input_index == s) { out.push_back (temp[s]); break; } const value_type mu = (target_length - cumulative_length) / steps[input_index]; interp.set (mu); out.push_back (interp.value (temp[input_index], temp[input_index+1], temp[input_index+2], temp[input_index+3])); } return true; }
Point<float> GMWMI_finder::find_interface (const std::vector< Point<float> >& tck, const bool end, Interp& interp) const { if (tck.size() == 0) return Point<float>(); if (tck.size() == 1) return tck.front(); if (tck.size() == 2) return (end ? tck.back() : tck.front()); // Track is long enough; can do the proper search // Need to generate an additional point beyond the end point typedef Point<float> PointF; size_t last = tck.size() - 1; const PointF p_end (end ? tck.back() : tck.front()); const PointF p_prev (end ? tck[last-1] : tck[1]); // Before proceeding, make sure that the interface lies somewhere in between these two points if (interp.scanner (p_end)) return p_end; const Tissues t_end (interp); if (interp.scanner (p_prev)) return p_end; const Tissues t_prev (interp); if (! (((t_end.get_gm() > t_end.get_wm()) && (t_prev.get_gm() < t_prev.get_wm())) || ((t_end.get_gm() < t_end.get_wm()) && (t_prev.get_gm() > t_prev.get_wm())))) { return p_end; } // Also make sure that the existing endpoint doesn't already obey the criterion if (t_end.get_gm() - t_end.get_wm() < GMWMI_ACCURACY) return p_end; const PointF curvature (end ? ((tck[last]-tck[last-1]) - (tck[last-1]-tck[last-2])) : ((tck[0]-tck[1]) - (tck[1]-tck[2]))); const PointF extrap ((end ? (tck[last]-tck[last-1]) : (tck[0]-tck[1])) + curvature); const PointF p_extrap (p_end + extrap); Point<float> domain [4]; domain[0] = (end ? tck[last-2] : tck[2]); domain[1] = p_prev; domain[2] = p_end; domain[3] = p_extrap; Math::Hermite<float> hermite (GMWMI_HERMITE_TENSION); float min_mu = 0.0, max_mu = 1.0; Point<float> p_best = p_end; size_t iters = 0; do { const float mu = 0.5 * (min_mu + max_mu); hermite.set (mu); const Point<float> p (hermite.value (domain)); interp.scanner (p); const Tissues t (interp); if (t.get_wm() > t.get_gm()) { min_mu = mu; } else { max_mu = mu; p_best = p; if (t.get_gm() - t.get_wm() < GMWMI_ACCURACY) return p_best; } } while (++iters != GMWMI_MAX_ITERS_TO_FIND_BOUNDARY); return p_best; }