Ejemplo n.º 1
0
    /**
     * \return Returns the weights for the covariance of the points as a vector
     */
    WeightVector covariance_weights_vector() const noexcept
    {
        const int point_count = count_points();

        WeightVector weight_vec(point_count);

        for (int i = 0; i < point_count; ++i)
        {
            weight_vec(i) = weights_(i).w_cov;
        }

        return weight_vec;
    }
Ejemplo n.º 2
0
Archivo: mls.hpp Proyecto: diegodgs/PCL
template <typename PointInT, typename PointOutT> void
pcl::MovingLeastSquares<PointInT, PointOutT>::computeMLSPointNormal (int index,
                                                                     const PointCloudIn &input,
                                                                     const std::vector<int> &nn_indices,
                                                                     std::vector<float> &nn_sqr_dists,
                                                                     PointCloudOut &projected_points,
                                                                     NormalCloud &projected_points_normals)
{
  // Compute the plane coefficients
  //pcl::computePointNormal<PointInT> (*input_, nn_indices, model_coefficients, curvature);
  EIGEN_ALIGN16 Eigen::Matrix3f covariance_matrix;
  Eigen::Vector4f xyz_centroid;

  // Estimate the XYZ centroid
  pcl::compute3DCentroid (input, nn_indices, xyz_centroid);
  //pcl::compute3DCentroid (input, nn_indices, xyz_centroid);

  pcl::computeCovarianceMatrix (input, nn_indices, xyz_centroid, covariance_matrix);
  // Compute the 3x3 covariance matrix

  EIGEN_ALIGN16 Eigen::Vector3f::Scalar eigen_value;
  EIGEN_ALIGN16 Eigen::Vector3f eigen_vector;
  Eigen::Vector4f model_coefficients;
  pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
  model_coefficients.head<3> () = eigen_vector;
  model_coefficients[3] = 0;
  model_coefficients[3] = -1 * model_coefficients.dot (xyz_centroid);

  // Projected query point
  Eigen::Vector3f point = input[(*indices_)[index]].getVector3fMap ();
  float distance = point.dot (model_coefficients.head<3> ()) + model_coefficients[3];
  point -= distance * model_coefficients.head<3> ();

  float curvature = covariance_matrix.trace ();
  // Compute the curvature surface change
  if (curvature != 0)
    curvature = fabsf (eigen_value / curvature);


  // Get a copy of the plane normal easy access
  Eigen::Vector3d plane_normal = model_coefficients.head<3> ().cast<double> ();
  // Vector in which the polynomial coefficients will be put
  Eigen::VectorXd c_vec;
  // Local coordinate system (Darboux frame)
  Eigen::Vector3d v (0.0f, 0.0f, 0.0f), u (0.0f, 0.0f, 0.0f);



  // Perform polynomial fit to update point and normal
  ////////////////////////////////////////////////////
  if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_)
  {
    // Update neighborhood, since point was projected, and computing relative
    // positions. Note updating only distances for the weights for speed
    std::vector<Eigen::Vector3d> de_meaned (nn_indices.size ());
    for (size_t ni = 0; ni < nn_indices.size (); ++ni)
    {
      de_meaned[ni][0] = input_->points[nn_indices[ni]].x - point[0];
      de_meaned[ni][1] = input_->points[nn_indices[ni]].y - point[1];
      de_meaned[ni][2] = input_->points[nn_indices[ni]].z - point[2];
      nn_sqr_dists[ni] = static_cast<float> (de_meaned[ni].dot (de_meaned[ni]));
    }

    // Allocate matrices and vectors to hold the data used for the polynomial fit
    Eigen::VectorXd weight_vec (nn_indices.size ());
    Eigen::MatrixXd P (nr_coeff_, nn_indices.size ());
    Eigen::VectorXd f_vec (nn_indices.size ());
    Eigen::MatrixXd P_weight; // size will be (nr_coeff_, nn_indices.size ());
    Eigen::MatrixXd P_weight_Pt (nr_coeff_, nr_coeff_);

    // Get local coordinate system (Darboux frame)
    v = plane_normal.unitOrthogonal ();
    u = plane_normal.cross (v);

    // Go through neighbors, transform them in the local coordinate system,
    // save height and the evaluation of the polynome's terms
    double u_coord, v_coord, u_pow, v_pow;
    for (size_t ni = 0; ni < nn_indices.size (); ++ni)
    {
      // (re-)compute weights
      weight_vec (ni) = exp (-nn_sqr_dists[ni] / sqr_gauss_param_);

      // transforming coordinates
      u_coord = de_meaned[ni].dot (u);
      v_coord = de_meaned[ni].dot (v);
      f_vec (ni) = de_meaned[ni].dot (plane_normal);

      // compute the polynomial's terms at the current point
      int j = 0;
      u_pow = 1;
      for (int ui = 0; ui <= order_; ++ui)
      {
        v_pow = 1;
        for (int vi = 0; vi <= order_ - ui; ++vi)
        {
          P (j++, ni) = u_pow * v_pow;
          v_pow *= v_coord;
        }
        u_pow *= u_coord;
      }
    }

    // Computing coefficients
    P_weight = P * weight_vec.asDiagonal ();
    P_weight_Pt = P_weight * P.transpose ();
    c_vec = P_weight * f_vec;
    P_weight_Pt.llt ().solveInPlace (c_vec);
  }

  switch (upsample_method_)
  {
    case (NONE):
    {
      Eigen::Vector3d normal = plane_normal;

      if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ && pcl_isfinite (c_vec[0]))
      {
        point += (c_vec[0] * plane_normal).cast<float> ();

        // Compute tangent vectors using the partial derivates evaluated at (0,0) which is c_vec[order_+1] and c_vec[1]
        if (compute_normals_)
          normal = plane_normal - c_vec[order_ + 1] * u - c_vec[1] * v;
      }

      PointOutT aux;
      aux.x = point[0];
      aux.y = point[1];
      aux.z = point[2];
      projected_points.push_back (aux);

      if (compute_normals_)
      {
        pcl::Normal aux_normal;
        aux_normal.normal_x = static_cast<float> (normal[0]);
        aux_normal.normal_y = static_cast<float> (normal[1]);
        aux_normal.normal_z = static_cast<float> (normal[2]);
        aux_normal.curvature = curvature;
        projected_points_normals.push_back (aux_normal);
      }

      break;
    }

    case (SAMPLE_LOCAL_PLANE):
    {
      // Uniformly sample a circle around the query point using the radius and step parameters
      for (float u_disp = -static_cast<float> (upsampling_radius_); u_disp <= upsampling_radius_; u_disp += static_cast<float> (upsampling_step_))
        for (float v_disp = -static_cast<float> (upsampling_radius_); v_disp <= upsampling_radius_; v_disp += static_cast<float> (upsampling_step_))
          if (u_disp*u_disp + v_disp*v_disp < upsampling_radius_*upsampling_radius_)
          {
            PointOutT projected_point;
            pcl::Normal projected_normal;
            projectPointToMLSSurface (u_disp, v_disp, u, v, plane_normal, curvature, point, c_vec, 
                                      static_cast<int> (nn_indices.size ()),
                                      projected_point, projected_normal);

            projected_points.push_back (projected_point);
            if (compute_normals_)
              projected_points_normals.push_back (projected_normal);
          }
      break;
    }

    case (RANDOM_UNIFORM_DENSITY):
    {
      // Compute the local point density and add more samples if necessary
      int num_points_to_add = static_cast<int> (floor (desired_num_points_in_radius_ / 2.0 / static_cast<double> (nn_indices.size ())));

      // Just add the query point, because the density is good
      if (num_points_to_add <= 0)
      {
        // Just add the current point
        Eigen::Vector3d normal = plane_normal;
        if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ && pcl_isfinite (c_vec[0]))
        {
          // Projection onto MLS surface along Darboux normal to the height at (0,0)
          point += (c_vec[0] * plane_normal).cast<float> ();
          // Compute tangent vectors using the partial derivates evaluated at (0,0) which is c_vec[order_+1] and c_vec[1]
          if (compute_normals_)
            normal = plane_normal - c_vec[order_ + 1] * u - c_vec[1] * v;
        }
        PointOutT aux;
        aux.x = point[0];
        aux.y = point[1];
        aux.z = point[2];
        projected_points.push_back (aux);

        if (compute_normals_)
        {
          pcl::Normal aux_normal;
          aux_normal.normal_x = static_cast<float> (normal[0]);
          aux_normal.normal_y = static_cast<float> (normal[1]);
          aux_normal.normal_z = static_cast<float> (normal[2]);
          aux_normal.curvature = curvature;
          projected_points_normals.push_back (aux_normal);
        }
      }
      else
      {
        // Sample the local plane
        for (int num_added = 0; num_added < num_points_to_add;)
        {
          float u_disp = (*rng_uniform_distribution_) (),
                v_disp = (*rng_uniform_distribution_) ();
          // Check if inside circle; if not, try another coin flip
          if (u_disp * u_disp + v_disp * v_disp > search_radius_ * search_radius_/4)
            continue;


          PointOutT projected_point;
          pcl::Normal projected_normal;
          projectPointToMLSSurface (u_disp, v_disp, u, v, plane_normal, curvature, point, c_vec, 
                                    static_cast<int> (nn_indices.size ()),
                                    projected_point, projected_normal);

          projected_points.push_back (projected_point);
          if (compute_normals_)
            projected_points_normals.push_back (projected_normal);

          num_added ++;
        }
      }
      break;
    }

    case (VOXEL_GRID_DILATION):
    {
      // Take all point pairs and sample space between them in a grid-fashion
      // \note consider only point pairs with increasing indices
      MLSResult result (plane_normal, u, v, c_vec, static_cast<int> (nn_indices.size ()), curvature);
      mls_results_[index] = result;
      break;
    }
  }
}
Ejemplo n.º 3
0
/*
 * Fits a weighted cubic regression on predictor(s)
 *
 * @param contrast - want to predict this value per snp
 * @param strength - covariate of choice
 * @param weights - weight of data points for this genotype
 * @param Predictor - output, prediction function coefficients
 * @param Predicted - output, predicted contrast per snp
 */
void
FitWeightedCubic(const std::vector<double> &contrast,
                 const std::vector<double> &strength,
                 const std::vector<double> &weights,
                 std::vector<double> &Predictor,
                 std::vector<double> &Predicted) {

  	// Singular value decomposition method
	unsigned int i;
	unsigned int nobs;
	unsigned int npred;
	npred = 3+1;
	nobs= contrast.size();

	// convert double into doubles to match newmat
  vector<Real> tmp_vec(nobs);
  Real* tmp_ptr = &tmp_vec[0];
	vector<Real> obs_vec(nobs);
	Real *obs_ptr = &obs_vec[0];
	vector<Real> weight_vec(nobs);

  Matrix covarMat(nobs,npred);
	ColumnVector observedVec(nobs);

	// fill in the data
	// modified by weights
	for (i=0; i<nobs; i++)
		weight_vec[i] = sqrt(weights[i]);

  	// load data - 1s into col 1 of matrix
	for (i=0; i<nobs; i++)
		tmp_vec[i] = weight_vec[i];
  	covarMat.Column(1) << tmp_ptr;
	for (i=0; i<nobs; i++)
		tmp_vec[i] *= strength[i];
  	covarMat.Column(2) << tmp_ptr;
	for (i=0; i<nobs; i++)
		tmp_vec[i] *= strength[i];
  	covarMat.Column(3) << tmp_ptr;
	for (i=0; i<nobs; i++)
		tmp_vec[i] *= strength[i];
  	covarMat.Column(4) << tmp_ptr;

  	for (i=0; i<nobs; i++)
		obs_vec[i] = contrast[i]*weight_vec[i];
  	observedVec << obs_ptr;

  	// do SVD
  	Matrix U, V;
  	DiagonalMatrix D;
    ColumnVector Fitted(nobs);
    ColumnVector A(npred);

  	SVD(covarMat,D,U,V);

  	Fitted = U.t() * observedVec;
  	A = V * ( D.i() * Fitted );

	// this predicts "0" for low weights
	// because of weighted regression
  	Fitted = U * Fitted;

	// this is the predictor
	Predictor.resize(npred);
	for (i=0; i<npred; i++)
		Predictor[i] = A.element(i);


  // export data back to doubles
	// and therefore this predicts "0" for low-weighted points
	// which is >not< the desired outcome!!!!
	// instead we need to predict all points at once
	// >unweighted< as output
	vector<double> Goofy;
	Predicted.resize(nobs);
  	for (i = 0; i < nobs; ++i) {
      Goofy.resize(npred);
      Goofy[0] = 1;
      Goofy[1] = strength[i];
      Goofy[2] = strength[i]*Goofy[1];
      Goofy[3] = strength[i]*Goofy[2];
      Predicted[i] = vprod(Goofy,Predictor);
  	}
}
Ejemplo n.º 4
0
//' rcpp_make_compact_graph
//'
//' Removes nodes and edges from a graph that are not needed for routing
//'
//' @param graph graph to be processed
//' @param quiet If TRUE, display progress
//' @return \code{Rcpp::List} containing one \code{data.frame} with the compact
//' graph, one \code{data.frame} with the original graph and one
//' \code{data.frame} containing information about the relating edge ids of the
//' original and compact graph.
//'
//' @noRd
// [[Rcpp::export]]
Rcpp::List rcpp_make_compact_graph (Rcpp::DataFrame graph, bool quiet)
{
    vertex_map_t vertices;
    edge_map_t edge_map;
    std::unordered_map <osm_id_t, int> components;
    int largest_component;
    vert2edge_map_t vert2edge_map;

    if (!quiet)
    {
        Rcpp::Rcout << "Constructing graph ... ";
        Rcpp::Rcout.flush ();
    }
    graph_from_df (graph, vertices, edge_map, vert2edge_map);
    if (!quiet)
    {
        Rcpp::Rcout << std::endl << "Determining connected components ... ";
        Rcpp::Rcout.flush ();
    }
    get_largest_graph_component (vertices, components, largest_component);

    if (!quiet)
    {
        Rcpp::Rcout << std::endl << "Removing intermediate nodes ... ";
        Rcpp::Rcout.flush ();
    }
    vertex_map_t vertices2 = vertices;
    edge_map_t edge_map2 = edge_map;
    contract_graph (vertices2, edge_map2, vert2edge_map);

    if (!quiet)
    {
        Rcpp::Rcout << std::endl << "Mapping compact to original graph ... ";
        Rcpp::Rcout.flush ();
    }
    int nedges = edge_map2.size ();

    // These vectors are all for the contracted graph:
    Rcpp::StringVector from_vec (nedges), to_vec (nedges),
        highway_vec (nedges);
    Rcpp::NumericVector from_lat_vec (nedges), from_lon_vec (nedges),
        to_lat_vec (nedges), to_lon_vec (nedges), dist_vec (nedges),
        weight_vec (nedges), edgeid_vec (nedges);

    unsigned int map_size = 0; // size of edge map contracted -> original
    unsigned int en = 0;
    std::map <int, osm_edge_t> edge_ordered;
    for (auto e = edge_map2.begin (); e != edge_map2.end (); ++e)
        edge_ordered.emplace (e->first, e->second);

    for (auto e = edge_ordered.begin (); e != edge_ordered.end (); ++e)
    {
        osm_id_t from = e->second.get_from_vertex ();
        osm_id_t to = e->second.get_to_vertex ();
        osm_vertex_t from_vtx = vertices2.at (from);
        osm_vertex_t to_vtx = vertices2.at (to);

        from_vec (en) = from;
        to_vec (en) = to;
        highway_vec (en) = e->second.highway;
        dist_vec (en) = e->second.dist;
        weight_vec (en) = e->second.weight;
        from_lat_vec (en) = from_vtx.getLat ();
        from_lon_vec (en) = from_vtx.getLon ();
        to_lat_vec (en) = to_vtx.getLat ();
        to_lon_vec (en) = to_vtx.getLon ();
        edgeid_vec (en) = e->second.getID ();

        map_size += e->second.is_replacement_for ().size ();
        en++;
    }

    Rcpp::NumericVector edge_id_orig (map_size), edge_id_comp (map_size);
    int pos = 0;
    for (auto e = edge_ordered.begin (); e != edge_ordered.end (); ++e)
    {
        int eid = e->second.getID ();
        std::set <int> edges = e->second.is_replacement_for ();
        for (auto ei: edges)
        {
            edge_id_comp (pos) = eid;
            edge_id_orig (pos++) = ei;
        }
    }
    
    Rcpp::DataFrame compact = Rcpp::DataFrame::create (
            Rcpp::Named ("from_id") = from_vec,
            Rcpp::Named ("to_id") = to_vec,
            Rcpp::Named ("edge_id") = edgeid_vec,
            Rcpp::Named ("d") = dist_vec,
            Rcpp::Named ("d_weighted") = weight_vec,
            Rcpp::Named ("from_lat") = from_lat_vec,
            Rcpp::Named ("from_lon") = from_lon_vec,
            Rcpp::Named ("to_lat") = to_lat_vec,
            Rcpp::Named ("to_lon") = to_lon_vec,
            Rcpp::Named ("highway") = highway_vec);

    Rcpp::DataFrame rel = Rcpp::DataFrame::create (
            Rcpp::Named ("id_compact") = edge_id_comp,
            Rcpp::Named ("id_original") = edge_id_orig);

    if (!quiet)
        Rcpp::Rcout << std::endl;

    return Rcpp::List::create (
            Rcpp::Named ("compact") = compact,
            Rcpp::Named ("original") = graph,
            Rcpp::Named ("map") = rel);
}
Ejemplo n.º 5
0
template <typename PointT> void
pcl::MLSResult::computeMLSSurface (const pcl::PointCloud<PointT> &cloud,
                                   int index,
                                   const std::vector<int> &nn_indices,
                                   double search_radius,
                                   int polynomial_order,
                                   boost::function<double(const double)> weight_func)
{
  // Compute the plane coefficients
  EIGEN_ALIGN16 Eigen::Matrix3d covariance_matrix;
  Eigen::Vector4d xyz_centroid;

  // Estimate the XYZ centroid
  pcl::compute3DCentroid (cloud, nn_indices, xyz_centroid);

  // Compute the 3x3 covariance matrix
  pcl::computeCovarianceMatrix (cloud, nn_indices, xyz_centroid, covariance_matrix);
  EIGEN_ALIGN16 Eigen::Vector3d::Scalar eigen_value;
  EIGEN_ALIGN16 Eigen::Vector3d eigen_vector;
  Eigen::Vector4d model_coefficients (0, 0, 0, 0);
  pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
  model_coefficients.head<3> ().matrix () = eigen_vector;
  model_coefficients[3] = -1 * model_coefficients.dot (xyz_centroid);

  // Projected query point
  valid = true;
  query_point = cloud.points[index].getVector3fMap ().template cast<double> ();
  double distance = query_point.dot (model_coefficients.head<3> ()) + model_coefficients[3];
  mean = query_point - distance * model_coefficients.head<3> ();

  curvature = covariance_matrix.trace ();
  // Compute the curvature surface change
  if (curvature != 0)
    curvature = std::abs (eigen_value / curvature);

  // Get a copy of the plane normal easy access
  plane_normal = model_coefficients.head<3> ();

  // Local coordinate system (Darboux frame)
  v_axis = plane_normal.unitOrthogonal ();
  u_axis = plane_normal.cross (v_axis);

  // Perform polynomial fit to update point and normal
  ////////////////////////////////////////////////////
  num_neighbors = static_cast<int> (nn_indices.size ());
  order = polynomial_order;
  if (order > 1)
  {
    int nr_coeff = (order + 1) * (order + 2) / 2;

    if (num_neighbors >= nr_coeff)
    {
      // Note: The max_sq_radius parameter is only used if weight_func was not defined
      double max_sq_radius = 1;
      if (weight_func == 0)
      {
        max_sq_radius = search_radius * search_radius;
        weight_func = boost::bind (&pcl::MLSResult::computeMLSWeight, this, _1, max_sq_radius);
      }

      // Allocate matrices and vectors to hold the data used for the polynomial fit
      Eigen::VectorXd weight_vec (num_neighbors);
      Eigen::MatrixXd P (nr_coeff, num_neighbors);
      Eigen::VectorXd f_vec (num_neighbors);
      Eigen::MatrixXd P_weight; // size will be (nr_coeff_, nn_indices.size ());
      Eigen::MatrixXd P_weight_Pt (nr_coeff, nr_coeff);

      // Update neighborhood, since point was projected, and computing relative
      // positions. Note updating only distances for the weights for speed
      std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > de_meaned (num_neighbors);
      for (size_t ni = 0; ni < (size_t) num_neighbors; ++ni)
      {
        de_meaned[ni][0] = cloud.points[nn_indices[ni]].x - mean[0];
        de_meaned[ni][1] = cloud.points[nn_indices[ni]].y - mean[1];
        de_meaned[ni][2] = cloud.points[nn_indices[ni]].z - mean[2];
        weight_vec (ni) = weight_func (de_meaned[ni].dot (de_meaned[ni]));
      }

      // Go through neighbors, transform them in the local coordinate system,
      // save height and the evaluation of the polynome's terms
      double u_coord, v_coord, u_pow, v_pow;
      for (size_t ni = 0; ni < (size_t) num_neighbors; ++ni)
      {
        // Transforming coordinates
        u_coord = de_meaned[ni].dot (u_axis);
        v_coord = de_meaned[ni].dot (v_axis);
        f_vec (ni) = de_meaned[ni].dot (plane_normal);

        // Compute the polynomial's terms at the current point
        int j = 0;
        u_pow = 1;
        for (int ui = 0; ui <= order; ++ui)
        {
          v_pow = 1;
          for (int vi = 0; vi <= order - ui; ++vi)
          {
            P (j++, ni) = u_pow * v_pow;
            v_pow *= v_coord;
          }
          u_pow *= u_coord;
        }
      }

      // Computing coefficients
      P_weight = P * weight_vec.asDiagonal ();
      P_weight_Pt = P_weight * P.transpose ();
      c_vec = P_weight * f_vec;
      P_weight_Pt.llt ().solveInPlace (c_vec);
    }
  }
}