// 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 Polygonal_schema_base Self; 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(), mark_perforated(this->get_new_mark()), 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 all the given edges to the current facet. /// @param s the sequence of labels of edges to add. 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); } /// marks the whole facet containing dh as perforated /// @return the number of darts of the marked face size_type perforate_facet(Dart_handle dh) { if (this->is_marked(dh, mark_perforated)) { return 0; } return this->template mark_cell<2>(dh, mark_perforated); } /// same method but using a label size_type perforate_facet(const std::string& s) { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) {// maybe there is no need to put an error message std::cerr<<"Polygonal_schema ERROR: " <<"you try to label "<second); } /// unmark the facet as being perforated, now the facet is filled /// @return the number of darts of the unmarked face size_type fill_facet(Dart_handle dh) { if (!this->is_marked(dh, mark_perforated)) { return 0; } return this->template unmark_cell<2>(dh, mark_perforated); } /// same fonciton but using a label size_type fill_facet(const std::string& s) { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) {// maybe there is no need to put an error message std::cerr<<"Polygonal_schema ERROR: " <<"you try to label "<second); } /// @return true iff dh is on a perforated facet bool is_perforated(Dart_const_handle dh) const { return this->is_marked(dh, mark_perforated); } /// same thing but using a label instead of a dart bool is_perforated(const std::string& s) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) {// maybe there is no need to put an error message std::cerr<<"Polygonal_schema ERROR: " <<"you ask if label "<second); } using Base::is_free; /// same thing but using a label instead of a dart template bool is_free(const std::string& s) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) {// maybe there is no need to put an error message std::cerr<<"Polygonal_schema ERROR: " <<"you ask if label "<(ite->second); } /// Non templated versions bool is_free(const std::string& s, unsigned int i) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) {// maybe there is no need to put an error message std::cerr<<"Polygonal_schema ERROR: " <<"you ask if label "<second, i); } void display_perforated_darts() const { std::cout<<"labels is_free<2> is_perforated"<first<<" "<(it->second) <<" "<second)< edge_label_to_dart; std::size_t mark_perforated; // mark for perforated facets. // Data members used when we create a facet. 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 //