mirror of https://github.com/CGAL/cgal
493 lines
16 KiB
C++
493 lines
16 KiB
C++
// Copyright (c) 1997-2002 Max-Planck-Institute Saarbruecken (Germany).
|
|
// 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) : Michael Seel <seel@mpi-sb.mpg.de>
|
|
// Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
|
|
|
|
#ifndef CGAL_SM_IO_PARSER_H
|
|
#define CGAL_SM_IO_PARSER_H
|
|
|
|
#include <CGAL/Nef_S2/SM_decorator.h>
|
|
#include <CGAL/Nef_2/Object_index.h>
|
|
#include <CGAL/Nef_S2/SM_decorator_traits.h>
|
|
#include <vector>
|
|
#include <iostream>
|
|
|
|
#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 <typename Decorator_>
|
|
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<SVertex_const_handle> VI;
|
|
CGAL::Object_index<SHalfedge_const_handle> EI;
|
|
CGAL::Object_index<SFace_const_handle> FI;
|
|
std::vector<SVertex_handle> SVertex_of;
|
|
std::vector<SHalfedge_handle> Edge_of;
|
|
std::vector<SFace_handle> 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<Decorator_>
|
|
|
|
|
|
template <typename Decorator_>
|
|
SM_io_parser<Decorator_>::
|
|
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 <typename Decorator_>
|
|
SM_io_parser<Decorator_>::
|
|
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 <typename Decorator_>
|
|
bool SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
bool SM_io_parser<Decorator_>::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 (iso) set_face(v,SFace_of[f]);
|
|
else set_first_out_edge(v,Edge_of[f]);
|
|
v->mark() = m; v->point() = p;
|
|
return true;
|
|
}
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
bool SM_io_parser<Decorator_>::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;
|
|
CGAL_assertion_msg
|
|
(eo >= 0 && eo < en && epr >= 0 && epr < en && ene >= 0 && ene < en &&
|
|
v >= 0 && v < vn && f >= 0 && f < fn ,
|
|
"wrong index in read_edge");
|
|
|
|
// precond: features exist!
|
|
CGAL_assertion(EI[e->twin()]);
|
|
set_prev(e,Edge_of[epr]);
|
|
set_next(e,Edge_of[ene]);
|
|
set_source(e,SVertex_of[v]);
|
|
set_face(e,SFace_of[f]);
|
|
e->mark() = m;
|
|
e->circle() = k;
|
|
return true;
|
|
}
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
bool SM_io_parser<Decorator_>::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");
|
|
|
|
set_face(l,SFace_of[f]);
|
|
l->mark() = m;
|
|
l->circle() = k;
|
|
return true;
|
|
}
|
|
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
bool SM_io_parser<Decorator_>::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) {
|
|
CGAL_assertion_msg(ei >= 0 && ei < en,
|
|
"wrong index in face cycle list.");
|
|
store_sm_boundary_object(Edge_of[ei],f);
|
|
} in.clear();
|
|
if (!check_sep(",")) { return false; }
|
|
while (in >> vi) {
|
|
CGAL_assertion_msg(vi >= 0 && vi < vn,
|
|
"wrong index in iso vertex list.");
|
|
store_sm_boundary_object(SVertex_of[vi],f);
|
|
} in.clear();
|
|
if (!check_sep(",")) { return false; }
|
|
while (in >> li) {
|
|
CGAL_assertion_msg(li >= 0 && li < 2,
|
|
"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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::read()
|
|
{
|
|
if ( !check_sep("Sphere_map_2") )
|
|
CGAL_error_msg("SM_io_parser::read: no embedded_PM header.");
|
|
if ( !(check_sep("vertices") && (in >> vn)) )
|
|
CGAL_error_msg("SM_io_parser::read: wrong vertex line.");
|
|
if ( !(check_sep("edges") && (in >> en) && (en%2==0)) )
|
|
CGAL_error_msg("SM_io_parser::read: wrong edge line.");
|
|
if ( !(check_sep("loops") && (in >> ln)) )
|
|
CGAL_error_msg("SM_io_parser::read: wrong loop line.");
|
|
if ( !(check_sep("faces") && (in >> fn)) )
|
|
CGAL_error_msg("SM_io_parser::read: wrong face line.");
|
|
|
|
SVertex_of.resize(vn);
|
|
Edge_of.resize(en);
|
|
SFace_of.resize(fn);
|
|
for(i=0; i<vn; i++) SVertex_of[i] = this->new_svertex();
|
|
for(i=0; i<en; i++)
|
|
if (i%2==0) Edge_of[i] = this->new_shalfedge_pair();
|
|
else Edge_of[i] = Edge_of[i-1]->twin();
|
|
for(i=0; i<fn; i++) SFace_of[i] = this->new_sface();
|
|
if ( ln == 2 ) {
|
|
Loop_of[0] = this->new_shalfloop_pair();
|
|
Loop_of[1] = this->shalfloop()->twin();
|
|
}
|
|
|
|
for(i=0; i<vn; i++) {
|
|
if (!read_vertex(SVertex_of[i]))
|
|
CGAL_error_msg("SM_io_parser::read: error in node line");
|
|
}
|
|
for(i=0; i<en; i++) {
|
|
if (!read_edge(Edge_of[i]))
|
|
CGAL_error_msg("SM_io_parser::read: error in edge line");
|
|
}
|
|
if ( ln == 2 ) {
|
|
read_loop(Loop_of[0]); read_loop(Loop_of[1]);
|
|
}
|
|
for(i=0; i<fn; i++) {
|
|
if (!read_face(SFace_of[i]))
|
|
CGAL_error_msg("SM_io_parser::read: error in face line");
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// VERBOSE OUTPUT:
|
|
// note that we output the index of the objects which is stored in them
|
|
// this is NOT the member index as produced by the forall loops
|
|
//-----------------------------------------------------------------------------
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::debug_vertex(SVertex_handle v) const
|
|
{
|
|
out << index(v) << "[" << v->mark() << "," << v->point() << "]" << std::endl;
|
|
}
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::debug_loop(SHalfloop_const_handle l) const
|
|
{
|
|
out << index(l) << " "
|
|
<< index(l->twin()) << " " << index(l->incident_sface())
|
|
<< " ["<< l->mark() << "] " << l->circle() << std::endl;
|
|
}
|
|
|
|
|
|
template <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::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<SHalfedge_iterator,bool> 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 <typename Decorator_>
|
|
void SM_io_parser<Decorator_>::dump(const Decorator_& D, std::ostream& os)
|
|
{ SM_io_parser<Decorator_> Out(os,D);
|
|
Out.print();
|
|
Out.print_faces();
|
|
}
|
|
|
|
|
|
|
|
} //namespace CGAL
|
|
|
|
|
|
#if defined(BOOST_MSVC)
|
|
# pragma warning(pop)
|
|
#endif
|
|
|
|
#endif //CGAL_SM_IO_PARSER_H
|