File: Generic_facegraph_printer.h

package info (click to toggle)
cgal 6.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 144,952 kB
  • sloc: cpp: 811,597; ansic: 208,576; sh: 493; python: 411; makefile: 286; javascript: 174
file content (205 lines) | stat: -rw-r--r-- 6,951 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// Copyright (c) 2019 GeometryFactory
//
// This file is part of CGAL (www.cgal.org);
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1.1/BGL/include/CGAL/boost/graph/IO/Generic_facegraph_printer.h $
// $Id: include/CGAL/boost/graph/IO/Generic_facegraph_printer.h 08b27d3db14 $
// 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 <CGAL/assertions.h>
#include <CGAL/boost/graph/iterator.h>
#include <CGAL/Named_function_parameters.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/property_map.h>

#include <boost/container/flat_map.hpp>

#include <string>
#include <vector>

namespace CGAL{
namespace IO {
namespace internal {

// Unfortunately, we don't know the value type of the normal/texture property maps
template <typename VNM>
struct Normal_writer
{
  Normal_writer(const VNM vnm) : vnm(vnm) { }

  template <typename Writer, typename VD>
  void operator()(Writer& writer, const VD v) const
  {
    const typename boost::property_traits<VNM>::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<internal_np::Param_not_found>
{
  Normal_writer(const internal_np::Param_not_found&) { }

  template <typename Writer, typename VD>
  void operator()(Writer&, const VD) const { }
};

template <typename VTM>
struct Texture_writer
{
  Texture_writer(const VTM vtm) : vtm(vtm) { }

  template <typename Writer, typename VD>
  void operator()(Writer& writer, const VD v) const
  {
    const typename boost::property_traits<VTM>::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<internal_np::Param_not_found>
{
  Texture_writer(const internal_np::Param_not_found&) { }

  template <typename Writer, typename VD>
  void operator()(Writer&, const VD) const { }
};

template <typename Stream, typename Graph, typename FileWriter>
class Generic_facegraph_printer
{
  typedef typename boost::graph_traits<Graph>::vertex_descriptor                   vertex_descriptor;
  typedef typename boost::graph_traits<Graph>::vertices_size_type                  vertices_size_type;
  typedef typename boost::graph_traits<Graph>::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 <typename NamedParameters = parameters::Default_named_parameters>
  bool operator()(const Graph& g,
                  const NamedParameters& np = parameters::default_values())
  {
    typedef typename GetVertexPointMap<Graph, NamedParameters>::const_type         VPM;
    typedef typename boost::property_traits<VPM>::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<vertex_descriptor, Color> >::type                      VCM;
    typedef typename internal_np::Lookup_named_param_def<
      internal_np::face_color_map_t, NamedParameters,
      Constant_property_map<face_descriptor, Color> >::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<NamedParameters, internal_np::vertex_normal_map_t>::value);
    const bool has_vertex_colors = !(is_default_parameter<NamedParameters, internal_np::vertex_color_map_t>::value);
    const bool has_vertex_textures = !(is_default_parameter<NamedParameters, internal_np::vertex_texture_map_t>::value);
    const bool has_face_colors = !(is_default_parameter<NamedParameters, internal_np::face_color_map_t>::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<VCM>(get_parameter(np, internal_np::vertex_color_map));
    FCM fcm = choose_parameter<FCM>(get_parameter(np, internal_np::face_color_map));

    Normal_writer<VNM> nw(vnm);
    Texture_writer<VTM> tw(vtm);

    // @todo bench that against CGAL::Inverse_index and std::unordered_map
    boost::container::flat_map<vertex_descriptor, vertices_size_type> 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<Graph> hc(halfedge(f, g), g);
      CGAL::Halfedge_around_face_circulator<Graph> 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