// Copyright (c) 2007-2016 INRIA (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // You can redistribute it and/or modify it under the terms of the GNU // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Laurent Saboret, Nader Salman, Gael Guennebaud #ifndef CGAL_POINT_SET_3_H #define CGAL_POINT_SET_3_H #include #include #include #include #include #include #include # include /// The Point_set_3 class is array of points + normals of type /// Point_with_normal_3 (in fact /// UI_point_3 to support a selection flag and an optional radius). /// It provides: /// - accessors: points and normals iterators, property maps /// - OpenGL rendering /// - bounding box /// /// CAUTION: /// - User is responsible to call invalidate_bounds() after adding, moving or removing points. /// - Selecting points changes the order of the points in the /// container. If selection is *not* empty, it becomes invalid after /// adding, moving or removing points, user is reponsible to call /// unselect_all() in those cases. /// /// @heading Parameters: /// @param Gt Geometric traits class. namespace CGAL { template class Point_set_3 { public: typedef Point_set_3 Point_set; typedef typename Gt::FT FT; typedef typename Gt::Point_3 Point; typedef typename Gt::Vector_3 Vector; typedef typename Gt::Iso_cuboid_3 Iso_cuboid; typedef typename Gt::Sphere_3 Sphere; typedef typename std::size_t Item; typedef typename Properties::Property_container Base; typedef typename Properties::Property_map Index_pmap; typedef typename Properties::Property_map Point_pmap; typedef typename Properties::Property_map Vector_pmap; typedef typename Index_pmap::Array::vector_type::iterator iterator; typedef typename Index_pmap::Array::vector_type::const_iterator const_iterator; private: struct Index_back_inserter { typedef std::output_iterator_tag iterator_category; typedef std::size_t value_type; typedef std::ptrdiff_t difference_type; typedef void pointer; typedef void reference; private: Point_set& ps; std::size_t ind; public: Index_back_inserter(Point_set& ps, std::size_t ind=0) : ps(ps), ind(ind) {} Index_back_inserter& operator++() { return *this; } Index_back_inserter& operator++(int) { return *this; } Index_back_inserter& operator*() { return *this; } Index_back_inserter& operator= (std::size_t& ind) { if(ps.size() <= (typename Point_set::Item(ind))) ps.add_item(); put(ps.indices(), Point_set::Item(ind),ind); ++ ind; return *this; } }; template struct Property_push_pmap { Point_set& ps; Property& prop; std::size_t ind; Property_push_pmap(Point_set& ps, Property& prop, std::size_t ind=0) : ps(ps), prop(prop), ind(ind) {} inline friend void put(Property_push_pmap& pm, std::size_t& i, typename Property::value_type& t) { if(pm.ps.size() <= (pm.ind)) pm.ps.add_item(); put(pm.prop, Point_set::Item(pm.ind), t); i = pm.ind; ++pm.ind; } }; typedef Property_push_pmap Point_push_pmap; typedef Property_push_pmap Normal_push_pmap; Base m_base; Point_pmap m_points; Index_pmap m_indices; Vector_pmap m_normals; // Assignment operator not implemented and declared private to make // sure nobody uses the default one without knowing it Point_set_3& operator= (const Point_set_3&) { return *this; } // Copy constructor not implemented and declared private to make // sure nobody uses the default one without knowing it Point_set_3 (const Point_set_3& p) { } public: Point_set_3 () : m_base() { m_indices = m_base.template add ("index").first; m_points = m_base.template add ("point").first; } void push_back (const Point& p) { Item i = m_base.push_back(); m_points[i] = p; } Index_pmap& indices() { return m_indices; } Point_pmap& points() { return m_points; } Vector_pmap& normals() { return m_normals; } iterator begin() { return m_indices.array().begin(); } iterator end() { return m_indices.array().end(); } const_iterator begin() const { return m_indices.array().begin(); } const_iterator end() const { return m_indices.array().end(); } bool empty() const { return (m_base.size() == 0); } std::size_t size () const { return m_base.size(); } void clear() { m_base.clear(); } Point& operator[] (Item index) { return m_points[index]; } const Point& operator[] (Item index) const { return (*this)[index]; } void erase (iterator first, iterator beyond) { if (beyond != end()) { // TODO } if (are_indices_up_to_date()) { m_base.erase (*first, *beyond); } else { std::size_t size = (beyond - first); apply_indices_change(); m_base.resize (m_base.size() - size); } } void add_item () { m_base.push_back(); } void apply_indices_change() { for (std::size_t i = 0; i < size(); ++ i) if (i != m_indices[i]) m_base.swap (i, m_indices[i]); } void reset_indices() { std::size_t i = 0; for (iterator it = begin(); it != end(); ++ it, ++ i) *it = i; } bool are_indices_up_to_date() { std::size_t i = 0; for (iterator it = begin(); it != end(); ++ it, ++ i) if (*it != i) return false; return true; } Index_back_inserter index_back_inserter () { return Index_back_inserter (*this, size()); } Point_push_pmap point_push_pmap () { return Property_push_pmap (*this, m_points, size()); } Normal_push_pmap normal_push_pmap () { return Property_push_pmap (*this, m_normals, size()); } bool has_normals() const { std::pair pm = m_base.template get ("normal"); return pm.second; } bool add_normal_property() { bool out = false; boost::tie (m_normals, out) = m_base.template add ("normal"); return out; } void remove_normal_property() { m_base.remove (m_normals); } Vector& normal (Item index) { return m_normals[index]; } const Vector& normal (Item index) const { return this->normal(index); } template bool has_property (const std::string& name) const { std::pair, bool> pm = m_base.template get (name); return pm.second; } template bool add_property (const std::string& name) { std::pair, bool> pm = m_base.template add (name); return pm.second; } template void remove_property (PMap& prop) { m_base.remove (prop); } template bool remove_property (const std::string& name) { std::pair, bool> pm = m_base.template get (name); if (!(pm.second)) return false; remove_property (pm.first); return true; } template T& property (typename Properties::template Property_map& pmap, std::size_t index) { return pmap[index]; } template const T& property (typename Properties::template Property_map& pmap, std::size_t index) const { return property (pmap, index); } template T& property (const std::string& name, std::size_t index) { std::pair, bool> pm = m_base.template get (name); return property (pm.first, index); } template const T& property (const std::string& name, std::size_t index) const { return property (name, index); } }; // end of class Point_set_3 } // namespace CGAL #endif // CGAL_POINT_SET_3_H