23#ifndef VCL_LOAD_SAVE_PLY_DETAIL_EDGE_H
24#define VCL_LOAD_SAVE_PLY_DETAIL_EDGE_H
28#include <vclib/io/write.h>
29#include <vclib/misc/tokenizer.h>
31namespace vcl::detail {
33template<EdgeMeshConcept MeshType, EdgeConcept EdgeType,
typename Stream>
34void readPlyEdgeProperty(
39 std::endian end = std::endian::little)
41 bool hasBeenRead =
false;
43 if (p.name == ply::vertex_indices) {
44 std::vector<uint> vids;
45 uint eSize = io::readPrimitiveType<uint>(file, p.listSizeType, end);
47 for (uint i = 0; i < eSize; ++i) {
48 vids[i] = io::readPrimitiveType<size_t>(file, p.type, end);
49 if (vids[i] >= mesh.vertexNumber()) {
50 throw MalformedFileException(
51 "Bad vertex index for edge " + std::to_string(e.index()));
55 e.setVertex(0u, vids[0]);
56 e.setVertex(1u, vids[1]);
58 if (p.name == ply::vertex1) {
59 uint v0 = io::readPrimitiveType<uint>(file, p.type, end);
63 if (p.name == ply::vertex2) {
64 uint v1 = io::readPrimitiveType<uint>(file, p.type, end);
69 if (p.name >= ply::nx && p.name <= ply::nz) {
70 if constexpr (HasPerEdgeNormal<MeshType>) {
72 using Scalar = EdgeType::NormalType::ScalarType;
73 int a = p.name - ply::nx;
74 Scalar n = io::readPrimitiveType<Scalar>(file, p.type, end);
80 if (p.name >= ply::red && p.name <= ply::alpha) {
81 if constexpr (HasPerFaceColor<MeshType>) {
83 int a = p.name - ply::red;
85 io::readPrimitiveType<unsigned char>(file, p.type, end);
90 if (p.name == ply::quality) {
91 if constexpr (HasPerFaceQuality<MeshType>) {
92 using QualityType = EdgeType::QualityType;
95 io::readPrimitiveType<QualityType>(file, p.type, end);
100 if (p.name == ply::unknown) {
101 if constexpr (HasPerFaceCustomComponents<MeshType>) {
102 if (mesh.hasPerFaceCustomComponent(p.unknownPropertyName)) {
103 io::readCustomComponent(
104 file, e, p.unknownPropertyName, p.type, end);
113 uint s = io::readPrimitiveType<int>(file, p.listSizeType, end);
114 for (uint i = 0; i < s; ++i)
115 io::readPrimitiveType<int>(file, p.type, end);
118 io::readPrimitiveType<int>(file, p.type, end);
123template<EdgeConcept EdgeType, MeshConcept MeshType>
128 const std::list<PlyProperty>& edgeProperties)
130 Tokenizer spaceTokenizer = readAndTokenizeNextNonEmptyLine(file);
131 Tokenizer::iterator token = spaceTokenizer.begin();
132 for (
const PlyProperty& p : edgeProperties) {
133 if (token == spaceTokenizer.end()) {
134 throw MalformedFileException(
"Unexpected end of line.");
136 readPlyEdgeProperty(token, mesh, e, p);
140template<EdgeConcept EdgeType, MeshConcept MeshType>
145 const std::list<PlyProperty>& edgeProperties,
148 for (
const PlyProperty& p : edgeProperties) {
149 readPlyEdgeProperty(file, mesh, e, p, end);
153template<EdgeMeshConcept MeshType>
156 const PlyHeader& header,
157 const MeshType& mesh)
159 using EdgeType = MeshType::EdgeType;
162 if (header.format() == ply::ASCII) {
163 format.isBinary =
false;
165 else if (header.format() == ply::BINARY_BIG_ENDIAN) {
166 format.endian = std::endian::big;
170 std::vector<uint> vIndices = mesh.vertexCompactIndices();
172 for (
const EdgeType& e : mesh.
edges()) {
173 for (
const PlyProperty& p : header.edgeProperties()) {
174 bool hasBeenWritten =
false;
175 if (p.name == ply::vertex1) {
177 file, vIndices[mesh.index(e.vertex(0))], p.type, format);
178 hasBeenWritten =
true;
180 if (p.name == ply::vertex2) {
182 file, vIndices[mesh.index(e.vertex(1))], p.type, format);
183 hasBeenWritten =
true;
185 if (p.name >= ply::nx && p.name <= ply::nz) {
186 if constexpr (HasPerEdgeNormal<MeshType>) {
188 file, e.normal()[p.name - ply::nx], p.type, format);
189 hasBeenWritten =
true;
192 if (p.name >= ply::red && p.name <= ply::alpha) {
193 if constexpr (HasPerEdgeColor<MeshType>) {
195 file, e.color()[p.name - ply::red], p.type, format);
196 hasBeenWritten =
true;
199 if (p.name == ply::quality) {
200 if constexpr (HasPerEdgeQuality<MeshType>) {
201 io::writeProperty(file, e.quality(), p.type, format);
202 hasBeenWritten =
true;
205 if (!hasBeenWritten) {
208 io::writeProperty(file, 0, p.type, format);
211 if (!format.isBinary)
216template<EdgeMeshConcept MeshType, LoggerConcept LogType>
219 const PlyHeader& header,
223 using EdgeType = MeshType::EdgeType;
224 m.reserveEdges(header.numberEdges());
226 log.startProgress(
"Reading edges", header.numberEdges());
228 for (uint eid = 0; eid < header.numberEdges(); ++eid) {
229 uint eeid = m.addEdge();
230 EdgeType& e = m.edge(eeid);
231 if (header.format() == ply::ASCII) {
232 detail::readPlyEdgeTxt(file, e, m, header.edgeProperties());
235 std::endian end = header.format() == ply::BINARY_BIG_ENDIAN ?
238 detail::readPlyEdgeBin(file, e, m, header.edgeProperties(), end);
bool isPerEdgeNormalAvailable(const MeshType &m)
Returns true if the Normal component is available (enabled) in the Edge element of the input mesh m.
Definition edge_requirements.h:330
bool isPerFaceQualityAvailable(const MeshType &m)
Returns true if the Quality component is available (enabled) in the Face element of the input mesh m.
Definition face_requirements.h:451
bool isPerFaceColorAvailable(const MeshType &m)
Returns true if the Color component is available (enabled) in the Face element of the input mesh m.
Definition face_requirements.h:214
constexpr detail::EdgesView edges
A view that allows to iterate overt the Edge elements of an object.
Definition edge.h:52