// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.2/Nef_S2/include/CGAL/Nef_S2/SM_io_parser.h $ // $Id: SM_io_parser.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Michael Seel // Peter Hachenberger #ifndef CGAL_SM_IO_PARSER_H #define CGAL_SM_IO_PARSER_H #include #include #include #include #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4355) // complaint about using 'this' to #endif // initialize a member namespace CGAL { /*{\Moptions outfile=SM_io_parser.man }*/ /*{\Manpage {SM_io_parser}{Decorator_}{IO of embedded maps}{IO}}*/ /*{\Mdefinition An instance |\Mvar| of the data type |\Mname| is a decorator to provide input and output of a embedded map. |\Mtype| is generic with respect to the |Decorator_| parameter. |Decorator_| has to be a decorator model of our |SM_decorator| concept.}*/ /*{\Mgeneralization SM_decorator}*/ template class SM_io_parser : public Decorator_ { typedef Decorator_ Base; typedef typename Decorator_::Sphere_point Sphere_point; typedef typename Decorator_::Sphere_circle Sphere_circle; typedef typename Decorator_::Mark Mark; typedef typename Decorator_::Decorator_traits Decorator_traits; typedef typename Decorator_traits::SVertex_iterator SVertex_iterator; typedef typename Decorator_traits::SHalfedge_iterator SHalfedge_iterator; typedef typename Decorator_traits::SFace_iterator SFace_iterator; typedef typename Decorator_traits::SVertex_handle SVertex_handle; typedef typename Decorator_traits::SVertex_const_handle SVertex_const_handle; typedef typename Decorator_traits::SHalfedge_handle SHalfedge_handle; typedef typename Decorator_traits::SHalfedge_const_handle SHalfedge_const_handle; typedef typename Decorator_traits::SFace_const_handle SFace_const_handle; typedef typename Decorator_traits::SFace_handle SFace_handle; typedef typename Decorator_traits::SHalfloop_handle SHalfloop_handle; typedef typename Decorator_traits::SHalfloop_const_handle SHalfloop_const_handle; typedef typename Decorator_traits::SFace_cycle_iterator SFace_cycle_iterator; typedef typename Decorator_traits::SHalfedge_around_svertex_circulator SHalfedge_around_svertex_circulator; using Base::is_isolated; using Base::first_out_edge; using Base::out_edges; std::istream& in; std::ostream& out; bool verbose; // a reference to the IO object CGAL::Object_index VI; CGAL::Object_index EI; CGAL::Object_index FI; std::vector SVertex_of; std::vector Edge_of; std::vector SFace_of; SHalfloop_handle Loop_of[2]; // object mapping for input std::size_t vn,en,ln,fn,i; // the number of objects bool check_sep(const char* sep); void print_vertex(SVertex_handle) const; void print_edge(SHalfedge_handle) const; void print_loop(SHalfloop_const_handle) const; void print_face(SFace_handle) const; bool read_vertex(SVertex_handle); bool read_edge(SHalfedge_handle); bool read_loop(SHalfloop_handle); bool read_face(SFace_handle); void debug_vertex(SVertex_handle) const; void debug_edge(SHalfedge_handle) const; void debug_loop(SHalfloop_const_handle) const; public: /*{\Mcreation 3}*/ SM_io_parser(std::istream& is, const Base& D); /*{\Mcreate creates an instance |\Mvar| of type |\Mname| to input |H| from |is|.}*/ SM_io_parser(std::ostream& os, const Base& D); /*{\Mcreate creates an instance |\Mvar| of type |\Mname| to output |H| to |os|.}*/ /*{\Moperations 2 3}*/ void print() const; /*{\Mop prints |H| to |os|.}*/ void read(); /*{\Mop reads |H| from |is|.}*/ void debug() const; void print_faces() const; std::string index(SVertex_const_handle v) const { return VI(v,verbose); } std::string index(SHalfedge_const_handle e) const { return EI(e,verbose); } std::string index(SHalfloop_const_handle l) const { if (verbose) return (l==this->shalfloop()? "l0" : "l1"); else return (l==this->shalfloop()? "0" : "1"); } std::string index(SFace_const_handle f) const { return FI(f,verbose); } static void dump(const Decorator_& D, std::ostream& os = std::cerr); /*{\Mstatic prints the plane map decorated by |D| to |os|.}*/ }; // SM_io_parser template SM_io_parser:: SM_io_parser(std::istream& iin, const Base& H) : Base(H), in(iin), out(std::cout), verbose(0), vn(0), en(0), ln(0), fn(0) { this->clear(); } template SM_io_parser:: SM_io_parser(std::ostream& iout, const Base& D) : Base(D), in(std::cin), out(iout), VI(this->svertices_begin(),this->svertices_end(),'v'), EI(this->shalfedges_begin(),this->shalfedges_end(),'e'), FI(this->sfaces_begin(),this->sfaces_end(),'f'), vn(this->number_of_svertices()), en(this->number_of_shalfedges()), ln(this->number_of_shalfloops()), fn(this->number_of_sfaces()) { verbose = (get_mode(out) != CGAL::IO::ASCII && get_mode(out) != CGAL::IO::BINARY); } //----------------------------------------------------------------------------- // OUTPUT AND INPUT: //----------------------------------------------------------------------------- template bool SM_io_parser::check_sep(const char* sep) { char c; do in.get(c); while (isspace(c)); while (*sep != '\0') { if (*sep != c) { in.putback(c); return false; } ++sep; in.get(c); } in.putback(c); return true; } template void SM_io_parser::print_vertex(SVertex_handle v) const { // syntax: index { isolated incident_object, mark, point } out << index(v) << " { "; if ( is_isolated(v) ) out << "1 " << index(v->incident_sface()); else out << "0 " << index(first_out_edge(v)); out << ", " << v->mark() << ", " << v->point() << "}\n"; } template bool SM_io_parser::read_vertex(SVertex_handle v) { // precondition: nodes exist // syntax: index { isolated incident_object, mark, point} int n; bool iso; int f; Mark m; Sphere_point p; if ( !(in >> n) || !check_sep("{") || !(in >> iso) || !(in >> f) || !check_sep(",") || !(in >> m) || !check_sep(",") || !(in >> p) || !check_sep("}") ) return false; if(f<0 || (iso && f > fn) || (!iso && f > en)) { in.setstate(std::ios_base::badbit); return false; } if (iso) this->set_face(v,SFace_of[f]); else this->set_first_out_edge(v,Edge_of[f]); v->mark() = m; v->point() = p; return true; } template void SM_io_parser::print_edge(SHalfedge_handle e) const { // syntax: index { twin, prev, next, source, face, mark, circle } Decorator_ D; out << index(e) << " { " << index(e->twin()) << ", " << index(e->sprev()) << ", " << index(e->snext()) << ", " << index(e->source()) << ", " << index(e->incident_sface()) << ", " << e->mark() << ", " << e->circle() << " }\n"; } template bool SM_io_parser::read_edge(SHalfedge_handle e) { // syntax: index { twin, prev, next, source, face, mark, circle } int n, eo, epr, ene, v, f; bool m; Sphere_circle k; if ( !(in >> n) || !check_sep("{") || !(in >> eo) || !check_sep(",") || !(in >> epr) || !check_sep(",") || !(in >> ene) || !check_sep(",") || !(in >> v) || !check_sep(",") || !(in >> f) || !check_sep(",") || !(in >> m) || !check_sep(",") || !(in >> k) || !check_sep("}") ) return false; if (! (eo >= 0 && eo < en && epr >= 0 && epr < en && ene >= 0 && ene < en && v >= 0 && v < vn && f >= 0 && f < fn )) { std::cerr<<"wrong index in read_edge"<twin()]); this->set_prev(e,Edge_of[epr]); this->set_next(e,Edge_of[ene]); this->set_source(e,SVertex_of[v]); this->set_face(e,SFace_of[f]); e->mark() = m; e->circle() = k; return true; } template void SM_io_parser::print_loop(SHalfloop_const_handle l) const { // syntax: index { twin, face, mark, circle } out << index(l) << " { " << index(l->twin()) << ", " << index(l->incident_sface()) << ", " << l->mark() << ", " << l->circle() << " }\n"; } template bool SM_io_parser::read_loop(SHalfloop_handle l) { // syntax: index { twin, face, mark, circle } int n, lo, f; bool m; Sphere_circle k; if ( !(in >> n) || !check_sep("{") || !(in >> lo) || !check_sep(",") || !(in >> f) || !check_sep(",") || !(in >> m) || !check_sep(",") || !(in >> k) || !check_sep("}") ) return false; CGAL_assertion_msg( (lo >= 0 && lo < 2 && f >= 0 && f < fn),"wrong index in read_edge"); this->set_face(l,SFace_of[f]); l->mark() = m; l->circle() = k; return true; } template void SM_io_parser::print_face(SFace_handle f) const { // syntax: index { fclist, ivlist, loop, mark } out << index(f) << " { "; SFace_cycle_iterator it; CGAL_forall_sface_cycles_of(it,f) if ( it.is_shalfedge() ) out << index(SHalfedge_handle(it)) << ' '; out << ", "; CGAL_forall_sface_cycles_of(it,f) if ( it.is_svertex() ) out << index(SVertex_handle(it)) << ' '; out << ", "; CGAL_forall_sface_cycles_of(it,f) if ( it.is_shalfloop() ) out << index(SHalfloop_handle(it)); out << ", " << f->mark() << " }\n"; } template bool SM_io_parser::read_face(SFace_handle f) { // syntax: index { fclist, ivlist, loop, mark } int n, ei, vi, li; Mark m; if ( !(in >> n) || !check_sep("{") ) return false; while (in >> ei) { if(!(ei >= 0 && ei < en)) { std::cerr<<"wrong index in face cycle list."<store_sm_boundary_object(Edge_of[ei],f); } in.clear(); if (!check_sep(",")) { return false; } while (in >> vi) { if(!(vi >= 0 && vi < vn)) { std::cerr<<"wrong index in iso vertex list."<store_sm_boundary_object(SVertex_of[vi],f); } in.clear(); if (!check_sep(",")) { return false; } while (in >> li) { if(!(li >= 0 && li < 2)) { std::cerr<<"wrong index in iso vertex list."<store_sm_boundary_object(Loop_of[li],f); } in.clear(); if (!check_sep(",") || !(in >> m) || !check_sep("}") ) return false; f->mark() = m; return true; } template void SM_io_parser::print() const { out << "Sphere_map_2" << std::endl; out << "vertices " << vn << std::endl; out << "edges " << en << std::endl; out << "loops " << ln << std::endl; out << "faces " << fn << std::endl; if (verbose) out << "/* index { isolated ? face : edge, mark, point } */" << std::endl; SVertex_iterator vit; CGAL_forall_svertices(vit,*this) print_vertex(vit); if (verbose) out << "/* index { twin, prev, next, source, face, mark, circle } */" << std::endl; SHalfedge_iterator eit; CGAL_forall_shalfedges(eit,*this) print_edge(eit); if (verbose) out << "/* index { twin, face, mark, circle } */" << std::endl; if ( this->has_shalfloop() ) { print_loop(this->shalfloop()); print_loop(this->shalfloop()->twin()); } if (verbose) out << "/* index { fclist, ivlist, loop, mark } */" << std::endl; SFace_iterator fit; CGAL_forall_sfaces(fit,*this) print_face(fit); out.flush(); if (verbose) debug(); } template void SM_io_parser::read() { if ( !check_sep("Nef_polyhedron_S2") ) { CGAL_warning_msg(false, "Missing line in header"); return; } if ( !check_sep("Sphere_map_2") ) { CGAL_warning_msg(false, "SM_io_parser::read: no embedded_PM header."); return; } if ( !(check_sep("vertices") && (in >> vn)) ) { CGAL_warning_msg(false, "SM_io_parser::read: wrong vertex line."); return; } if ( !(check_sep("edges") && (in >> en) && (en%2==0)) ) { CGAL_warning_msg(false, "SM_io_parser::read: wrong edge line."); return; } if ( !(check_sep("loops") && (in >> ln)) ) { CGAL_warning_msg(false, "SM_io_parser::read: wrong loop line."); return; } if ( !(check_sep("faces") && (in >> fn)) ) { CGAL_warning_msg(false, "SM_io_parser::read: wrong face line."); return; } SVertex_of.resize(vn); Edge_of.resize(en); SFace_of.resize(fn); for(i=0; inew_svertex(); for(i=0; inew_shalfedge_pair(); else Edge_of[i] = Edge_of[i-1]->twin(); for(i=0; inew_sface(); if ( ln == 2 ) { Loop_of[0] = this->new_shalfloop_pair(); Loop_of[1] = this->shalfloop()->twin(); } for(i=0; i void SM_io_parser::debug_vertex(SVertex_handle v) const { out << index(v) << "[" << v->mark() << "," << v->point() << "]" << std::endl; } template void SM_io_parser::debug_edge(SHalfedge_handle e) const { out << index(e) << "(" << index(e->source()) << "," << index(e->target()) << ") " << index(e->twin()) << " " << index(e->incident_sface()) << " ["<< e->mark() << "," << e->circle() << "] " << std::endl; } template void SM_io_parser::debug_loop(SHalfloop_const_handle l) const { out << index(l) << " " << index(l->twin()) << " " << index(l->incident_sface()) << " ["<< l->mark() << "] " << l->circle() << std::endl; } template void SM_io_parser::debug() const { out << "\nDEBUG Plane_map\n"; out << "Vertices: " << this->number_of_svertices() << "\n"; out << "SHalfedges: " << this->number_of_shalfedges() << "\n"; out << "Loop: " << this->number_of_shalfloops() << "\n"; SVertex_iterator vit; CGAL_forall_svertices(vit,*this) { if ( is_isolated(vit) ) continue; SHalfedge_around_svertex_circulator hcirc(out_edges(vit)), hend(hcirc); debug_vertex(vit); CGAL_For_all(hcirc,hend) { out << " "; debug_edge(hcirc); } } if ( this->has_shalfloop() ) { debug_loop(this->shalfloop()); debug_loop(this->shalfloop()->twin()); } out << std::endl; } template void SM_io_parser::print_faces() const { out << "\nFACES\n"; out << "Vertices: " << this->number_of_svertices() << "\n"; out << "SHalfedges: " << this->number_of_shalfedges() << "\n"; out << "Loop: " << this->number_of_shalfloops() << "\n"; SHalfedge_iterator e; Unique_hash_map Done(false); CGAL_forall_shalfedges(e,*this) { if ( Done[e] ) continue; typename Base::SHalfedge_around_sface_circulator c(e), ce = c; out << "face cycle\n"; CGAL_For_all(c,ce) { Done[c]=true; out << " "; debug_vertex(c->source()); } } if ( this->has_shalfloop() ) { debug_loop(this->shalfloop()); debug_loop(this->shalfloop()->twin()); } out << std::endl; } template void SM_io_parser::dump(const Decorator_& D, std::ostream& os) { SM_io_parser Out(os,D); Out.print(); Out.print_faces(); } } //namespace CGAL #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif //CGAL_SM_IO_PARSER_H