Visual Computing Library  devel
Loading...
Searching...
No Matches
edge.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_IO_MESH_PLY_DETAIL_EDGE_H
24#define VCL_IO_MESH_PLY_DETAIL_EDGE_H
25
26#include "header.h"
27
28#include <vclib/io/write.h>
29
30namespace vcl::detail {
31
32template<EdgeMeshConcept MeshType, EdgeConcept EdgeType, typename Stream>
33void readPlyEdgeProperty(
34 Stream& file,
35 MeshType& mesh,
36 EdgeType& e,
37 PlyProperty p,
38 std::endian end = std::endian::little)
39{
40 bool hasBeenRead = false;
41 // loading vertex indices in case of list
42 if (p.name == ply::vertex_indices) {
43 std::vector<uint> vids; // contains the vertex ids of the actual edge
44 uint eSize = io::readPrimitiveType<uint>(file, p.listSizeType, end);
45 vids.resize(eSize);
46 for (uint i = 0; i < eSize; ++i) {
47 vids[i] = io::readPrimitiveType<size_t>(file, p.type, end);
48 if (vids[i] >= mesh.vertexNumber()) {
49 throw MalformedFileException(
50 "Bad vertex index for edge " + std::to_string(e.index()));
51 }
52 }
53 hasBeenRead = true;
54 e.setVertex(0u, vids[0]);
55 e.setVertex(1u, vids[1]);
56 }
57 if (p.name == ply::vertex1) { // loading vertex1 index
58 uint v0 = io::readPrimitiveType<uint>(file, p.type, end);
59 hasBeenRead = true;
60 e.setVertex(0u, v0);
61 }
62 if (p.name == ply::vertex2) { // loading vertex2 index
63 uint v1 = io::readPrimitiveType<uint>(file, p.type, end);
64 hasBeenRead = true;
65 e.setVertex(1u, v1);
66 }
67 // loading one of the normal components
68 if (p.name >= ply::nx && p.name <= ply::nz) {
69 if constexpr (HasPerEdgeNormal<MeshType>) {
70 if (isPerEdgeNormalAvailable(mesh)) {
71 using Scalar = EdgeType::NormalType::ScalarType;
72 int a = p.name - ply::nx;
73 Scalar n = io::readPrimitiveType<Scalar>(file, p.type, end);
74 hasBeenRead = true;
75 }
76 }
77 }
78 // loading one of the color components
79 if (p.name >= ply::red && p.name <= ply::alpha) {
80 if constexpr (HasPerFaceColor<MeshType>) {
81 if (isPerFaceColorAvailable(mesh)) {
82 int a = p.name - ply::red;
83 unsigned char c =
84 io::readPrimitiveType<unsigned char>(file, p.type, end);
85 hasBeenRead = true;
86 }
87 }
88 }
89 if (p.name == ply::quality) { // loading the quality component
90 if constexpr (HasPerFaceQuality<MeshType>) {
91 using QualityType = EdgeType::QualityType;
92 if (isPerFaceQualityAvailable(mesh)) {
93 QualityType s =
94 io::readPrimitiveType<QualityType>(file, p.type, end);
95 hasBeenRead = true;
96 }
97 }
98 }
99 if (p.name == ply::unknown) {
100 if constexpr (HasPerFaceCustomComponents<MeshType>) {
101 if (mesh.hasPerFaceCustomComponent(p.unknownPropertyName)) {
102 io::readCustomComponent(
103 file, e, p.unknownPropertyName, p.type, end);
104 hasBeenRead = true;
105 }
106 }
107 }
108 // if nothing has been read, it means that there is some data we don't know
109 // we still need to read and discard what we read
110 if (!hasBeenRead) {
111 if (p.list) {
112 uint s = io::readPrimitiveType<int>(file, p.listSizeType, end);
113 for (uint i = 0; i < s; ++i)
114 io::readPrimitiveType<int>(file, p.type, end);
115 }
116 else {
117 io::readPrimitiveType<int>(file, p.type, end);
118 }
119 }
120}
121
122template<EdgeConcept EdgeType, MeshConcept MeshType>
123void readPlyEdgeTxt(
124 std::istream& file,
125 EdgeType& e,
126 MeshType& mesh,
127 const std::list<PlyProperty>& edgeProperties)
128{
129 Tokenizer spaceTokenizer = readAndTokenizeNextNonEmptyLine(file);
130 Tokenizer::iterator token = spaceTokenizer.begin();
131 for (const PlyProperty& p : edgeProperties) {
132 if (token == spaceTokenizer.end()) {
133 throw MalformedFileException("Unexpected end of line.");
134 }
135 readPlyEdgeProperty(token, mesh, e, p);
136 }
137}
138
139template<EdgeConcept EdgeType, MeshConcept MeshType>
140void readPlyEdgeBin(
141 std::istream& file,
142 EdgeType& e,
143 MeshType& mesh,
144 const std::list<PlyProperty>& edgeProperties,
145 std::endian end)
146{
147 for (const PlyProperty& p : edgeProperties) {
148 readPlyEdgeProperty(file, mesh, e, p, end);
149 }
150}
151
152template<EdgeMeshConcept MeshType>
153void writePlyEdges(
154 std::ostream& file,
155 const PlyHeader& header,
156 const MeshType& mesh)
157{
158 using EdgeType = MeshType::EdgeType;
159
160 FileType format;
161 if (header.format() == ply::ASCII) {
162 format.isBinary = false;
163 }
164 else if (header.format() == ply::BINARY_BIG_ENDIAN) {
165 format.endian = std::endian::big;
166 }
167
168 // indices of vertices that do not consider deleted vertices
169 std::vector<uint> vIndices = mesh.vertexCompactIndices();
170
171 for (const EdgeType& e : mesh.edges()) {
172 for (const PlyProperty& p : header.edgeProperties()) {
173 bool hasBeenWritten = false;
174 if (p.name == ply::vertex1) {
175 io::writeProperty(
176 file, vIndices[mesh.index(e.vertex(0))], p.type, format);
177 hasBeenWritten = true;
178 }
179 if (p.name == ply::vertex2) {
180 io::writeProperty(
181 file, vIndices[mesh.index(e.vertex(1))], p.type, format);
182 hasBeenWritten = true;
183 }
184 if (p.name >= ply::nx && p.name <= ply::nz) {
185 if constexpr (HasPerEdgeNormal<MeshType>) {
186 io::writeProperty(
187 file, e.normal()[p.name - ply::nx], p.type, format);
188 hasBeenWritten = true;
189 }
190 }
191 if (p.name >= ply::red && p.name <= ply::alpha) {
192 if constexpr (HasPerEdgeColor<MeshType>) {
193 io::writeProperty(
194 file, e.color()[p.name - ply::red], p.type, format);
195 hasBeenWritten = true;
196 }
197 }
198 if (p.name == ply::quality) {
199 if constexpr (HasPerEdgeQuality<MeshType>) {
200 io::writeProperty(file, e.quality(), p.type, format);
201 hasBeenWritten = true;
202 }
203 }
204 if (!hasBeenWritten) {
205 // be sure to write something if the header declares some
206 // property that is not in the mesh
207 io::writeProperty(file, 0, p.type, format);
208 }
209 }
210 if (!format.isBinary)
211 file << std::endl;
212 }
213}
214
215template<EdgeMeshConcept MeshType, LoggerConcept LogType>
216void readPlyEdges(
217 std::istream& file,
218 const PlyHeader& header,
219 MeshType& m,
220 LogType& log)
221{
222 using EdgeType = MeshType::EdgeType;
223 m.reserveEdges(header.numberEdges());
224
225 log.startProgress("Reading edges", header.numberEdges());
226
227 for (uint eid = 0; eid < header.numberEdges(); ++eid) {
228 uint eeid = m.addEdge();
229 EdgeType& e = m.edge(eeid);
230 if (header.format() == ply::ASCII) {
231 detail::readPlyEdgeTxt(file, e, m, header.edgeProperties());
232 }
233 else {
234 std::endian end = header.format() == ply::BINARY_BIG_ENDIAN ?
235 std::endian::big :
236 std::endian::little;
237 detail::readPlyEdgeBin(file, e, m, header.edgeProperties(), end);
238 }
239
240 log.progress(eid);
241 }
242
243 log.endProgress();
244}
245
246} // namespace vcl::detail
247
248#endif // VCL_IO_MESH_PLY_DETAIL_EDGE_H
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:486
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:713
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:476
constexpr detail::EdgesView edges
A view that allows to iterate overt the Edge elements of an object.
Definition edge.h:84