// Copyright (c) 2019 GeometryFactory // // This file is part of CGAL (www.cgal.org); // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Mael Rouxel-Labbé #ifndef CGAL_BGL_IO_GENERIC_FACEGRAPH_PRINTER_H #define CGAL_BGL_IO_GENERIC_FACEGRAPH_PRINTER_H #include #include #include #include #include #include #include #include namespace CGAL{ namespace IO { namespace internal { // Unfortunately, we don't know the value type of the normal/texture property maps template struct Normal_writer { Normal_writer(const VNM vnm) : vnm(vnm) { } template void operator()(Writer& writer, const VD v) const { const typename boost::property_traits::reference n = get(vnm, v); writer.write_vertex_normal(to_double(n.x()), to_double(n.y()), to_double(n.z())); } private: const VNM vnm; }; template <> struct Normal_writer { Normal_writer(const internal_np::Param_not_found&) { } template void operator()(Writer&, const VD) const { } }; template struct Texture_writer { Texture_writer(const VTM vtm) : vtm(vtm) { } template void operator()(Writer& writer, const VD v) const { const typename boost::property_traits::reference t = get(vtm, v); writer.write_vertex_texture(to_double(t.x()), to_double(t.y())); } private: const VTM vtm; }; template <> struct Texture_writer { Texture_writer(const internal_np::Param_not_found&) { } template void operator()(Writer&, const VD) const { } }; template class Generic_facegraph_printer { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::vertices_size_type vertices_size_type; typedef typename boost::graph_traits::face_descriptor face_descriptor; public: Generic_facegraph_printer(Stream& os) : m_os(os) { } Generic_facegraph_printer(Stream& os, FileWriter writer) : m_os(os), m_writer(writer) { } template bool operator()(const Graph& g, const NamedParameters& np = parameters::default_values()) { typedef typename GetVertexPointMap::const_type VPM; typedef typename boost::property_traits::reference Point_ref; typedef CGAL::IO::Color Color; typedef typename internal_np::Lookup_named_param_def< internal_np::vertex_color_map_t, NamedParameters, Constant_property_map >::type VCM; typedef typename internal_np::Lookup_named_param_def< internal_np::face_color_map_t, NamedParameters, Constant_property_map >::type FCM; // No default because value_type is unknown, but the pmap is only used if provided via NP typedef typename internal_np::Get_param< typename NamedParameters::base, internal_np::vertex_normal_map_t>::type VNM; typedef typename internal_np::Get_param< typename NamedParameters::base, internal_np::vertex_texture_map_t>::type VTM; using parameters::choose_parameter; using parameters::is_default_parameter; using parameters::get_parameter; if(!m_os.good()) return false; set_stream_precision_from_NP(m_os, np); VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_const_property_map(CGAL::vertex_point, g)); const bool has_vertex_normals = !(is_default_parameter::value); const bool has_vertex_colors = !(is_default_parameter::value); const bool has_vertex_textures = !(is_default_parameter::value); const bool has_face_colors = !(is_default_parameter::value); VNM vnm = get_parameter(np, internal_np::vertex_normal_map); VTM vtm = get_parameter(np, internal_np::vertex_texture_map); VCM vcm = choose_parameter(get_parameter(np, internal_np::vertex_color_map)); FCM fcm = choose_parameter(get_parameter(np, internal_np::face_color_map)); Normal_writer nw(vnm); Texture_writer tw(vtm); // @todo bench that against CGAL::Inverse_index and std::unordered_map boost::container::flat_map index_map; m_writer.write_header(m_os, vertices(g).size(), halfedges(g).size(), faces(g).size(), has_face_colors || has_vertex_colors, has_vertex_normals , has_vertex_textures ); vertices_size_type id = 0; for(const vertex_descriptor v : vertices(g)) { const Point_ref p = get(vpm, v); m_writer.write_vertex(to_double(p.x()), to_double(p.y()), to_double(p.z())); if(has_vertex_normals) nw(m_writer, v); if(has_vertex_colors) { const CGAL::IO::Color& vc = get(vcm, v); m_writer.write_vertex_color(vc.red(), vc.green(), vc.blue()); // @fixme correct? } if(has_vertex_textures) tw(m_writer, v); index_map[v] = id++; } m_writer.write_facet_header(); for(const face_descriptor f : faces(g)) { CGAL::Halfedge_around_face_circulator hc(halfedge(f, g), g); CGAL::Halfedge_around_face_circulator hc_end = hc; const std::size_t n = circulator_size(hc); CGAL_assertion(n >= 3); m_writer.write_facet_begin(n); do { m_writer.write_facet_vertex_index(index_map[target(*hc, g)]); ++hc; } while(hc != hc_end); if(has_face_colors) { const CGAL::IO::Color& fc = get(fcm, f); m_writer.write_face_color(fc.red(), fc.green(), fc.blue()); } m_writer.write_facet_end(); } m_writer.write_footer(); return m_os.good(); } protected: Stream& m_os; FileWriter m_writer; }; } // end internal } // end IO } // end CGAL #endif // CGAL_BGL_IO_GENERIC_FACEGRAPH_PRINTER_H