// Copyright (c) 2019 CNRS and LIRIS' Establishments (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$ // SPDX-License-Identifier: GPL-3.0+ // // Author(s) : Guillaume Damiand // #ifndef CGAL_POLYGONAL_SCHEMA_H #define CGAL_POLYGONAL_SCHEMA_H 1 #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { namespace Surface_mesh_topology { namespace internal { /// @return opposite label of label s /// (i.e. add/remove - depending if s is positive or negative) inline std::string opposite_label(const std::string & s) { CGAL_assertion(!s.empty()); if (s[0]=='-') { return s.substr(1, std::string::npos); } return std::string("-")+s; } template struct Polygonal_schema_tools {}; template struct Polygonal_schema_tools { typedef typename CMap::Dart_handle Dart_handle; static Dart_handle add_edge_to_face(CMap& cmap, const std::string& s, Dart_handle prev_dart, Dart_handle dart_same_label, Dart_handle dart_opposite_label, std::unordered_map& edge_label_to_dart) { if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(prev_dart, res); } if (dart_opposite_label!=nullptr) { cmap.template link_beta<2>(res, dart_opposite_label); } return res; } std::string get_label(CMap& cmap, Dart_handle dh) const { CGAL_assertion(cmap.info(dh).m_label!=nullptr); return std::string(cmap.info(dh).m_label); } }; template struct Polygonal_schema_tools { typedef typename GMap::Dart_handle Dart_handle; // In a GMap, if an edge is 2-free, only one of its two dart has one label. // Otherwise, d has one label and alpha<0,2>(d) the opposite label. static Dart_handle add_edge_to_face(GMap& gmap, const std::string& s, Dart_handle prev_dart, Dart_handle dart_same_label, Dart_handle dart_opposite_label, std::unordered_map& edge_label_to_dart) { if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(res, dh2); if (prev_dart!=gmap.null_handle) { gmap.template link_alpha<1>(res, gmap.template alpha<0>(prev_dart)); } if (dart_same_label!=nullptr) { // Here dart_same_label!=nullptr std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=dh2; gmap.info(dh2).m_label=new char[s2.size()+1]; strncpy(gmap.info(dh2).m_label, s2.c_str(), s2.size()+1); // +1 to copy also the \0 char gmap.template sew<2>(res, dart_same_label); } else { // Here either dart_opposite_label!=nullptr, or both are nullptr edge_label_to_dart[s]=res; gmap.info(res).m_label=new char[s.size()+1]; strncpy(gmap.info(res).m_label, s.c_str(), s.size()+1); // +1 to copy also the \0 char if (dart_opposite_label!=nullptr) { std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=res; gmap.info(res).m_label=new char[s2.size()+1]; strncpy(gmap.info(res).m_label, s2.c_str(), s2.size()+1); // +1 to copy also the \0 char gmap.template sew<2>(dh2, dart_opposite_label); } } return res; } std::string get_label(GMap& gmap, Dart_handle dh) const { char* label=gmap.info(dh).m_label; if (label==nullptr) { if (!gmap.is_free<2>(dh)) { label=gmap.info(gmap.template alpha<2>(dh)).m_label; } else { return internal::opposite_label (std::string(gmap.info(gmap.template alpha<0>(dh)))); } } CGAL_assertion(label!=nullptr); return std::string(label); } }; } // end namespace internal struct Combinatorial_map_tag; struct Generalized_map_tag; template < class BaseModel > class Polygonal_schema_base: public BaseModel { public: typedef BaseModel Base; typedef BaseModel Map; // Either a GMap or a CMap typedef typename Map::Dart_handle Dart_handle; typedef typename Map::Dart_const_handle Dart_const_handle; typedef typename Map::size_type size_type; Polygonal_schema_base() : Base(), first_dart(this->null_handle), prev_dart(this->null_handle), facet_started(false) {} ~Polygonal_schema_base() { for (auto it=this->darts().begin(), itend=this->darts().end(); it!=itend; ++it) { if (this->info(it).m_label!=nullptr) { delete []this->info(it).m_label; this->info(it).m_label=nullptr; } } } /// Start a new facet. void begin_facet() { if (facet_started) { std::cerr<<"Polygonal_schema ERROR: " <<"you try to start a facet" <<" but the previous facet is not yet ended."<null_handle; prev_dart = this->null_handle; facet_started=true; } /// Add one edge to the current facet, given by its label (any string, using minus sign for orientation) void add_edge_to_facet(const std::string& s) { if (!facet_started) { std::cerr<<"Polygonal_schema ERROR: " <<"you try to add an edge to a facet" <<" but the facet is not yet started."<:: add_edge_to_face(*this, s, prev_dart, dart_same_label, dart_opposite_label, edge_label_to_dart); if (prev_dart==this->null_handle) { first_dart=cur; } prev_dart=cur; } /// add the given edges to the current facet /// s is a sequence of labels, add all the corresponding edges into the current facet. void add_edges_to_facet(const std::string& s) { if (!facet_started) { std::cerr<<"Polygonal_schema ERROR: " <<"you try to add edges to a facet" <<" but the facet is not yet started."< l) { if (!facet_started) { std::cerr<<"Polygonal_schema ERROR: " <<"you try to add edges to a facet" <<" but the facet is not yet started."< l) { if (facet_started) { std::cerr<<"Polygonal_schema ERROR: " <<"you try to add a new facet" <<" but the previous facet is not yet ended."<null_handle && prev_dart!=this->null_handle ); this->set_next(prev_dart, first_dart); facet_started=false; return first_dart; } /// @return dart with the given label, nullptr if this dart does not exist. Dart_handle get_dart_labeled(const std::string & s) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) { return nullptr; } return ite->second; } std::string get_label(Dart_handle dh) const { return internal::Polygonal_schema_tools::get_label(dh); } protected: // For each edge label, its corresponding dart. Stores both association a -a, to allow // users to start to add either a or -a. std::unordered_map edge_label_to_dart; Dart_handle first_dart; Dart_handle prev_dart; bool facet_started; }; template > class Polygonal_schema_with_combinatorial_map: public Polygonal_schema_base, Items_, Alloc_, Storage_> > { public: typedef Polygonal_schema_with_combinatorial_map Self; typedef Combinatorial_map_base<2, Self, Items_, Alloc_, Storage_> CMap_base; typedef Polygonal_schema_base Base; typedef typename Base::Dart_handle Dart_handle; typedef typename Base::Dart_const_handle Dart_const_handle; Polygonal_schema_with_combinatorial_map() : Base() {} Polygonal_schema_with_combinatorial_map(const Self & amap) : Base(amap) {} template Polygonal_schema_with_combinatorial_map(const Combinatorial_map_base& amap) : Base(amap) {} template Polygonal_schema_with_combinatorial_map(const Combinatorial_map_base& amap, const Converters& converters) : Base(amap, converters) {} template Polygonal_schema_with_combinatorial_map(const Combinatorial_map_base& amap, const Converters& converters, const DartInfoConverter& dartinfoconverter) : Base(amap, converters, dartinfoconverter) {} template Polygonal_schema_with_combinatorial_map(const Combinatorial_map_base& amap, const Converters& converters, const DartInfoConverter& dartinfoconverter, const PointConverter& pointconverter) : Base(amap, converters, dartinfoconverter, pointconverter) {} }; template > class Polygonal_schema_with_generalized_map: public Polygonal_schema_base, Items_, Alloc_, Storage_> > { public: typedef Polygonal_schema_with_generalized_map Self; typedef Generalized_map_base<2, Self, Items_, Alloc_, Storage_> GMap_base; typedef Polygonal_schema_base Base; typedef typename Base::Dart_handle Dart_handle; typedef typename Base::Dart_const_handle Dart_const_handle; Polygonal_schema_with_generalized_map() : Base() {} Polygonal_schema_with_generalized_map(const Self & amap) : Base(amap) {} template Polygonal_schema_with_generalized_map(const Generalized_map_base& amap) : Base(amap) {} template Polygonal_schema_with_generalized_map(const Generalized_map_base& amap, const Converters& converters) : Base(amap, converters) {} template Polygonal_schema_with_generalized_map(const Generalized_map_base& amap, const Converters& converters, const DartInfoConverter& dartinfoconverter) : Base(amap, converters, dartinfoconverter) {} template Polygonal_schema_with_generalized_map(const Generalized_map_base& amap, const Converters& converters, const DartInfoConverter& dartinfoconverter, const PointConverter& pointconverter) : Base(amap, converters, dartinfoconverter, pointconverter) {} }; } //namespace Surface_mesh_topology } //namespace CGAL #endif // CGAL_POLYGONAL_SCHEMA_H // // EOF //