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;
        }
Beispiel #2
0
        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;

        }