// Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org); you may redistribute it under // the terms of the Q Public License version 1.0. // See the file LICENSE.QPL distributed with CGAL. // // 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) : Laurent RINEAU #ifndef CGAL_IO_FILE_MEDIT_H #define CGAL_IO_FILE_MEDIT_H #include #include #include #include #include namespace CGAL { namespace { //------------------------------------------------------- // Default property map implementation //------------------------------------------------------- #ifdef CGAL_MESH_3_IO_VERBOSE template inline std::ostream& operator<<(std::ostream &os, const std::pair& pair) { return os << "<" << pair.first << "," << pair.second << ">"; } #endif /** * */ template class Default_facet_index_pmap { typedef typename C3T3::Surface_index Surface_index; typedef std::map Surface_map; typedef typename C3T3::Facet Facet; typedef unsigned int size_type; public: Default_facet_index_pmap(const C3T3& c3t3, const int first_index = 0) : r_c3t3_(c3t3) { typedef typename C3T3::Facet_iterator Facet_iterator; int index_counter = first_index + 1; for( Facet_iterator facet_it = r_c3t3_.facets_begin(); facet_it != r_c3t3_.facets_end(); ++facet_it) { // Add surface index in internal map if needed if ( surface_map_.end() == surface_map_.find(c3t3.surface_index((*facet_it).first, (*facet_it).second)) ) { surface_map_.insert(std::make_pair(r_c3t3_.surface_index(*facet_it), index_counter)); ++index_counter; } } // Rebind indices in alphanumeric order index_counter = first_index + 1; for ( typename Surface_map::iterator mit = surface_map_.begin() ; mit != surface_map_.end() ; ++mit ) { mit->second = index_counter++; } #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Nb of surface patches: " << surface_map_.size() << "\n"; std::cerr << "Surface mapping:\n\t" ; typedef typename Surface_map::iterator Surface_map_iterator; for ( Surface_map_iterator surf_it = surface_map_.begin() ; surf_it != surface_map_.end() ; ++surf_it ) { std::cerr << "[" << (*surf_it).first << ":" << (*surf_it).second << "] "; } std::cerr << "\n"; #endif } int surface_index(const Facet& f) const { return surface_index(r_c3t3_.surface_index(f)); } int surface_index(const Surface_index& index) const { typedef typename Surface_map::const_iterator Smi; Smi elt_it = surface_map_.find(index); if ( elt_it != surface_map_.end() ) return elt_it->second; else return -1; } size_type surface_number() const { return surface_map_.size(); } private: const C3T3& r_c3t3_; Surface_map surface_map_; }; template class Default_cell_index_pmap { typedef typename C3T3::Subdomain_index Subdomain_index; typedef std::map Subdomain_map; typedef typename C3T3::Cell_handle Cell_handle; typedef unsigned int size_type; public: Default_cell_index_pmap(const C3T3& c3t3, const int first_index = 0) : r_c3t3_(c3t3) { typedef typename C3T3::Cell_iterator Cell_iterator; int index_counter = first_index + 1; for( Cell_iterator cell_it = r_c3t3_.cells_begin(); cell_it != r_c3t3_.cells_end(); ++cell_it) { // Add subdomain index in internal map if needed if ( subdomain_map_.end() == subdomain_map_.find(r_c3t3_.subdomain_index(cell_it)) ) { subdomain_map_.insert(std::make_pair(r_c3t3_.subdomain_index(cell_it), index_counter)); ++index_counter; } } // Rebind indices in alphanumeric order index_counter = first_index + 1; for ( typename Subdomain_map::iterator mit = subdomain_map_.begin() ; mit != subdomain_map_.end() ; ++mit ) { mit->second = index_counter++; } #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Nb of subdomains: " << subdomain_map_.size() << "\n"; std::cerr << "Subdomain mapping:\n\t" ; typedef typename Subdomain_map::iterator Subdomain_map_iterator; for ( Subdomain_map_iterator sub_it = subdomain_map_.begin() ; sub_it != subdomain_map_.end() ; ++sub_it ) { std::cerr << "[" << (*sub_it).first << ":" << (*sub_it).second << "] "; } std::cerr << "\n"; #endif } int subdomain_index(const Cell_handle& ch) const { return subdomain_index(r_c3t3_.subdomain_index(ch)); } int subdomain_index(const Subdomain_index& index) const { typedef typename Subdomain_map::const_iterator Smi; Smi elt_it = subdomain_map_.find(index); if ( elt_it != subdomain_map_.end() ) return elt_it->second; else return -1; } size_type subdomain_number() const { return subdomain_map_.size(); } private: const C3T3& r_c3t3_; Subdomain_map subdomain_map_; }; template class Default_vertex_index_pmap { typedef typename C3T3::Surface_index Surface_index; typedef typename C3T3::Subdomain_index Subdomain_index; typedef typename C3T3::Index Index; typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Cell_handle Cell_handle; typedef typename C3T3::Facet Facet; public: Default_vertex_index_pmap(const Default_facet_index_pmap& f_pmap, const Default_cell_index_pmap& c_pmap, const C3T3& c3t3) : f_pmap_(f_pmap) , c_pmap_(c_pmap) , r_c3t3_(c3t3) , edge_index_(1 + f_pmap_.surface_number() + c_pmap_.subdomain_number()) {} int index(const Vertex_handle& vh) const { switch ( r_c3t3_.in_dimension(vh) ) { case 2: { // Check if each incident surface facet of vh has the same surface index typename std::vector facets; r_c3t3_.triangulation().finite_incident_facets( vh, std::back_inserter(facets)); if ( facets.begin() == facets.end() ) return -1; // Look for the first surface facet typename std::vector::iterator it_facet = facets.begin(); while ( ! r_c3t3_.is_in_complex(*it_facet) ) { if ( ++it_facet == facets.end() ) return -1; } Surface_index facet_index = r_c3t3_.surface_index(*it_facet); ++it_facet; for( ; it_facet != facets.end() ; ++it_facet) { // If another index is found, return value for edge vertice if ( r_c3t3_.is_in_complex(*it_facet) && facet_index != r_c3t3_.surface_index(*it_facet) ) return edge_index_; } return f_pmap_.surface_index(facet_index); } break; case 3: { // Returns value of any incident cell typename std::vector cells; r_c3t3_.triangulation().finite_incident_cells( vh,std::back_inserter(cells)); if ( cells.begin() != cells.end() ) return c_pmap_.subdomain_index(r_c3t3_.subdomain_index(*cells.begin())); else return -1; } break; default: // should not happen return -1; break; } } private: Default_facet_index_pmap f_pmap_; Default_cell_index_pmap c_pmap_; const C3T3& r_c3t3_; const unsigned int edge_index_; }; //template //class Vertex_index_pmap //{ // typedef typename C3T3::Surface_index Surface_index; // typedef typename C3T3::Subdomain_index Subdomain_index; // typedef typename C3T3::Index Index; // typedef typename C3T3::Vertex_handle Vertex_handle; // //public: // Vertex_index_pmap(const Default_facet_index_pmap& f_pmap, // const Default_cell_index_pmap& c_pmap, // const C3T3& c3t3) // : f_pmap_(f_pmap) // , c_pmap_(c_pmap) // , r_c3t3_(c3t3) { } // // int index(const Vertex_handle& vh) const // { // switch ( r_c3t3_.in_dimension(vh) ) // { // case 2: // return f_pmap_.surface_index(r_c3t3_.index(vh).surface_index()); // break; // case 3: // return c_pmap_.subdomain_index(r_c3t3_.index(vh).subdomain_index()); // break; // default: // // should not happen // return -1; // break; // } // } // //private: // Default_facet_index_pmap f_pmap_; // Default_cell_index_pmap c_pmap_; // const C3T3& r_c3t3_; //}; //------------------------------------------------------- // Property map access methods //------------------------------------------------------- template int get(const Default_vertex_index_pmap& vmap, const typename C3T3::Vertex_handle& vh) { return vmap.index(vh); } template int get(const Default_facet_index_pmap& fmap, const typename C3T3::Facet& f) { return fmap.surface_index(f); } template int get(const Default_cell_index_pmap& fmap, const typename C3T3::Cell_handle& ch) { return fmap.subdomain_index(ch); } //------------------------------------------------------- // IO functions //------------------------------------------------------- template void output_to_medit(std::ostream& os, const C3T3& c3t3) { #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Output to medit:\n"; #endif output_to_medit(os, c3t3, Default_cell_index_pmap(c3t3)); } template void output_to_medit(std::ostream& os, const C3T3& c3t3, const Default_cell_index_pmap& cell_pmap) { output_to_medit( os, c3t3, Default_facet_index_pmap(c3t3, cell_pmap.subdomain_number()), cell_pmap); } template void output_to_medit(std::ostream& os, const C3T3& c3t3, const Default_facet_index_pmap& facet_pmap, const Default_cell_index_pmap& cell_pmap) { output_to_medit( os, c3t3, Default_vertex_index_pmap(facet_pmap, cell_pmap, c3t3), facet_pmap, cell_pmap); } template void output_to_medit(std::ostream& os, const C3T3& c3t3, const Vertex_index_property_map& vertex_pmap, const Facet_index_property_map& facet_pmap, const Cell_index_property_map& cell_pmap) { typedef typename C3T3::Triangulation Tr; typedef typename C3T3::Facet_iterator Facet_iterator; typedef typename C3T3::Cell_iterator Cell_iterator; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Point Point_3; const Tr& tr = c3t3.triangulation(); //------------------------------------------------------- // File output //------------------------------------------------------- //------------------------------------------------------- // Header //------------------------------------------------------- os << std::setprecision(20); os << "MeshVersionFormatted 1" << std::endl << "Dimension 3" << std::endl; //------------------------------------------------------- // Vertices //------------------------------------------------------- os << "Vertices" << std::endl << tr.number_of_vertices() << std::endl; std::map V; int inum = 1; for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); vit != tr.finite_vertices_end(); ++vit) { V[vit] = inum++; Point_3 p = vit->point(); os << CGAL::to_double(p.x()) << " " << CGAL::to_double(p.y()) << " " << CGAL::to_double(p.z()) << " " << get(vertex_pmap,vit) << std::endl; } //------------------------------------------------------- // Facets //------------------------------------------------------- os << "Triangles" << std::endl << c3t3.number_of_facets() << std::endl; for( Facet_iterator fit = c3t3.facets_begin(); fit != c3t3.facets_end(); ++fit) { for (int i=0; i<4; i++) { if (i != fit->second) { const Vertex_handle& vh = (*fit).first->vertex(i); os << V[vh] << " "; } } os << get(facet_pmap, *fit) //ref << std::endl; } //------------------------------------------------------- // Tetrahedra //------------------------------------------------------- os << "Tetrahedra" << std::endl << c3t3.number_of_cells() << std::endl; for( Cell_iterator cit = c3t3.cells_begin() ; cit != c3t3.cells_end() ; ++cit ) { for (int i=0; i<4; i++) os << V[cit->vertex(i)] << " "; os << get(cell_pmap, cit) << std::endl; } //------------------------------------------------------- // End //------------------------------------------------------- os << "End" << std::endl; } // end output_to_medit(...) } // end of anomymous namespace for output_to_medit(..) namespace Mesh_3 { namespace details { class Debug { bool active; std::ostream* out; const std::string header; class Debug_aux { Debug* debug; public: Debug_aux() : debug(0) {} Debug_aux(Debug* d) : debug(d) {} template Debug_aux& operator<<(const T& t) { if ( debug ) debug->apply(t, false); return *this; } void set_debug(Debug* d) { debug = d; } operator bool() const { return false; } }; Debug_aux aux; public: Debug(bool debug, std::ostream* debug_str = &std::cout, const std::string header_string = "") : active(debug), out(debug_str), header(header_string), aux() { aux.set_debug(this); } template void apply(T& t, bool with_header = true) { if(active) { if(with_header) *out << header; *out << t; } } template Debug_aux& operator<<(const T& t) { apply(t); return aux; } operator bool() const { return false; } }; // end internal class Debug // template // Debug_aux& operator<<(Debug& d, const T& t) // { // d.apply(t); // return aux; // } } // end namespace details } // end namespace Mesh_3 } // end namespace CGAL #endif // CGAL_IO_FILE_MEDIT_H