// Copyright (c) 2005,2006,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 // (based on old version by Michal Meyerovitch and Ester Ezra) // #ifndef CGAL_IO_ARRANGEMENT_2_READER_H #define CGAL_IO_ARRANGEMENT_2_READER_H #include /*! \file * The header file for the Arrangement_2_reader class. */ #include #include #include #include #include namespace CGAL { /*! \class * An auxiliary class for reading an arrangement from an input stream. */ template class Arrangement_2_reader { public: typedef Arrangement_ Arrangement_2; typedef Arrangement_2_reader Self; protected: typedef typename Arrangement_2::Size Size; typedef typename Arrangement_2::Dcel Dcel; typedef typename Arrangement_2::X_monotone_curve_2 X_monotone_curve_2; typedef typename Arrangement_2::Point_2 Point_2; typedef typename Arrangement_2::Vertex_handle Vertex_handle; typedef typename Arrangement_2::Halfedge_handle Halfedge_handle; typedef typename Arrangement_2::Face_handle Face_handle; typedef CGAL::Arr_accessor Arr_accessor; typedef typename Arr_accessor::Dcel_vertex DVertex; typedef typename Arr_accessor::Dcel_halfedge DHalfedge; typedef typename Arr_accessor::Dcel_face DFace; typedef typename Arr_accessor::Dcel_outer_ccb DOuter_ccb; typedef typename Arr_accessor::Dcel_inner_ccb DInner_ccb; typedef typename Arr_accessor::Dcel_isolated_vertex DIso_vert; // Data members: Arrangement_2& m_arr; Arr_accessor m_arr_access; Point_2 m_point; std::vector m_vertices; X_monotone_curve_2 m_curve; std::vector m_halfedges; private: // Copy constructor and assignment operator - not supported. Arrangement_2_reader(const Self&); Self& operator=(const Self&); public: /*! Constructor. */ Arrangement_2_reader(Arrangement_2& arr) : m_arr(arr), m_arr_access(arr) {} /*! Destructor. */ virtual ~Arrangement_2_reader() {} /*! Read the arrangement. */ template void operator()(Formatter& formatter) { // Clear the exisiting arrangement so it contains no DCEL features. m_arr_access.clear_all(); // Read the arrangement dimensions. formatter.read_arrangement_begin(); const Size number_of_vertices = formatter.read_size("number_of_vertices"); const Size number_of_halfedges = 2*formatter.read_size("number_of_edges"); const Size number_of_faces = formatter.read_size("number_of_faces"); Size k; // std::cout << number_of_vertices << std::endl; // std::cout << number_of_halfedges << std::endl; // std::cout << number_of_faces << std::endl; // Read the DCEL vertices and store them in the vertices vector. formatter.read_vertices_begin(); m_vertices.resize(number_of_vertices); for (k = 0; k < number_of_vertices; k++) m_vertices[k] = _read_vertex(formatter); formatter.read_vertices_end(); // Read the DCEL halfedges and store them in the halfedges vector. DHalfedge* he = NULL; formatter.read_edges_begin(); m_halfedges.resize(number_of_halfedges); for (k = 0; k < number_of_halfedges; k += 2) { he = _read_edge(formatter); m_halfedges[k] = he; m_halfedges[k + 1] = he->opposite(); } formatter.read_edges_end(); // Read the DCEL faces. formatter.read_faces_begin(); for (k = 0; k < number_of_faces; k++) _read_face(formatter); formatter.read_faces_end(); formatter.read_arrangement_end(); // Use the accessor an update the topology-traits properties with the // new DCEL we have just read. m_arr_access.dcel_updated(); } protected: /*! Read a DCEL vertex. */ template DVertex* _read_vertex(Formatter& formatter) { formatter.read_vertex_begin(); // Read the boundary conditions. Arr_parameter_space ps_x = Arr_parameter_space(formatter.read_vertex_index()); Arr_parameter_space ps_y = Arr_parameter_space(formatter.read_vertex_index()); int has_point = formatter.read_vertex_index(); DVertex* new_v; if (has_point) { // Read the point associated with the vertex. formatter.read_point(m_point); // Allocate a new DCEL vertex and associate it with this point. new_v = m_arr_access.new_vertex(&m_point, ps_x, ps_y); // Read any auxiliary data associated with the vertex. formatter.read_vertex_data(Vertex_handle(new_v)); } else { // Allocate a vertex at infinity. new_v = m_arr_access.new_vertex(NULL, ps_x, ps_y); } formatter.read_vertex_end(); return (new_v); } /*! Read a DCEL edge (a pair of twin halfedges). */ template DHalfedge* _read_edge(Formatter& formatter) { formatter.read_edge_begin(); // Read the indices of the end-vertices and the edge direction. int source_idx = formatter.read_vertex_index(); int target_idx = formatter.read_vertex_index(); int direction = formatter.read_vertex_index(); int has_curve = formatter.read_vertex_index(); DHalfedge* new_he; DVertex* src_v = m_vertices[source_idx]; DVertex* trg_v = m_vertices[target_idx]; if (has_curve) { // Read the x-monotone curve associated with the edge. formatter.read_x_monotone_curve(m_curve); // Allocate a pair of new DCEL halfegdes and associate them with the // x-monotone curve we read. new_he = m_arr_access.new_edge(&m_curve); } else { // Allocate a new fictitious edge. new_he = m_arr_access.new_edge(NULL); } // Set the cross pointers between the twin halfedges and the end vertices. trg_v->set_halfedge(new_he); new_he->set_vertex(trg_v); src_v->set_halfedge(new_he->opposite()); new_he->opposite()->set_vertex(src_v); // Set the direction of the halfedges. if (direction == 0) { new_he->set_direction(ARR_LEFT_TO_RIGHT); } else { CGAL_assertion(direction == 1); new_he->set_direction(ARR_RIGHT_TO_LEFT); } // Read any auxiliary data associated with the halfedges. if (has_curve) { formatter.read_halfedge_data(Halfedge_handle(new_he)); formatter.read_halfedge_data(Halfedge_handle((new_he->opposite()))); } formatter.read_edge_end(); return (new_he); } /*! Read a DCEL face. */ template void _read_face(Formatter& formatter) { formatter.read_face_begin(); // Allocate a new face and determine whether it is unbounded and wether it // is valid (non-fictitious). DFace* new_f = m_arr_access.new_face(); const bool is_unbounded = (formatter.read_vertex_index() != 0); const bool is_valid = (formatter.read_vertex_index() != 0); new_f->set_unbounded(is_unbounded); new_f->set_fictitious(! is_valid); // Read the outer CCBs of the face. formatter.read_outer_ccbs_begin(); DOuter_ccb* new_occb; const Size n_occbs = formatter.read_size("number_of_outer_ccbs"); DHalfedge* he; Size n, k; for (k = 0; k < n_occbs; k++) { // Allocate a new outer CCB record and set its incident face. new_occb = m_arr_access.new_outer_ccb(); new_occb->set_face(new_f); // Read the current outer CCB. n = formatter.read_size("halfedges_on_outer_ccb"); he = _read_ccb(formatter, n, new_occb, NULL); new_f->add_outer_ccb(new_occb, he); } formatter.read_outer_ccbs_end(); // Read the inner CCBs of the face. formatter.read_inner_ccbs_begin(); DInner_ccb* new_iccb; const Size n_iccbs = formatter.read_size("number_of_inner_ccbs"); for (k = 0; k < n_iccbs; k++) { // Allocate a new inner CCB record and set its incident face. new_iccb = m_arr_access.new_inner_ccb(); new_iccb->set_face(new_f); // Read the current inner CCB. n = formatter.read_size("halfedges_on_inner_ccb"); he = _read_ccb(formatter, n, NULL, new_iccb); new_f->add_inner_ccb(new_iccb, he); } formatter.read_inner_ccbs_end(); // Read the isolated vertices inside the face. Size n_isolated_vertices = formatter.read_size("number_of_isolated_vertices"); if (n_isolated_vertices) { formatter.read_isolated_vertices_begin(); Size k; for (k = 0; k < n_isolated_vertices; k++) { // Allocate a new isolated vertex record and set its incident face. DIso_vert* new_iso_vert = m_arr_access.new_isolated_vertex(); new_iso_vert->set_face(new_f); // Read the current isolated vertex. std::size_t v_idx = formatter.read_vertex_index(); DVertex* iso_v = m_vertices[v_idx]; iso_v->set_isolated_vertex(new_iso_vert); new_f->add_isolated_vertex(new_iso_vert, iso_v); } formatter.read_isolated_vertices_end(); } // Read any auxiliary data associated with the face. if (is_valid) formatter.read_face_data(Face_handle(new_f)); formatter.read_face_end(); } /*! * Read a circular boundary of a conncted component. * \param formatter The formatter. * \param boundary_size The number of halfedges along the boundary. * \param p_outer The outer CCB. * \param p_inner The inner CCB. * \pre p_outer is valid and p_inner is NULL, or vice versa. * \return A pointer to the first halfedge read. */ template DHalfedge* _read_ccb(Formatter& formatter, Size boundary_size, DOuter_ccb* p_outer, DInner_ccb* p_inner) { CGAL_assertion((p_outer != NULL && p_inner == NULL) || (p_outer == NULL && p_inner != NULL)); formatter.read_ccb_halfedges_begin(); // Find the first halfedge, and set its CCB. std::size_t first_idx = formatter.read_halfedge_index(); DHalfedge* first_he = m_halfedges [first_idx]; if (p_outer != NULL) first_he->set_outer_ccb(p_outer); else first_he->set_inner_ccb(p_inner); // Read the rest of the halfedge along the boundary. std::size_t curr_idx; DHalfedge* prev_he = first_he; DHalfedge* curr_he; Size k; for (k = 1; k < boundary_size; k++) { curr_idx = formatter.read_halfedge_index(); curr_he = m_halfedges[curr_idx]; // Connect the previous halfedge and the current one. prev_he->set_next(curr_he); // Set the CCB. if (p_outer != NULL) curr_he->set_outer_ccb(p_outer); else curr_he->set_inner_ccb(p_inner); prev_he = curr_he; } // Close the circular list be connecting the first and the last halfedges. prev_he->set_next(first_he); formatter.read_ccb_halfedges_end(); // Return the first halfedge. return (first_he); } }; } //namespace CGAL #endif // CGAL_IO_ARRANGEMENT_2_READER_H