27enum class IOMode { ASCII = 0, BINARY };
50 std::size_t height{0};
66 const volcart::filesystem::path& path,
IOMode mode = IOMode::BINARY)
83 const volcart::filesystem::path& path,
IOMode mode = IOMode::BINARY)
99 const volcart::filesystem::path& path,
101 IOMode mode = IOMode::BINARY)
113 const volcart::filesystem::path& path,
115 IOMode mode = IOMode::BINARY)
130 std::stringstream ss;
131 ss <<
"size: " << ps.
size() << std::endl;
132 ss <<
"dim: " << T::channels << std::endl;
133 ss <<
"ordered: false" << std::endl;
137 if (std::is_same<typename T::value_type, int>::value) {
138 ss <<
"int" << std::endl;
139 }
else if (std::is_same<typename T::value_type, float>::value) {
140 ss <<
"float" << std::endl;
141 }
else if (std::is_same<typename T::value_type, double>::value) {
142 ss <<
"double" << std::endl;
144 auto msg =
"unsupported type";
149 ss << PointSet<T>::HEADER_TERMINATOR << std::endl;
156 std::stringstream ss;
157 ss <<
"width: " << ps.
width() << std::endl;
158 ss <<
"height: " << ps.
height() << std::endl;
159 ss <<
"dim: " << T::channels << std::endl;
160 ss <<
"ordered: true" << std::endl;
164 if (std::is_same<typename T::value_type, int>::value) {
165 ss <<
"int" << std::endl;
166 }
else if (std::is_same<typename T::value_type, float>::value) {
167 ss <<
"float" << std::endl;
168 }
else if (std::is_same<typename T::value_type, double>::value) {
169 ss <<
"double" << std::endl;
171 auto msg =
"unsupported type";
176 ss << PointSet<T>::HEADER_TERMINATOR << std::endl;
191 std::regex comments{
"^#"};
192 std::regex width{
"^width"};
193 std::regex height{
"^height"};
194 std::regex dim{
"^dim"};
195 std::regex ordering{
"^ordered"};
196 std::regex type{
"^type"};
197 std::regex size{
"^size"};
198 std::regex version{
"^version"};
199 std::regex validTypes{
"^(float)|(double)|(int)"};
204 std::vector<std::string> strs;
206 while (std::getline(infile, line)) {
208 strs =
split(line,
':');
210 std::begin(strs), std::end(strs), [](
auto& s) {
trim(s); });
215 if (std::regex_match(strs[0], comments)) {
220 else if (std::regex_match(strs[0], width)) {
221 h.width = std::stoul(strs[1]);
225 else if (std::regex_match(strs[0], height)) {
226 h.height = std::stoul(strs[1]);
230 else if (std::regex_match(strs[0], size)) {
231 h.size = std::stoul(strs[1]);
235 else if (std::regex_match(strs[0], dim)) {
236 auto parsedDim = std::stoul(strs[1]);
237 if (parsedDim != T::channels) {
239 "Incorrect dimension read for template specification";
246 else if (std::regex_match(strs[0], ordering)) {
248 if (strs[1] ==
"true") {
250 }
else if (strs[1] ==
"false") {
253 auto msg =
"'ordered' key must have value 'true'/'false'";
259 else if (std::regex_match(strs[0], type)) {
260 if (!std::regex_match(strs[1], validTypes)) {
261 auto msg =
"Valid types are int, float, double. Got: '" +
267 std::string readerType;
268 if (std::is_same_v<typename T::value_type, int>) {
270 }
else if (std::is_same_v<typename T::value_type, float>) {
271 readerType =
"float";
272 }
else if (std::is_same_v<typename T::value_type, double>) {
273 readerType =
"double";
277 if (strs[1] != readerType) {
278 auto msg =
"Type mismatch: vcps filetype '" + strs[1] +
279 "' not compatible with reader type '" +
287 else if (std::regex_match(strs[0], version)) {
288 auto fileVersion = std::stoi(strs[1]);
290 auto msg =
"Version mismatch. VCPS file version is " +
291 strs[1] +
", processing version is " +
299 else if (std::regex_match(line, headerTerminator)) {
311 if (!ordered && h.width > 0 && h.height > 0) {
312 h.size = h.width * h.height;
316 if (h.type.empty()) {
317 const auto* msg =
"Must provide type";
319 }
else if (h.dim == 0) {
320 const auto* msg =
"Must provide dim";
322 }
else if (!ordered && h.size == 0) {
323 const auto* msg =
"Unordered pointsets must have a size";
325 }
else if (ordered && (h.width == 0 || h.height == 0)) {
327 "Ordered pointsets must have a nonzero width and height";
329 }
else if (ordered && !h.ordered) {
331 "Tried to read unordered pointset with ordered PointSetIO";
344 std::ifstream infile{path.string()};
345 if (!infile.is_open()) {
346 auto msg =
"could not open file '" + path.string() +
"'";
354 for (std::size_t i = 0; i < header.size; ++i) {
355 std::array<typename T::value_type, T::channels> values;
356 for (std::size_t d = 0; d < header.dim; ++d) {
359 ps.push_back(T{values.data()});
367 const volcart::filesystem::path& path)
369 std::ifstream infile{path.string()};
370 if (!infile.is_open()) {
371 auto msg =
"could not open file '" + path.string() +
"'";
379 std::vector<T> points;
380 points.reserve(header.width);
381 for (std::size_t h = 0; h < header.height; ++h) {
382 for (std::size_t w = 0; w < header.width; ++w) {
383 std::array<typename T::value_type, T::channels> values;
384 for (std::size_t d = 0; d < header.dim; ++d) {
385 infile >> values.at(d);
387 points.emplace_back(values.data());
399 std::ifstream infile{path.string(), std::ios::binary};
400 if (!infile.is_open()) {
401 auto msg =
"could not open file '" + path.string() +
"'";
408 std::size_t typeBytes{};
409 if (header.type ==
"float") {
410 typeBytes =
sizeof(float);
411 }
else if (header.type ==
"double") {
412 typeBytes =
sizeof(double);
413 }
else if (header.type ==
"int") {
414 typeBytes =
sizeof(int);
419 for (std::size_t i = 0; i < header.size; ++i) {
420 auto nbytes = header.dim * typeBytes;
421 infile.read(
reinterpret_cast<char*
>(t.val), nbytes);
430 const volcart::filesystem::path& path)
432 std::ifstream infile{path.string(), std::ios::binary};
433 if (!infile.is_open()) {
434 auto msg =
"could not open file '" + path.string() +
"'";
441 std::size_t typeBytes =
sizeof(int);
442 if (header.type ==
"float") {
443 typeBytes =
sizeof(float);
444 }
else if (header.type ==
"double") {
445 typeBytes =
sizeof(double);
446 }
else if (header.type ==
"int") {
447 typeBytes =
sizeof(int);
449 auto msg =
"Unrecognized type: " + header.type;
455 std::size_t nbytes = header.width * header.dim * typeBytes;
456 std::vector<T> points(header.width, 0);
457 points.reserve(header.width);
458 for (std::size_t h = 0; h < header.height; ++h) {
459 infile.read(
reinterpret_cast<char*
>(points.data()), nbytes);
470 const volcart::filesystem::path& path,
PointSet<T> ps)
472 std::ofstream outfile{path.string()};
473 if (!outfile.is_open()) {
474 auto msg =
"could not open file '" + path.string() +
"'";
480 for (
const auto& p : ps) {
481 for (std::size_t i = 0; i < T::channels; ++i) {
482 outfile << p(i) <<
" ";
484 outfile << std::endl;
489 if (outfile.fail()) {
490 auto msg =
"failure writing file '" + path.string() +
"'";
497 const volcart::filesystem::path& path,
PointSet<T> ps)
499 std::ofstream outfile{path.string(), std::ios::binary};
500 if (!outfile.is_open()) {
501 auto msg =
"could not open file '" + path.string() +
"'";
506 outfile.write(header.c_str(), header.size());
508 for (
const auto& p : ps) {
509 auto nbytes = T::channels *
sizeof(
typename T::value_type);
510 outfile.write(
reinterpret_cast<const char*
>(p.val), nbytes);
515 if (outfile.fail()) {
516 auto msg =
"failure writing file '" + path.string() +
"'";
525 std::ofstream outfile{path.string()};
526 if (!outfile.is_open()) {
527 auto msg =
"could not open file '" + path.string() +
"'";
533 for (
const auto& p : ps) {
534 for (std::size_t i = 0; i < T::channels; ++i) {
535 outfile << p(i) <<
" ";
537 outfile << std::endl;
542 if (outfile.fail()) {
543 auto msg =
"failure writing file '" + path.string() +
"'";
552 std::ofstream outfile{path.string(), std::ios::binary};
553 if (!outfile.is_open()) {
554 auto msg =
"could not open file '" + path.string() +
"'";
559 outfile.write(header.c_str(), header.size());
561 for (
const auto& p : ps) {
562 auto nbytes = T::channels *
sizeof(
typename T::value_type);
563 outfile.write(
reinterpret_cast<const char*
>(p.val), nbytes);
568 if (outfile.fail()) {
569 auto msg =
"failure writing file '" + path.string() +
"'";
Holds a collection of ordered points.
std::size_t height() const
Return the number of rows in the OrderedPointSet.
std::size_t width() const
Return the number of columns in the OrderedPointSet.
Read and write PointSet and OrderedPointSet.
static OrderedPointSet< T > ReadOrderedPointSetAscii(const volcart::filesystem::path &path)
Read an ASCII OrderedPointSet.
static void WritePointSetBinary(const volcart::filesystem::path &path, PointSet< T > ps)
Write a binary PointSet.
static OrderedPointSet< T > ReadOrderedPointSet(const volcart::filesystem::path &path, IOMode mode=IOMode::BINARY)
Read OrderedPointSet from file.
static PointSet< T > ReadPointSet(const volcart::filesystem::path &path, IOMode mode=IOMode::BINARY)
Read PointSet from file.
static std::string MakeOrderedHeader(OrderedPointSet< T > ps)
Generate an OrderedPointSet header string.
static void WriteOrderedPointSet(const volcart::filesystem::path &path, const OrderedPointSet< T > &ps, IOMode mode=IOMode::BINARY)
Write an OrderedPointSet to disk.
static Header ParseHeader(std::ifstream &infile, bool ordered=true)
Parse a PointSet/OrderedPointSet file header.
static PointSet< T > ReadPointSetAscii(const volcart::filesystem::path &path)
Read an ASCII PointSet.
static void WritePointSetAscii(const volcart::filesystem::path &path, PointSet< T > ps)
Write an ASCII PointSet.
static std::string MakeHeader(PointSet< T > ps)
Generate a PointSet header string.
static OrderedPointSet< T > ReadOrderedPointSetBinary(const volcart::filesystem::path &path)
Read a binary OrderedPointSet.
static PointSet< T > ReadPointSetBinary(const volcart::filesystem::path &path)
Read a binary PointSet.
static void WriteOrderedPointSetBinary(const volcart::filesystem::path &path, OrderedPointSet< T > ps)
Write a binary OrderedPointSet.
static void WriteOrderedPointSetAscii(const volcart::filesystem::path &path, OrderedPointSet< T > ps)
Write an ASCII OrderedPointSet.
static void WritePointSet(const volcart::filesystem::path &path, const PointSet< T > &ps, IOMode mode=IOMode::BINARY)
Write a PointSet to disk.
Holds a collection of points.
std::size_t size() const
Get the size of the PointSet.
IOMode
IO Mode for file readers/writers.
Volume Cartographer library
static void to_lower(std::string &s)
Convert string characters to lower case (in place)
static void trim(std::string &s)
Trim from both ends (in place)
static std::vector< std::string > split(const std::string &s, const Ds &... ds)
Split a string by a delimiter.