9 std::ofstream ofs(path.
native());
12 ofs <<
"format ascii 1.0\n";
13 ofs <<
"comment Exported by " <<
CODE_NAME <<
"\n";
17 ofs <<
"element vertex " << mesh.
vertices.size() <<
"\n";
18 ofs <<
"property float x\n";
19 ofs <<
"property float y\n";
20 ofs <<
"property float z\n";
21 ofs <<
"element face " << mesh.
faces.size() <<
"\n";
22 ofs <<
"property list int int vertex_index\n";
23 ofs <<
"end_header\n";
27 ofs << v[
X] <<
" " << v[
Y] <<
" " << v[
Z] << std::endl;
29 for (
Size i = 0; i < mesh.
faces.size(); ++i) {
30 ofs <<
"3 " << mesh.
faces[i][0] <<
" " << mesh.
faces[i][1] <<
" " << mesh.
faces[i][2]
34 }
catch (
const std::exception& e) {
40 if (line.size() < format.size()) {
43 if (line.substr(0, format.size()) == format) {
45 return line.substr(
min(line.size(), format.size() + 1));
53 std::ifstream ifs(path.
native());
57 if (!std::getline(ifs, line) || line !=
"ply") {
58 throw IoError(
"File does not have a valid .ply format");
60 if (!std::getline(ifs, line) || line !=
"format ascii 1.0") {
61 throw IoError(
"Only ascii format of the .ply file is currently supported");
68 while (std::getline(ifs, line)) {
69 if (stripStart(line,
"comment")) {
71 }
else if (stripStart(line,
"end_header")) {
74 vertexCnt = std::stoul(vertexStr.value());
76 faceCnt = std::stoul(faceStr.value());
78 properties.
push(property.value());
83 if (faceCnt ==
Size(-1) || vertexCnt ==
Size(-1)) {
84 throw IoError(
"Header did not contain number of faces or vertices");
85 }
else if (properties.
size() < 3 || properties[0] !=
"x" || properties[1] !=
"y" ||
86 properties[2] !=
"z") {
88 "Currently, only files where x, y, z are the first 3 float properties are supported");
93 while (vertices.
size() < vertexCnt) {
94 std::getline(ifs, line);
99 std::stringstream ss(line);
101 ss >> v[
X] >> v[
Y] >> v[
Z];
103 for (
Size i = 0; i < properties.
size() - 3; ++i) {
108 throw IoError(
"Invalid line format when reading the vertex data");
112 if (vertices.
size() != vertexCnt) {
113 throw IoError(
"Incorrect number of vertices in the file");
118 while (triangles.
size() < faceCnt) {
119 std::getline(ifs, line);
124 std::stringstream ss(line);
125 ss >> cnt >> i >> j >> k;
126 if (!ss || cnt != 3) {
127 throw IoError(
"Invalid line format when reading the index data");
129 triangles.
emplaceBack(vertices[i], vertices[j], vertices[k]);
133 }
catch (
const std::exception& e) {
134 return makeUnexpected<Array<Triangle>>(e.what());
139 : lengthUnit(lengthUnit) {}
149 std::ifstream ifs(path.
native());
150 Size vertexCnt, triangleCnt;
151 ifs >> vertexCnt >> triangleCnt;
153 throw IoError(
"Invalid format: cannot read file header");
159 for (
Size vertexIdx = 0; vertexIdx < vertexCnt; ++vertexIdx) {
160 ifs >> dummy >> v[
X] >> v[
Y] >> v[
Z];
167 for (
Size triangleIdx = 0; triangleIdx < triangleCnt; ++triangleIdx) {
168 ifs >> dummy >> i >> j >> k;
170 triangles.
emplaceBack(vertices[i - 1], vertices[j - 1], vertices[k - 1]);
174 }
catch (
const std::exception& e) {
175 return makeUnexpected<Array<Triangle>>(e.what());
187 std::ifstream ifs(path.
native());
191 std::string identifier;
194 if (identifier ==
"v") {
196 ifs >> v[
X] >> v[
Y] >> v[
Z];
198 }
else if (identifier ==
"f") {
201 triangles.
emplaceBack(vertices[i - 1], vertices[j - 1], vertices[k - 1]);
207 }
catch (
const std::exception& e) {
208 return makeUnexpected<Array<Triangle>>(e.what());
214 if (extension ==
"ply") {
215 return makeAuto<PlyFile>();
216 }
else if (extension ==
"obj") {
217 return makeAuto<ObjFile>();
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
constexpr char CODE_NAME[]
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
AutoPtr< IMeshFile > getMeshFile(const Path &path)
Deduces mesh type from extension of given path.
Mesh getMeshFromTriangles(ArrayView< const Triangle > triangles, const Float eps)
Converts array of triangles into a mesh.
#define NAMESPACE_SPH_END
const NothingType NOTHING
const SuccessTag SUCCESS
Global constant for successful outcome.
INLINE Outcome makeFailed(TArgs &&... args)
Constructs failed object with error message.
Object providing safe access to continuous memory of data.
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
StorageType & emplaceBack(TArgs &&... args)
Constructs a new element at the end of the array in place, using the provided arguments.
INLINE TCounter size() const noexcept
Wrapper of pointer that deletes the resource from destructor.
Wrapper of type that either contains a value of given type, or an error message.
Exception thrown when file cannot be read, it has invalid format, etc.
virtual Expected< Array< Triangle > > load(const Path &path) override
virtual Outcome save(const Path &path, ArrayView< const Triangle > triangles) override
Object representing a path on a filesystem.
std::string native() const
Returns the native version of the path.
Path extension() const
Returns the extension of the filename.
virtual Expected< Array< Triangle > > load(const Path &path) override
virtual Outcome save(const Path &path, ArrayView< const Triangle > triangles) override
virtual Expected< Array< Triangle > > load(const Path &path) override
virtual Outcome save(const Path &path, ArrayView< const Triangle > triangles) override
TabFile(const Float lengthUnit=1.e3_f)