348 lines
11 KiB
C
348 lines
11 KiB
C
|
// Copyright (c) 2007,2009,2010,2011 Tel-Aviv University (Israel).
|
||
|
// 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) : Ron Wein <wein@post.tau.ac.il>
|
||
|
// (based on old version by Michal Meyerovitch and Ester Ezra)
|
||
|
//
|
||
|
#ifndef CGAL_IO_ARRANGEMENT_2_WRITER_H
|
||
|
#define CGAL_IO_ARRANGEMENT_2_WRITER_H
|
||
|
|
||
|
#include <CGAL/license/Arrangement_on_surface_2.h>
|
||
|
|
||
|
|
||
|
/*! \file
|
||
|
* The header file for the Arrangement_2_writer<Arrangement> class.
|
||
|
*/
|
||
|
|
||
|
#include <CGAL/Arr_accessor.h>
|
||
|
#include <map>
|
||
|
|
||
|
namespace CGAL {
|
||
|
|
||
|
/*! \class
|
||
|
* An auxiliary class for writing an arrangement to an output stream.
|
||
|
*/
|
||
|
template <class Arrangement_>
|
||
|
class Arrangement_2_writer
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
typedef Arrangement_ Arrangement_2;
|
||
|
typedef Arrangement_2_writer<Arrangement_2> Self;
|
||
|
|
||
|
protected:
|
||
|
|
||
|
typedef typename Arrangement_2::Size Size;
|
||
|
typedef typename Arrangement_2::Dcel Dcel;
|
||
|
|
||
|
typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle;
|
||
|
typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle;
|
||
|
typedef typename Arrangement_2::Face_const_handle Face_const_handle;
|
||
|
|
||
|
typedef CGAL::Arr_accessor<Arrangement_2> Arr_accessor;
|
||
|
typedef typename Arr_accessor::Dcel_vertex_iterator Vertex_const_iterator;
|
||
|
typedef typename Arr_accessor::Dcel_edge_iterator Edge_const_iterator;
|
||
|
typedef typename Arr_accessor::Dcel_face_iterator Face_const_iterator;
|
||
|
|
||
|
typedef typename Arr_accessor::Dcel_outer_ccb_iterator
|
||
|
Outer_ccb_iterator;
|
||
|
typedef typename Arr_accessor::Dcel_inner_ccb_iterator
|
||
|
Inner_ccb_iterator;
|
||
|
typedef typename Arr_accessor::Dcel_iso_vertex_iterator
|
||
|
Isolated_vertex_iterator;
|
||
|
|
||
|
typedef typename Arr_accessor::Dcel_vertex DVertex;
|
||
|
typedef typename Arr_accessor::Dcel_halfedge DHalfedge;
|
||
|
typedef typename Arr_accessor::Dcel_face DFace;
|
||
|
typedef std::map<const DVertex*, int> Vertex_index_map;
|
||
|
typedef std::map<const DHalfedge*, int> Halfedge_index_map;
|
||
|
|
||
|
// Data memebrs:
|
||
|
const Arrangement_2& m_arr;
|
||
|
const Dcel* m_dcel;
|
||
|
int m_curr_v;
|
||
|
Vertex_index_map m_v_index;
|
||
|
int m_curr_he;
|
||
|
Halfedge_index_map m_he_index;
|
||
|
|
||
|
private:
|
||
|
|
||
|
// Copy constructor and assignment operator - not supported.
|
||
|
Arrangement_2_writer(const Self&);
|
||
|
Self& operator= (const Self&);
|
||
|
|
||
|
public:
|
||
|
|
||
|
/*! Constructor. */
|
||
|
Arrangement_2_writer(const Arrangement_2& arr) :
|
||
|
m_arr(arr),
|
||
|
m_dcel(NULL),
|
||
|
m_curr_v(0),
|
||
|
m_curr_he(0)
|
||
|
{
|
||
|
const Arr_accessor arr_access(const_cast<Arrangement_2&>(arr));
|
||
|
m_dcel = &(arr_access.dcel());
|
||
|
}
|
||
|
|
||
|
/*! Destructor. */
|
||
|
virtual ~Arrangement_2_writer()
|
||
|
{}
|
||
|
|
||
|
/*! Write the arrangement. */
|
||
|
template <class Formatter>
|
||
|
void operator()(Formatter& formatter)
|
||
|
{
|
||
|
formatter.write_arrangement_begin();
|
||
|
formatter.write_size("number_of_vertices",
|
||
|
m_dcel->size_of_vertices());
|
||
|
formatter.write_size("number_of_edges",
|
||
|
m_dcel->size_of_halfedges() / 2);
|
||
|
formatter.write_size("number_of_faces",
|
||
|
m_dcel->size_of_faces());
|
||
|
|
||
|
// Reset indices.
|
||
|
m_curr_v = 0;
|
||
|
m_curr_he = 0;
|
||
|
|
||
|
// Write the vertices.
|
||
|
formatter.write_vertices_begin();
|
||
|
Vertex_const_iterator vit;
|
||
|
for (vit = m_dcel->vertices_begin(); vit != m_dcel->vertices_end(); ++vit)
|
||
|
{
|
||
|
_write_vertex(formatter, vit);
|
||
|
}
|
||
|
formatter.write_vertices_end();
|
||
|
|
||
|
// Write the edges.
|
||
|
formatter.write_edges_begin();
|
||
|
Edge_const_iterator eit;
|
||
|
for (eit = m_dcel->edges_begin(); eit != m_dcel->edges_end(); ++eit)
|
||
|
{
|
||
|
_write_edge(formatter, eit);
|
||
|
}
|
||
|
formatter.write_edges_end();
|
||
|
|
||
|
// Write the faces (the fictitious face first).
|
||
|
formatter.write_faces_begin();
|
||
|
|
||
|
Face_const_iterator fit;
|
||
|
for (fit = m_dcel->faces_begin(); fit != m_dcel->faces_end(); ++fit)
|
||
|
_write_face(formatter, fit);
|
||
|
formatter.write_faces_end();
|
||
|
|
||
|
formatter.write_arrangement_end();
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
/*! Write a vertex. */
|
||
|
template <class Formatter>
|
||
|
void _write_vertex(Formatter& formatter, Vertex_const_iterator vit)
|
||
|
{
|
||
|
// Map the current vertex to its index.
|
||
|
const DVertex* v = &(*vit);
|
||
|
|
||
|
m_v_index[v] = m_curr_v;
|
||
|
++m_curr_v;
|
||
|
|
||
|
// Write the vertex.
|
||
|
formatter.write_vertex_begin();
|
||
|
formatter.write_vertex_index(static_cast<int>(v->parameter_space_in_x()));
|
||
|
formatter.write_vertex_index(static_cast<int>(v->parameter_space_in_y()));
|
||
|
|
||
|
if (! v->has_null_point())
|
||
|
{
|
||
|
// Write the associated point.
|
||
|
formatter.write_vertex_index(1);
|
||
|
formatter.write_point(v->point());
|
||
|
|
||
|
// Write additional user-defined data.
|
||
|
formatter.write_vertex_data(Vertex_const_handle(v));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mark that the vertex is not associated with a point.
|
||
|
formatter.write_vertex_index(0);
|
||
|
}
|
||
|
|
||
|
formatter.write_vertex_end();
|
||
|
}
|
||
|
|
||
|
/*! Write an edge (a pair of halfedges). */
|
||
|
template <class Formatter>
|
||
|
void _write_edge(Formatter& formatter, Edge_const_iterator hit)
|
||
|
{
|
||
|
// Map the halfedge and its twin to their indices.
|
||
|
const DHalfedge* he = &(*hit);
|
||
|
const DHalfedge* he_t = he->opposite();
|
||
|
|
||
|
m_he_index[&(*he)] = m_curr_he;
|
||
|
++m_curr_he;
|
||
|
m_he_index[&(*he_t)] = m_curr_he;
|
||
|
++m_curr_he;
|
||
|
|
||
|
// Write the edge.
|
||
|
formatter.write_edge_begin();
|
||
|
formatter.write_vertex_index(_index(he_t->vertex()));
|
||
|
formatter.write_vertex_index(_index(he->vertex()));
|
||
|
|
||
|
if (he->direction() == ARR_LEFT_TO_RIGHT)
|
||
|
formatter.write_vertex_index(0);
|
||
|
else
|
||
|
formatter.write_vertex_index(1);
|
||
|
|
||
|
if (! he->has_null_curve())
|
||
|
{
|
||
|
// Write the associated curve.
|
||
|
formatter.write_vertex_index(1);
|
||
|
formatter.write_x_monotone_curve(he->curve());
|
||
|
|
||
|
// Write additional user-defined data.
|
||
|
formatter.write_halfedge_data(Halfedge_const_handle(he));
|
||
|
formatter.write_halfedge_data(Halfedge_const_handle(he_t));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Mark that the edge is fictitious.
|
||
|
formatter.write_vertex_index(0);
|
||
|
}
|
||
|
formatter.write_edge_end();
|
||
|
}
|
||
|
|
||
|
/*! Write a face. */
|
||
|
template <class Formatter>
|
||
|
void _write_face(Formatter& formatter, Face_const_iterator fit) const
|
||
|
{
|
||
|
const DFace* f = &(*fit);
|
||
|
|
||
|
formatter.write_face_begin();
|
||
|
|
||
|
// Write whether the face is unbounded and whether it is valid
|
||
|
// (non-fictitious).
|
||
|
if (f->is_unbounded())
|
||
|
formatter.write_vertex_index(1);
|
||
|
else
|
||
|
formatter.write_vertex_index(0);
|
||
|
|
||
|
if (! f->is_fictitious())
|
||
|
formatter.write_vertex_index(1);
|
||
|
else
|
||
|
formatter.write_vertex_index(0);
|
||
|
|
||
|
// Write the outer CCBs of the face.
|
||
|
const std::size_t n_occbs = f->number_of_outer_ccbs();
|
||
|
Outer_ccb_iterator oc_it;
|
||
|
|
||
|
formatter.write_outer_ccbs_begin();
|
||
|
formatter.write_size("number_of_outer_ccbs", n_occbs);
|
||
|
for (oc_it = f->outer_ccbs_begin();
|
||
|
oc_it != f->outer_ccbs_end(); ++oc_it)
|
||
|
{
|
||
|
const std::size_t n = _circulator_size(*oc_it);
|
||
|
|
||
|
formatter.write_size("halfedges_on_outer_ccb", n);
|
||
|
_write_ccb(formatter, *oc_it);
|
||
|
}
|
||
|
formatter.write_inner_ccbs_end();
|
||
|
|
||
|
// Write the inner CCBs of the face.
|
||
|
const std::size_t n_iccbs = f->number_of_inner_ccbs();
|
||
|
Inner_ccb_iterator ic_it;
|
||
|
|
||
|
formatter.write_inner_ccbs_begin();
|
||
|
formatter.write_size("number_of_inner_ccbs", n_iccbs);
|
||
|
for (ic_it = f->inner_ccbs_begin(); ic_it != f->inner_ccbs_end(); ++ic_it)
|
||
|
{
|
||
|
const std::size_t n = _circulator_size(*ic_it);
|
||
|
formatter.write_size("halfedges_on_inner_ccb", n);
|
||
|
_write_ccb(formatter, *ic_it);
|
||
|
}
|
||
|
formatter.write_inner_ccbs_end();
|
||
|
|
||
|
// Write the isolated vertices inside the face.
|
||
|
std::size_t n_isolated = f->number_of_isolated_vertices();
|
||
|
formatter.write_size("number_of_isolated_vertices", n_isolated);
|
||
|
if (n_isolated) {
|
||
|
formatter.write_isolated_vertices_begin();
|
||
|
Isolated_vertex_iterator iso_vit;
|
||
|
for (iso_vit = f->isolated_vertices_begin();
|
||
|
iso_vit != f->isolated_vertices_end(); ++iso_vit)
|
||
|
formatter.write_vertex_index(_index(&(*iso_vit)));
|
||
|
formatter.write_isolated_vertices_end();
|
||
|
}
|
||
|
|
||
|
// Write additional user-defined data associated with the face.
|
||
|
if (! f->is_fictitious())
|
||
|
formatter.write_face_data(Face_const_handle(f));
|
||
|
|
||
|
formatter.write_face_end();
|
||
|
}
|
||
|
|
||
|
/*! Write the edges along a given CCB. */
|
||
|
template <class Formatter>
|
||
|
void _write_ccb(Formatter& formatter, const DHalfedge* ccb) const
|
||
|
{
|
||
|
const DHalfedge* curr = ccb;
|
||
|
|
||
|
formatter.write_ccb_halfedges_begin();
|
||
|
do {
|
||
|
formatter.write_halfedge_index(_index(curr));
|
||
|
curr = curr->next();
|
||
|
} while (curr != ccb);
|
||
|
formatter.write_ccb_halfedges_end();
|
||
|
}
|
||
|
|
||
|
/*! Get the mapped index of a given vertex. */
|
||
|
int _index(const DVertex* v) const
|
||
|
{
|
||
|
typename Vertex_index_map::const_iterator pos = m_v_index.find(v);
|
||
|
|
||
|
CGAL_assertion(pos != m_v_index.end());
|
||
|
return (pos->second);
|
||
|
}
|
||
|
|
||
|
/*! Get the mapped index of a given halfegde. */
|
||
|
int _index(const DHalfedge* he) const
|
||
|
{
|
||
|
typename Halfedge_index_map::const_iterator pos = m_he_index.find(he);
|
||
|
|
||
|
CGAL_assertion(pos != m_he_index.end());
|
||
|
return (pos->second);
|
||
|
}
|
||
|
|
||
|
/*! Get the number of edges along a given CCB. */
|
||
|
std::size_t _circulator_size(const DHalfedge* ccb) const
|
||
|
{
|
||
|
CGAL_assertion(ccb != NULL);
|
||
|
|
||
|
std::size_t n = 0;
|
||
|
const DHalfedge* curr = ccb;
|
||
|
|
||
|
do {
|
||
|
++n;
|
||
|
curr = curr->next();
|
||
|
} while (curr != ccb);
|
||
|
|
||
|
return (n);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} //namespace CGAL
|
||
|
|
||
|
#endif // CGAL_IO_ARRANGEMENT_2_WRITER_H
|