64 const std::vector<Comment> &
comments()
const {
return comments_; }
69 const std::vector<PlyElement> &
elements()
const {
return elements_; }
81 std::optional<PlyElement>
element(
const std::string &name)
const
83 const auto it = std::find_if(
84 elements_.begin(), elements_.end(), [&](
const PlyElement &e) { return e.name() == name; });
85 return it != elements_.end() ? std::optional(*it) : std::nullopt;
100 bool find(
const std::string &elementName)
const
102 while (currElement_ != elements_.end() && currElement_->name() != elementName) {
skipElement(); }
103 return currElement_ != elements_.end();
115 bool hasElement()
const {
return currElement_ != elements_.end(); }
144 template<
typename T,
typename Layout>
147 parser_.read<Layout>(*currElement_++,
reinterpret_cast<std::uint8_t *
>(dest),
alignof(T));
161 template<
typename T,
typename Layout>
164 std::vector<T> result(currElement_->size());
165 parser_.read<Layout>(*currElement_++,
reinterpret_cast<std::uint8_t *
>(result.data()),
alignof(T));
177 IStream(std::istream &is,
const detail::HeaderParser &headerParser)
178 : parser_{is, headerParser.
format()},
181 format_{headerParser.
format()},
182 currElement_{elements_.begin()}
188 detail::ParserVariant parser_;
191 std::vector<Comment> comments_;
193 std::vector<PlyElement> elements_;
198 mutable std::vector<PlyElement>::const_iterator currElement_;
219 OStream(
PlyFormat format, std::vector<Comment> comments) : format_{format}, comments_{std::move(comments)}
222 std::stable_sort(comments_.begin(), comments_.end(), [](
const Comment &x,
const Comment &y) {
223 return x.line < y.line;
233 template<
typename... Ts>
240 elementWriteClosures_.emplace_back(
241 std::move(layoutElement),
242 [layout](detail::WriterVariant &writer,
const PlyElement &e) { writer.write(e, layout); });
255 const std::uint8_t *src = elementData.
data();
256 const std::size_t alignment = elementData.
alignment();
258 elementWriteClosures_.emplace_back(
259 elementData.
element(), [src, alignment](detail::WriterVariant &writer,
const PlyElement &e) {
260 writer.write(e, src, alignment);
272 detail::WriterVariant writer{os, format_};
273 for (
const auto &elementClosurePair : elementWriteClosures_)
275 const PlyElement &element{elementClosurePair.first};
276 const auto &writeFn = elementClosurePair.second;
277 writeFn(writer, element);
286 void writeHeader(std::ostream &os)
const
292 case PlyFormat::Ascii:
293 os <<
"format ascii 1.0\n";
295 case PlyFormat::BinaryBigEndian:
296 os <<
"format binary_big_endian 1.0\n";
298 case PlyFormat::BinaryLittleEndian:
299 os <<
"format binary_little_endian 1.0\n";
307 std::uint32_t line = 2;
308 auto first = comments_.begin();
309 const auto last = comments_.end();
310 const auto maybeWriteComments = [&]() {
311 while (first != last && first->line == line++)
313 if (first->text.empty()) { os <<
"comment\n"; }
314 else { os <<
"comment " << first->text <<
'\n'; }
319 for (
const auto &elementClosurePair : elementWriteClosures_)
321 maybeWriteComments();
322 const PlyElement &element{elementClosurePair.first};
323 os <<
"element " << element.name() <<
' ' << element.size() <<
'\n';
325 for (
const PlyProperty &property : element.properties())
327 maybeWriteComments();
328 if (property.isList())
330 os <<
"property list " <<
property.sizeType() <<
' ' <<
property.type() <<
' ' <<
property.name()
333 else { os <<
"property " <<
property.type() <<
' ' <<
property.name() <<
'\n'; }
337 maybeWriteComments();
338 os <<
"end_header\n";
341 using ElementWriteClosure = std::function<void(detail::WriterVariant &,
const PlyElement &)>;
344 std::vector<std::pair<PlyElement, ElementWriteClosure>> elementWriteClosures_;
349 std::vector<Comment> comments_;
364 std::vector<PlyElementData> elementsData;
366 while (plyIs.hasElement())
368 elementsData.emplace_back(plyIs.readElement());
369 plyOs.
add(elementsData.back());
Represents an input PLY data stream that can be queried for data.
PlyElementData readElement() const
const std::vector< Comment > & comments() const
std::vector< T > readElement() const
IStream(std::istream &is)
void readElement(T *dest) const
PlyElement element() const
std::optional< PlyElement > element(const std::string &name) const
bool find(const std::string &elementName) const
void skipElement() const
Skips the current element.
const std::vector< PlyElement > & elements() const
OStream(PlyFormat format)
OStream(PlyFormat format, std::vector< Comment > comments)
void add(const PlyElementData &elementData)
void add(const PlyElement &element, const reflect::Layout< Ts... > layout)
void write(std::ostream &os) const
const PlyElement & element() const
std::uint8_t * data() const
std::size_t alignment() const
void convert(std::istream &is, std::ostream &os, PlyFormat format)
const std::vector< PlyProperty > & properties() const
const std::string & name() const