#ifndef CGAL_SHAPE_DETECTION_3_CONE_SHAPE_H #define CGAL_SHAPE_DETECTION_3_CONE_SHAPE_H #include "Shape_base.h" #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif /*! \file Cone_shape.h */ namespace CGAL { /*! \brief Cone_shape implements Shape_base. The cone is parameterized by its apex, the axis and the opening angle. This representation models an infinite single-cone and does not consider a base plane. */ template class Cone_shape : public Shape_base { public: /// \cond SKIP_IN_MANUAL typedef typename Sd_traits::Input_iterator Input_iterator; ///< random access iterator for input data. typedef typename Sd_traits::Point_pmap Point_pmap; ///< property map to access the location of an input point. typedef typename Sd_traits::Normal_pmap Normal_pmap; ///< property map to access the unoriented normal of an input point. /// \endcond typedef typename Sd_traits::Geom_traits::FT FT; ///< number type. typedef typename Sd_traits::Geom_traits::Point_3 Point;///< point type. typedef typename Sd_traits::Geom_traits::Vector_3 Vector;///< vector type. Cone_shape() : Shape_base() {} /*! Opening angle between the axis and the surface of the cone. */ FT angle() const { return m_angle; } /*! The apex of the cone. */ Point apex() const { return m_apex; } /*! The axis points from the apex into the cone. */ Vector axis() const { return m_axis; } /*! Helper function to write apex, axis and angle of the cone and number of assigned points into a string. */ std::string info() const { std::stringstream sstr; sstr << "Type: cone apex: (" << m_apex.x() << ", " << m_apex.y(); sstr << ", " << m_apex.z() << ") axis: (" << m_axis.x() << ", "; sstr << m_axis.y() << ", " << m_axis.z() << ") angle:" << m_angle; sstr << " #Pts: " << this->m_indices.size(); return sstr.str(); } /*! Provides the squared Euclidean distance of the point to the shape. */ FT squared_distance(const Point &_p) const { Vector toApex = _p - m_apex; FT a = toApex.squared_length(); // projection on axis FT b = toApex * m_axis; // distance to axis FT l = sqrt(a - b * b); FT c = m_cosAng * l; FT d = m_nSinAng * b; // far on other side? return (b < 0 && c - d < 0) ? a : abs(c + d) * abs(c + d); } protected: /// \cond SKIP_IN_MANUAL virtual void create_shape(const std::vector &indices) { Point p1 = get(this->m_point_pmap, *(this->m_first + indices[0])); Point p2 = get(this->m_point_pmap, *(this->m_first + indices[1])); Point p3 = get(this->m_point_pmap, *(this->m_first + indices[2])); Vector n1 = get(this->m_normal_pmap, *(this->m_first + indices[0])); Vector n2 = get(this->m_normal_pmap, *(this->m_first + indices[1])); Vector n3 = get(this->m_normal_pmap, *(this->m_first + indices[2])); // first calculate intersection of three planes -> apex Vector lineDir = CGAL::cross_product(n1, n2); lineDir = lineDir * 1.0 / (sqrt(lineDir.squared_length())); // lineDir not normalized direction of intersection lines // of two planes (p1, n1) and (p2, n2) // get point on line by moving point p1 onto line Vector orthLineInPlane = CGAL::cross_product(n1, lineDir); orthLineInPlane = orthLineInPlane * 1.0 / (sqrt(orthLineInPlane.squared_length())); // distance of p1 to (p2, n2) FT d = (p1 - CGAL::ORIGIN) * n2 - (p2 - CGAL::ORIGIN) * n2; // projection of orthLineInPlane onto p2 FT l = orthLineInPlane * n2; Point pointOnLine = p1 - (d/l) * orthLineInPlane; // checking d = (pointOnLine - p1) * n1; // should be 0 d = (pointOnLine - p2) * n2; // should be 0 // distance of pLineDir to (p3, n3) d = (pointOnLine - CGAL::ORIGIN) * n3 - (p3 - CGAL::ORIGIN) * n3; l = lineDir * n3; m_apex = pointOnLine - (d/l) * lineDir; // checking d = (m_apex - p1) * n1; // should be 0 d = (m_apex - p2) * n2; // should be 0 d = (m_apex - p3) * n3; // should be 0 // 2. find axis Vector v1 = p1 - m_apex; v1 = v1 * 1.0 / (sqrt(v1.squared_length())); Point c1 = m_apex + v1; Vector v2 = p2 - m_apex; v2 = v2 * 1.0 / (sqrt(v2.squared_length())); Point c2 = m_apex + v2; Vector v3 = p3 - m_apex; v3 = v3 * 1.0 / (sqrt(v3.squared_length())); Point c3 = m_apex + v3; m_axis = CGAL::cross_product(c1 - c2, c1 - c3); m_axis = (orthLineInPlane * m_axis < 0) ? -m_axis : m_axis; m_axis = m_axis * 1.0 / sqrt(m_axis.squared_length()); m_angle = acos(v1 * m_axis) + acos(v2 * m_axis) + acos(v3 * m_axis); m_angle /= 3; if (m_angle < 0 || m_angle > M_PI / 2.12) return; m_nSinAng = -sin(m_angle); m_cosAng = cos(m_angle); this->m_isValid = true; } void parameters(std::vector > ¶meterSpace, const std::vector &indices, FT min[2], FT max[2]) const { Vector a = CGAL::cross_product(Vector(0, 1, 0), m_axis); if (a.squared_length() < 0.01) a = CGAL::cross_product(Vector(0, 0, 1), m_axis); a = a * 1.0 / sqrt(a.squared_length()); Vector b = CGAL::cross_product(m_axis, a); b = b * 1.0 / sqrt(b.squared_length()); } void squared_distance(std::vector &dists, const std::vector &shapeIndex, const std::vector &indices) { for (size_t i = 0;im_point_pmap, *(this->m_first + indices[i])) - m_apex; FT a = toApex.squared_length(); // projection on axis FT b = toApex * m_axis; // distance to axis FT l = sqrt(a - b * b); FT c = m_cosAng * l; FT d = m_nSinAng * b; // far on other side? dists[i] = (b < 0 && c - d < 0) ? a : abs(c + d) * abs(c + d); if (dists[i] > 0.01) { int asd; asd = 2; } } } } void cos_to_normal(std::vector &angles, const std::vector &shapeIndex, const std::vector &indices) const { for (size_t i = 0;im_point_pmap, *(this->m_first + indices[i])) - m_apex; Vector b = CGAL::cross_product(m_axis, CGAL::cross_product(m_axis, a)); b = (a * b < 0) ? -b : b; b = b * 1.0 / sqrt(b.squared_length()); b = m_cosAng * b + m_nSinAng * m_axis; angles[i] = abs(get(this->m_normal_pmap, *(this->m_first + indices[i])) * b); } } } FT cos_to_normal(const Point &_p, const Vector &_n) const { // construct vector orthogonal to axis in direction of the point Vector a = _p - m_apex; Vector b = CGAL::cross_product(m_axis, CGAL::cross_product(m_axis, a)); b = (a * b < 0) ? -b : b; b = b * 1.0 / sqrt(b.squared_length()); b = m_cosAng * b + m_nSinAng * m_axis; return abs(_n * b); } virtual size_t required_samples() const { return 3; } virtual bool supports_connected_component() const { return false; } // U is longitude virtual bool wraps_u() const { return true; } // V is between caps virtual bool wraps_v() const { return false; } private: FT m_angle; Point m_apex; Vector m_axis; Point m_pointOnPrimitive; FT m_nSinAng, m_cosAng; /// \endcond }; } #endif