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