cgal/Stream_support/include/CGAL/IO/PLY/PLY_writer.h

319 lines
10 KiB
C++

// Copyright (c) 2017 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) : Simon Giraudot
#ifndef CGAL_IO_PLY_PLY_WRITER_H
#define CGAL_IO_PLY_PLY_WRITER_H
#include <CGAL/IO/io.h>
#include <CGAL/number_utils.h>
namespace CGAL {
namespace IO {
namespace internal {
template <typename T> inline void property_header_type (std::ostream& stream)
{
CGAL_assertion_msg (false, "Unknown PLY type");
stream << "undefined_type";
}
template <> inline void property_header_type<char> (std::ostream& stream) { stream << "char"; }
template <> inline void property_header_type<signed char> (std::ostream& stream) { stream << "char"; }
template <> inline void property_header_type<unsigned char> (std::ostream& stream) { stream << "uchar"; }
template <> inline void property_header_type<short> (std::ostream& stream) { stream << "short"; }
template <> inline void property_header_type<unsigned short> (std::ostream& stream) { stream << "ushort"; }
template <> inline void property_header_type<int> (std::ostream& stream) { stream << "int"; }
template <> inline void property_header_type<unsigned int> (std::ostream& stream) { stream << "uint"; }
template <> inline void property_header_type<float> (std::ostream& stream) { stream << "float"; }
template <> inline void property_header_type<double> (std::ostream& stream) { stream << "double"; }
template <typename T>
void property_header (std::ostream& stream, const PLY_property<T>& prop)
{
stream << "property ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <typename T>
void property_header (std::ostream& stream, const PLY_property<std::vector<T> >& prop)
{
stream << "property list uchar ";
property_header_type<T>(stream);
stream << " " << prop.name << std::endl;
}
template <std::size_t N>
struct Properties_header
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
Properties_header<N-1>::write(stream, wrappers);
property_header (stream, std::get<N+1>(wrappers));
}
};
template <>
struct Properties_header<0>
{
template <class PLY_property_tuple>
static void write(std::ostream& stream, PLY_property_tuple& wrappers)
{
property_header (stream, std::get<1>(wrappers));
}
};
template <typename PropertyMap,
typename ... T>
void output_property_header(std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
}
template <typename PropertyMap,
typename T>
void output_property_header(std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
property_header(stream, current.second);
}
template <typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header(std::ostream& stream,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_header(stream, current.second);
output_property_header(stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_property_header(std::ostream& stream,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
Properties_header<sizeof...(T)-1>::write(stream, current);
output_property_header(stream, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap>
void property_write(std::ostream& stream, ForwardIterator it, PropertyMap map)
{
stream << CGAL::IO::oformat(get(map, *it));
}
template <typename T>
inline T no_char_character(const T& t) { return t; }
inline int no_char_character(const char& t) { return int(t); }
inline int no_char_character(const signed char& t) { return int(t); }
inline int no_char_character(const unsigned char& t) { return int(t); }
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write(std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> > map)
{
if(CGAL::IO::get_mode(stream) == CGAL::IO::ASCII)
stream << no_char_character(get(map.first, *it));
else
{
typename boost::property_traits<PropertyMap>::value_type value = get(map.first, *it);
stream.write(reinterpret_cast<char*>(&value), sizeof(value));
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void simple_property_write(std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<std::vector<T> > > map)
{
const typename PropertyMap::value_type& value = get(map.first, *it);
if(CGAL::IO::get_mode(stream) == CGAL::IO::ASCII)
{
stream << value.size();
for(std::size_t i = 0; i < value.size(); ++ i)
stream << " " << no_char_character(value[i]);
}
else
{
unsigned char size = static_cast<unsigned char>(value.size());
stream.write(reinterpret_cast<char*>(&size), sizeof(size));
for(std::size_t i = 0; i < value.size(); ++ i)
{
T t = T(value[i]);
stream.write(reinterpret_cast<char*>(&t), sizeof(t));
}
}
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T>
void output_properties(std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current)
{
property_write(stream, it, std::get<0>(current));
if(CGAL::IO::get_mode(stream) == CGAL::IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T>
void output_properties(std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current)
{
simple_property_write(stream, it, std::forward<std::pair<PropertyMap, PLY_property<T> > >(current));
if(get_mode(stream) == CGAL::IO::ASCII)
stream << std::endl;
}
template <typename ForwardIterator,
typename PropertyMap,
typename T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties(std::ostream& stream,
ForwardIterator it,
std::pair<PropertyMap, PLY_property<T> >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
simple_property_write(stream, it, current);
if(get_mode(stream) == CGAL::IO::ASCII)
stream << " ";
output_properties(stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
template <typename ForwardIterator,
typename PropertyMap,
typename ... T,
typename NextPropertyHandler,
typename ... PropertyHandler>
void output_properties(std::ostream& stream,
ForwardIterator it,
std::tuple<PropertyMap, PLY_property<T>... >&& current,
NextPropertyHandler&& next,
PropertyHandler&& ... properties)
{
property_write(stream, it, std::get<0>(current));
if(get_mode(stream) == CGAL::IO::ASCII)
stream << " ";
output_properties(stream, it, std::forward<NextPropertyHandler>(next),
std::forward<PropertyHandler>(properties)...);
}
// Printer classes used by Point_set_3 and Surface_mesh(translate a
// property map to a PLY property)
template <typename Index>
class Abstract_property_printer
{
public:
virtual ~Abstract_property_printer() { }
virtual void print(std::ostream& stream, const Index& index) = 0;
};
template <typename Index, typename PropertyMap>
class Property_printer
: public Abstract_property_printer<Index>
{
PropertyMap m_pmap;
public:
Property_printer(const PropertyMap& pmap) : m_pmap(pmap) { }
virtual void print(std::ostream& stream, const Index& index)
{
stream << get(m_pmap, index);
}
};
template <typename Index,
typename PropertyMap,
typename Type = typename boost::property_traits<PropertyMap>::value_type>
class Simple_property_printer
: public Abstract_property_printer<Index>
{
PropertyMap m_pmap;
public:
Simple_property_printer(const PropertyMap& pmap) : m_pmap(pmap) { }
virtual void print(std::ostream& stream, const Index& index)
{
if(get_mode(stream) == CGAL::IO::ASCII)
stream << no_char_character(get(m_pmap, index));
else
{
Type t = Type(get(m_pmap, index));
stream.write(reinterpret_cast<char*>(&t), sizeof(t));
}
}
};
template <typename Index,
typename PropertyMap,
typename VectorType = typename boost::property_traits<PropertyMap>::value_type,
typename ElementType = typename VectorType::value_type>
class Simple_property_vector_printer
: public Abstract_property_printer<Index>
{
PropertyMap m_pmap;
public:
Simple_property_vector_printer(const PropertyMap& pmap) : m_pmap(pmap) { }
virtual void print(std::ostream& stream, const Index& index)
{
const VectorType& vec = get(m_pmap, index);
if(get_mode(stream) == CGAL::IO::ASCII)
{
stream << vec.size();
for(const ElementType& v : vec)
{
stream << " " << v;
}
}
else
{
unsigned char size = (unsigned char)(vec.size());
stream.write(reinterpret_cast<char*>(&size), sizeof(size));
for(const ElementType& v : vec)
{
ElementType t = ElementType(v);
stream.write(reinterpret_cast<char*>(&t), sizeof(t));
}
}
}
};
} // namespace internal
} // namespace IO
} // namespace CGAL
#endif // CGAL_IO_PLY_PLY_WRITER_H