diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 4566857..7f3d7b2 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -32,4 +32,5 @@ add_example(process_ex OFF) add_example(array_ex OFF) add_example(gmt_ex OFF) add_example(gnuplot_ex OFF) -add_example(stl_io_ex OFF) \ No newline at end of file +add_example(stl_io_ex OFF) +add_example(ply_io_ex ON) \ No newline at end of file diff --git a/example/ply_io_ex.cpp b/example/ply_io_ex.cpp new file mode 100644 index 0000000..d402110 --- /dev/null +++ b/example/ply_io_ex.cpp @@ -0,0 +1,44 @@ +/******************************************************** + * ██████╗ ██████╗████████╗██╗ + * ██╔════╝ ██╔════╝╚══██╔══╝██║ + * ██║ ███╗██║ ██║ ██║ + * ██║ ██║██║ ██║ ██║ + * ╚██████╔╝╚██████╗ ██║ ███████╗ + * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ + * Geophysical Computational Tools & Library (GCTL) + * + * Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn) + * + * GCTL is distributed under a dual licensing scheme. You can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 2 + * of the License, or (at your option) any later version. You should have + * received a copy of the GNU Lesser General Public License along with this + * program. If not, see . + * + * If the terms and conditions of the LGPL v.2. would prevent you from using + * the GCTL, please consider the option to obtain a commercial license for a + * fee. These licenses are offered by the GCTL's original author. As a rule, + * licenses are provided "as-is", unlimited in time for a one time fee. Please + * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget + * to include some description of your company and the realm of its activities. + * Also add information on how to contact you by electronic and paper mail. + ******************************************************/ + + #include "../lib/core.h" + #include "../lib/io.h" + + using namespace gctl; + + int main(int argc, char const *argv[]) try + { + array nodes; + array tris; + read_ply_binary("tmp_binary", nodes, tris); + save_ply_ascii("tmp", nodes, tris); + return 0; + } + catch(std::exception &e) + { + GCTL_ShowWhatError(e.what(), GCTL_ERROR_ERROR, 0, 0, 0); + } \ No newline at end of file diff --git a/lib/io.h b/lib/io.h index 40b9e7b..cc994aa 100644 --- a/lib/io.h +++ b/lib/io.h @@ -39,5 +39,6 @@ #include "io/triangle_io.h" #include "io/off_io.h" #include "io/stl_io.h" +#include "io/ply_io.h" #endif // _GCTL_IO_H \ No newline at end of file diff --git a/lib/io/off_io.h b/lib/io/off_io.h index 6d6d4b9..b9cb56f 100644 --- a/lib/io/off_io.h +++ b/lib/io/off_io.h @@ -36,7 +36,7 @@ namespace gctl { template - void read_Geomview_off(std::string filename, array> &nodes, + void read_off_acsii(std::string filename, array> &nodes, array> &facets) { std::ifstream infile; @@ -120,7 +120,7 @@ namespace gctl } template - void save_Geomview_off(std::string filename, const array> &nodes, + void save_off_ascii(std::string filename, const array> &nodes, const array> &facets) { std::ofstream outfile; diff --git a/lib/io/ply_io.h b/lib/io/ply_io.h new file mode 100644 index 0000000..be70d0c --- /dev/null +++ b/lib/io/ply_io.h @@ -0,0 +1,216 @@ +/******************************************************** + * ██████╗ ██████╗████████╗██╗ + * ██╔════╝ ██╔════╝╚══██╔══╝██║ + * ██║ ███╗██║ ██║ ██║ + * ██║ ██║██║ ██║ ██║ + * ╚██████╔╝╚██████╗ ██║ ███████╗ + * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ + * Geophysical Computational Tools & Library (GCTL) + * + * Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn) + * + * GCTL is distributed under a dual licensing scheme. You can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 2 + * of the License, or (at your option) any later version. You should have + * received a copy of the GNU Lesser General Public License along with this + * program. If not, see . + * + * If the terms and conditions of the LGPL v.2. would prevent you from using + * the GCTL, please consider the option to obtain a commercial license for a + * fee. These licenses are offered by the GCTL's original author. As a rule, + * licenses are provided "as-is", unlimited in time for a one time fee. Please + * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget + * to include some description of your company and the realm of its activities. + * Also add information on how to contact you by electronic and paper mail. + ******************************************************/ + +#ifndef _GCTL_PLY_IO_H +#define _GCTL_PLY_IO_H + +// library's head file +#include "../core.h" +#include "../utility.h" +#include "../geometry.h" + +namespace gctl +{ + template + void read_ply_ascii(std::string filename, array> &nodes, + array> &facets) + { + std::ifstream infile; + open_infile(infile, filename, ".ply"); + + int n, f; + std::string line; + std::stringstream ss; + while (std::getline(infile, line)) + { + if (sscanf(line.c_str(), "element vertex %d", &n)==1) nodes.resize(n); + if (sscanf(line.c_str(), "element face %d", &f)==1) facets.resize(f); + if (line == "end_header") + { + if (nodes.empty() || facets.empty()) + { + infile.close(); + throw std::runtime_error("[gctl::read_ply_ascii] Invalid node or facet sizes."); + } + + for (size_t i = 0; i < nodes.size(); ++i) + { + std::getline(infile, line); + sscanf(line.c_str(), "%lf %lf %lf", &nodes[i].x, &nodes[i].y, &nodes[i].z); + nodes[i].id = i; + } + + for (size_t i = 0; i < facets.size(); ++i) + { + std::getline(infile, line); + int d, v1, v2, v3; + sscanf(line.c_str(), "%d %d %d %d", &d, &v1, &v2, &v3); + facets[i].vert[0] = &nodes[v1]; + facets[i].vert[1] = &nodes[v2]; + facets[i].vert[2] = &nodes[v3]; + facets[i].id = i; + } + break; + } + } + + infile.close(); + return; + } + + template + void save_ply_ascii(std::string filename, const array> &nodes, + const array> &facets) + { + time_t now = time(0); + char* dt = ctime(&now); + + std::ofstream outfile; + open_outfile(outfile, filename, ".ply"); + + outfile << "ply" << std::endl; + outfile << "format ascii 1.0" << std::endl; + outfile << "comment Created by GCTL at " << dt; + outfile << "element vertex " << nodes.size() << std::endl; + outfile << "property float x" << std::endl; + outfile << "property float y" << std::endl; + outfile << "property float z" << std::endl; + outfile << "element face " << facets.size() << std::endl; + outfile << "property list uchar int vertex_indices" << std::endl; + outfile << "end_header" << std::endl; + + for (size_t i = 0; i < nodes.size(); ++i) + { + outfile << nodes[i].x << " " << nodes[i].y << " " << nodes[i].z << std::endl; + } + + for (size_t i = 0; i < facets.size(); ++i) + { + outfile << "3 " << facets[i].vert[0]->id << " " << facets[i].vert[1]->id << " " << facets[i].vert[2]->id << std::endl; + } + outfile.close(); + return; + } + + template + void read_ply_binary(std::string filename, array> &nodes, + array> &facets) + { + std::ifstream infile; + open_infile(infile, filename, ".ply", std::ios::binary); + + int n, f; + std::string line; + std::stringstream ss; + while (std::getline(infile, line)) + { + if (sscanf(line.c_str(), "element vertex %d", &n)==1) nodes.resize(n); + if (sscanf(line.c_str(), "element face %d", &f)==1) facets.resize(f); + if (line == "end_header") + { + if (nodes.empty() || facets.empty()) + { + infile.close(); + throw std::runtime_error("[gctl::read_ply_ascii] Invalid node or facet sizes."); + } + + float x, y, z; + for (size_t i = 0; i < nodes.size(); ++i) + { + infile.read((char*)&x, sizeof(float)); + infile.read((char*)&y, sizeof(float)); + infile.read((char*)&z, sizeof(float)); + nodes[i].x = x; + nodes[i].y = y; + nodes[i].z = z; + nodes[i].id = i; + } + + unsigned char num_vertices; + int v1, v2, v3; + for (size_t i = 0; i < facets.size(); ++i) + { + infile.read((char*)&num_vertices, sizeof(unsigned char)); + infile.read((char*)&v1, sizeof(int)); + infile.read((char*)&v2, sizeof(int)); + infile.read((char*)&v3, sizeof(int)); + facets[i].vert[0] = &nodes[v1]; + facets[i].vert[1] = &nodes[v2]; + facets[i].vert[2] = &nodes[v3]; + facets[i].id = i; + } + break; + } + } + + infile.close(); + return; + } + + template + void save_ply_binary(std::string filename, const array> &nodes, + const array> &facets) + { + std::ofstream outfile; + open_outfile(outfile, filename, ".ply", std::ios::binary); + + outfile << "ply\n" + << "format binary_little_endian 1.0\n" + << "comment Created by GCTL\n" + << "element vertex " << nodes.size() << "\n" + << "property float x\n" + << "property float y\n" + << "property float z\n" + << "element face " << facets.size() << "\n" + << "property list uchar int vertex_indices\n" + << "end_header\n"; + + float x, y, z; + for (size_t i = 0; i < nodes.size(); ++i) + { + x = nodes[i].x; + y = nodes[i].y; + z = nodes[i].z; + outfile.write((char*)&x, sizeof(float)); + outfile.write((char*)&y, sizeof(float)); + outfile.write((char*)&z, sizeof(float)); + } + + unsigned char num_vertices = 3; + for (size_t i = 0; i < facets.size(); ++i) + { + outfile.write((char*)&num_vertices, sizeof(unsigned char)); + outfile.write((char*)&facets[i].vert[0]->id, sizeof(int)); + outfile.write((char*)&facets[i].vert[1]->id, sizeof(int)); + outfile.write((char*)&facets[i].vert[2]->id, sizeof(int)); + } + outfile.close(); + return; + } +}; + +#endif // _GCTL_PLY_IO_H \ No newline at end of file