Ejemplo n.º 1
0
void ConvexPolygon::calculateMatrixForm() {

    //every two adjacent endpoints define a line -> inequality constraint
    //first, resize A and b. x and b are column vectors
    this->A = Eigen::MatrixXd (this->endpoints.size(),2);
    this->b = Eigen::VectorXd (this->endpoints.size());
    Eigen::Vector2d normal;

    for(size_t i=1; i<endpoints.size(); i++) {
	//to define the correct line direction, we also need a point on the inside of the constraint - the seed
	normal(0) = endpoints[i-1](1) - endpoints[i](1);
	normal(1) = endpoints[i](0) - endpoints[i-1](0);
	if(normal.dot(seed) > 0) { //we want the outward pointing normal, so n.dot(s) < 0
	    normal = -normal;
	}
	normal.normalize();
	b(i-1) = -endpoints[i].dot(normal); //endpoints[i];
	A(i-1,0) = normal(0);
	A(i-1,1) = normal(1);
    }
    normal(0) = endpoints.back()(1) - endpoints.front()(1);
    normal(1) = endpoints.front()(0) - endpoints.back()(0);
    if(normal.dot(seed) > 0) { //we want the outward pointing normal, so n.dot(s) < 0
	normal = -normal;
    }
    normal.normalize();
    b(endpoints.size()-1) = -endpoints.front().dot(normal); //endpoints[i];
    A(endpoints.size()-1,0) = normal(0);
    A(endpoints.size()-1,1) = normal(1);
}
Ejemplo n.º 2
0
unsigned
NurbsTools::getClosestPoint (const Eigen::Vector2d &p, const Eigen::Vector2d &dir, const vector_vec2d &data,
                             unsigned &idxcp)
{
  if (data.empty ())
    throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n");

  size_t idx = 0;
  idxcp = 0;
  double dist2 (0.0);
  double dist2cp (DBL_MAX);
  for (size_t i = 0; i < data.size (); i++)
  {
    Eigen::Vector2d v = (data[i] - p);
    double d2 = v.squaredNorm ();

    if (d2 < dist2cp)
    {
      idxcp = i;
      dist2cp = d2;
    }

    if (d2 == 0.0)
      return i;

    v.normalize ();

    double d1 = dir.dot (v);
    if (d1 / d2 > dist2)
    {
      idx = i;
      dist2 = d1 / d2;
    }
  }
  return idx;
}
Ejemplo n.º 3
0
ON_NurbsSurface
SequentialFitter::grow (float max_dist, float max_angle, unsigned min_length, unsigned max_length)
{
  unsigned num_bnd = unsigned (this->m_data.boundary_param.size ());

  if (num_bnd == 0)
    throw std::runtime_error ("[SequentialFitter::grow] No boundary given.");

  if (unsigned (this->m_data.boundary.size ()) != num_bnd)
  {
    printf ("[SequentialFitter::grow] %lu %u\n", this->m_data.boundary.size (), num_bnd);
    throw std::runtime_error ("[SequentialFitter::grow] size of boundary and boundary parameters do not match.");
  }

  if (this->m_boundary_indices->indices.size () != num_bnd)
  {
    printf ("[SequentialFitter::grow] %lu %u\n", this->m_boundary_indices->indices.size (), num_bnd);
    throw std::runtime_error ("[SequentialFitter::grow] size of boundary indices and boundary parameters do not match.");
  }

  float angle = cosf (max_angle);
  unsigned bnd_moved (0);

  for (unsigned i = 0; i < num_bnd; i++)
  {
    Eigen::Vector3d r, tu, tv, n, bn;
    double pointAndTangents[9];
    double u = this->m_data.boundary_param[i] (0);
    double v = this->m_data.boundary_param[i] (1);

    // Evaluate point and tangents
    m_nurbs.Evaluate (u, v, 1, 3, pointAndTangents);
    r (0) = pointAndTangents[0];
    r (1) = pointAndTangents[1];
    r (2) = pointAndTangents[2];
    tu (0) = pointAndTangents[3];
    tu (1) = pointAndTangents[4];
    tu (2) = pointAndTangents[5];
    tv (0) = pointAndTangents[6];
    tv (1) = pointAndTangents[7];
    tv (2) = pointAndTangents[8];

    n = tu.cross (tv);
    n.normalize ();

    // calculate boundary normal (pointing outward)
    double eps = 0.00000001;

    if (u < eps)
      bn = n.cross (tv);
    if (u > 1.0 - eps)
      bn = -n.cross (tv);
    if (v < eps)
      bn = -n.cross (tu);
    if (v > 1.0 - eps)
      bn = n.cross (tu);

    bn.normalize ();

    Eigen::Vector3d e (r (0) + bn (0) * max_dist, r (1) + bn (1) * max_dist, r (2) + bn (2) * max_dist);

    // Project into image plane
    Eigen::Vector2d ri = this->project (r);
    Eigen::Vector2d ei = this->project (e);
    Eigen::Vector2d bni = ei - ri;
    bni.normalize ();

    // search for valid points along boundary normal in image space
    float max_dist_sq = max_dist * max_dist;
    bool valid = false;
    pcl::PointXYZRGB point = m_cloud->at (this->m_boundary_indices->indices[i]);
    for (unsigned j = min_length; j < max_length; j++)
    {
      int col = int (ri (0) + bni (0) * j);
      int row = int (ri (1) + bni (1) * j);

      if (row >= int (m_cloud->height) || row < 0)
      {
        j = max_length;
        break;
      }
      if (col >= int (m_cloud->width) || col < 0)
      {
        j = max_length;
        break;
      }

      unsigned idx = row * m_cloud->width + col;

      pcl::PointXYZRGB &pt = m_cloud->at (idx);
      if (!pcl_isnan (pt.x) && !pcl_isnan (pt.y) && !pcl_isnan (pt.z))
      {

        // distance requirement
        Eigen::Vector3d d (pt.x - r (0), pt.y - r (1), pt.z - r (2));
        if (d.dot (d) < max_dist_sq)
        {
          d.normalize ();
          if (std::abs (d.dot (bn)) > (angle))
          {
            valid = true;
            point = pt;
          } // dot
        } // max_dist
      } // isnan
    } // j

    // if valid point found, add current boundary point to interior points and move boundary
    if (valid)
    {
      this->m_data.interior.push_back (this->m_data.boundary[i]);
      this->m_data.boundary[i] (0) = point.x;
      this->m_data.boundary[i] (1) = point.y;
      this->m_data.boundary[i] (2) = point.z;
      bnd_moved++;
    }

  } // i

  compute_interior (m_nurbs);

  double int_err (0.0);
  double div_err = 1.0 / double (m_data.interior_error.size ());
  for (unsigned i = 0; i < m_data.interior_error.size (); i++)
  {
    int_err += (m_data.interior_error[i] * div_err);
  }

  printf ("[SequentialFitter::grow] average interior error: %e\n", int_err);

  return m_nurbs;

}
Ejemplo n.º 4
0
double
FittingCurve2d::inverseMappingO2 (const ON_NurbsCurve &nurbs, const Eigen::Vector2d &pt, double &error,
                                  Eigen::Vector2d &p, Eigen::Vector2d &t)
{
  if (nurbs.Order () != 2)
    printf ("[FittingCurve2d::inverseMappingO2] Error, order not 2 (polynomial degree 1)\n");

  std::vector<double> elements = getElementVector (nurbs);

  Eigen::Vector2d min_pt;
  double min_param (DBL_MAX);
  double min_dist (DBL_MAX);
  error = DBL_MAX;
  int is_corner (-1);

  for (unsigned i = 0; i < elements.size () - 1; i++)
  {
    Eigen::Vector2d p1;
    nurbs.Evaluate (elements[i], 0, 2, &p1 (0));

    Eigen::Vector2d p2;
    nurbs.Evaluate (elements[i + 1], 0, 2, &p2 (0));

    Eigen::Vector2d d1 (p2 (0) - p1 (0), p2 (1) - p1 (1));
    Eigen::Vector2d d2 (pt (0) - p1 (0), pt (1) - p1 (1));

    double d1_norm = d1.norm ();

    double d0_norm = d1.dot (d2) / d1_norm;
    Eigen::Vector2d d0 = d1 * d0_norm / d1_norm;
    Eigen::Vector2d p0 = p1 + d0;

    if (d0_norm < 0.0)
    {
      double tmp_dist = (p1 - pt).norm ();
      if (tmp_dist < min_dist)
      {
        min_dist = tmp_dist;
        min_pt = p1;
        min_param = elements[i];
        is_corner = i;
      }
    }
    else if (d0_norm >= d1_norm)
    {
      double tmp_dist = (p2 - pt).norm ();
      if (tmp_dist < min_dist)
      {
        min_dist = tmp_dist;
        min_pt = p2;
        min_param = elements[i + 1];
        is_corner = i + 1;
      }
    }
    else
    { // p0 lies on line segment
      double tmp_dist = (p0 - pt).norm ();
      if (tmp_dist < min_dist)
      {
        min_dist = tmp_dist;
        min_pt = p0;
        min_param = elements[i] + (d0_norm / d1_norm) * (elements[i + 1] - elements[i]);
        is_corner = -1;
      }
    }
  }

  if (is_corner >= 0)
  {
    double param1, param2;
    if (is_corner == 0 || is_corner == elements.size () - 1)
    {
      double x0a = elements[0];
      double x0b = elements[elements.size () - 1];
      double xa = elements[1];
      double xb = elements[elements.size () - 2];

      param1 = x0a + 0.5 * (xa - x0a);
      param2 = x0b + 0.5 * (xb - x0b);
    }
    else
    {
      double x0 = elements[is_corner];
      double x1 = elements[is_corner - 1];
      double x2 = elements[is_corner + 1];

      param1 = x0 + 0.5 * (x1 - x0);
      param2 = x0 + 0.5 * (x2 - x0);
    }

    double pt1[4];
    nurbs.Evaluate (param1, 1, 2, pt1);
    Eigen::Vector2d t1 (pt1[2], pt1[3]);
    t1.normalize ();

    double pt2[4];
    nurbs.Evaluate (param2, 1, 2, pt2);
    Eigen::Vector2d t2 (pt2[2], pt2[3]);
    t2.normalize ();

    t = 0.5 * (t1 + t2);
  }
  else
  {
    double point_tangent[4];
    nurbs.Evaluate (min_param, 1, 2, point_tangent);
    t (0) = point_tangent[2];
    t (1) = point_tangent[3];
  }

  t.normalize ();
  p = min_pt;
  return min_param;
}
Ejemplo n.º 5
0
template<typename PointInT> pcl::nurbs::NurbsSurface
pcl::nurbs::NurbsFitter<PointInT>::grow (float max_dist, float max_angle, unsigned min_length, unsigned max_length)
{
  unsigned num_bnd = this->nurbs_data_.boundary_param.size ();

  if (num_bnd == 0)
    throw std::runtime_error ("[NurbsFitter::grow] No boundary given.");

  if ((unsigned)this->nurbs_data_.boundary.size () != num_bnd)
  {
    printf ("[NurbsFitter::grow] %u %u\n", (unsigned)this->nurbs_data_.boundary.size (), num_bnd);
    throw std::runtime_error ("[NurbsFitter::grow] size of boundary and boundary parameters do not match.");
  }

  if (this->boundary_indices_->indices.size () != num_bnd)
  {
    printf ("[NurbsFitter::grow] %u %u\n", (unsigned)this->boundary_indices_->indices.size (), num_bnd);
    throw std::runtime_error ("[NurbsFitter::grow] size of boundary indices and boundary parameters do not match.");
  }

  float angle = cos (max_angle);
  unsigned bnd_moved (0);

  for (unsigned i = 0; i < num_bnd; i++)
  {
    vec3 r (0.0, 0.0, 0.0), tu (0.0, 0.0, 0.0), tv (0.0, 0.0, 0.0), n (0.0, 0.0, 0.0), bn (0.0, 0.0, 0.0);
    double u = this->nurbs_data_.boundary_param[i] (0);
    double v = this->nurbs_data_.boundary_param[i] (1);

    // Evaluate point and tangents
    nurbs_surface_.evaluate (u, v, r, tu, tv);

    n = tu.cross (tv);
    n.normalize ();

    // calculate boundary normal (pointing outward)
    double eps = 0.00000001;

    if (u < eps)
      bn = n.cross (tv);
    if (u > 1.0 - eps)
      bn = -n.cross (tv);
    if (v < eps)
      bn = -n.cross (tu);
    if (v > 1.0 - eps)
      bn = n.cross (tu);

    bn.normalize ();

    Eigen::Vector3d e (r (0) + bn (0) * max_dist, r (1) + bn (1) * max_dist, r (2) + bn (2) * max_dist);

    // Project into image plane
    Eigen::Vector2d ri = this->project (r);
    Eigen::Vector2d ei = this->project (e);
    Eigen::Vector2d bni = ei - ri;
    bni.normalize ();

    // search for valid points along boundary normal in image space
    float max_dist_sq = max_dist * max_dist;
    bool valid = false;
    PointInT point = cloud_->at (this->boundary_indices_->indices[i]);
    for (unsigned j = min_length; j < max_length; j++)
    {
      int col = static_cast<int> (ri (0) + bni (0) * j);
      int row = static_cast<int> (ri (1) + bni (1) * j);

      if (row >= int (cloud_->height) || row < 0)
      {
        j = max_length;
        break;
      }
      if (col >= int (cloud_->width) || col < 0)
      {
        j = max_length;
        break;
      }

      unsigned idx = row * cloud_->width + col;

      const PointInT &pt = cloud_->at (idx);
      if (!pcl_isnan (pt.x) && !pcl_isnan (pt.y) && !pcl_isnan (pt.z))
      {

        // distance requirement
        Eigen::Vector3d d (pt.x - r (0), pt.y - r (1), pt.z - r (2));
        if (d.dot (d) < max_dist_sq)
        {
          d.normalize ();
          if (std::abs (d.dot (bn)) > (angle))
          {
            valid = true;
            point = pt;
          } // dot
        } // max_dist
      } // isnan
    } // j

      // if valid point found, add current boundary point to interior points and move boundary
    if (valid)
    {
      this->nurbs_data_.interior.push_back (this->nurbs_data_.boundary[i]);
      this->nurbs_data_.boundary[i] (0) = point.x;
      this->nurbs_data_.boundary[i] (1) = point.y;
      this->nurbs_data_.boundary[i] (2) = point.z;
      ++bnd_moved;
    }

  } // i

  computeInterior (nurbs_surface_);

  double int_err (0.0);
  double div_err = 1.0 / nurbs_data_.interior_error.size ();
  for (unsigned i = 0; i < nurbs_data_.interior_error.size (); i++)
  {
    int_err += (nurbs_data_.interior_error[i] * div_err);
  }

  printf ("[NurbsFitter::grow] average interior error: %e\n", int_err);

  return (nurbs_surface_);
}