9#ifndef PECLET_CORE_GEOM_VTI_IO_HPP
10#define PECLET_CORE_GEOM_VTI_IO_HPP
24inline void writeVti(
const std::string& path,
const GridSdf& g,
const std::string& name =
"sdf") {
25 std::ofstream f(path);
27 throw std::runtime_error(
"writeVti: cannot open " + path);
29 f <<
"<?xml version=\"1.0\"?>\n"
30 <<
"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\">\n"
31 <<
" <ImageData WholeExtent=\"0 " << nx - 1 <<
" 0 " << ny - 1 <<
" 0 " << nz - 1 <<
"\""
34 <<
" <Piece Extent=\"0 " << nx - 1 <<
" 0 " << ny - 1 <<
" 0 " << nz - 1 <<
"\">\n"
35 <<
" <PointData Scalars=\"" << name <<
"\">\n"
36 <<
" <DataArray type=\"Float32\" Name=\"" << name <<
"\" format=\"ascii\">\n";
37 f.setf(std::ios::scientific);
39 for (std::size_t i = 0; i < g.
values.size(); ++i) {
40 f << g.
values[i] << (((i + 1) %
static_cast<std::size_t
>(nx) == 0) ?
'\n' :
' ');
42 f <<
"\n </DataArray>\n </PointData>\n </Piece>\n </ImageData>\n</VTKFile>\n";
46inline std::string
vtiAttr(
const std::string& s,
const std::string& key) {
47 std::string needle = key +
"=\"";
48 auto p = s.find(needle);
49 if (p == std::string::npos)
50 throw std::runtime_error(
"readVti: missing attribute " + key);
52 auto e = s.find(
'"', p);
53 return s.substr(p, e - p);
59 std::ifstream f(path);
61 throw std::runtime_error(
"readVti: cannot open " + path);
62 std::stringstream buf;
64 const std::string s = buf.str();
67 Index x0, x1, y0, y1, z0, z1;
68 std::istringstream(
detail::vtiAttr(s,
"WholeExtent")) >> x0 >> x1 >> y0 >> y1 >> z0 >> z1;
69 g.
dims = {x1 - x0 + 1, y1 - y0 + 1, z1 - z0 + 1};
73 auto da = s.find(
"<DataArray");
74 if (da == std::string::npos)
75 throw std::runtime_error(
"readVti: no DataArray");
76 auto open = s.find(
'>', da);
77 auto close = s.find(
"</DataArray>", open);
78 std::istringstream data(s.substr(open + 1, close - open - 1));
80 std::size_t n =
static_cast<std::size_t
>(g.
dims[0]) * g.
dims[1] * g.
dims[2];
82 for (std::size_t i = 0; i < n; ++i) {
100 const std::string& name =
"vector") {
101 std::ofstream f(path);
103 throw std::runtime_error(
"writeVtiVector: cannot open " + path);
105 f <<
"<?xml version=\"1.0\"?>\n"
106 <<
"<VTKFile type=\"ImageData\" version=\"1.0\" byte_order=\"LittleEndian\">\n"
107 <<
" <ImageData WholeExtent=\"0 " << nx - 1 <<
" 0 " << ny - 1 <<
" 0 " << nz - 1 <<
"\""
110 <<
" <Piece Extent=\"0 " << nx - 1 <<
" 0 " << ny - 1 <<
" 0 " << nz - 1 <<
"\">\n"
111 <<
" <PointData Vectors=\"" << name <<
"\">\n"
112 <<
" <DataArray type=\"Float32\" Name=\"" << name
113 <<
"\" NumberOfComponents=\"3\" format=\"ascii\">\n";
114 f.setf(std::ios::scientific);
116 std::size_t npts =
static_cast<std::size_t
>(nx) * ny * nz;
117 for (std::size_t p = 0; p < npts; ++p) {
118 f << g.
values[3 * p] <<
' ' << g.
values[3 * p + 1] <<
' ' << g.
values[3 * p + 2] <<
'\n';
120 f <<
" </DataArray>\n </PointData>\n </Piece>\n </ImageData>\n</VTKFile>\n";
125 std::ifstream f(path);
127 throw std::runtime_error(
"readVtiVector: cannot open " + path);
128 std::stringstream buf;
130 const std::string s = buf.str();
133 Index x0, x1, y0, y1, z0, z1;
134 std::istringstream(
detail::vtiAttr(s,
"WholeExtent")) >> x0 >> x1 >> y0 >> y1 >> z0 >> z1;
135 g.
dims = {x1 - x0 + 1, y1 - y0 + 1, z1 - z0 + 1};
139 auto da = s.find(
"<DataArray");
140 auto open = s.find(
'>', da);
141 auto close = s.find(
"</DataArray>", open);
142 std::istringstream data(s.substr(open + 1, close - open - 1));
143 std::size_t n3 = 3u *
static_cast<std::size_t
>(g.
dims[0]) * g.
dims[1] * g.
dims[2];
145 for (std::size_t i = 0; i < n3; ++i) {
Sampled (grid) signed-distance field with trilinear interpolation.
std::string vtiAttr(const std::string &s, const std::string &key)
VtiVector readVtiVector(const std::string &path)
Read a vector-field VTI written by writeVtiVector.
GridSdf readVti(const std::string &path)
Read a VTK ImageData (.vti) written by writeVti (ASCII PointData scalar) into a GridSdf.
void writeVti(const std::string &path, const GridSdf &g, const std::string &name="sdf")
Write a GridSdf as a VTK ImageData (.vti), PointData Float32 scalar, ASCII.
void writeVtiVector(const std::string &path, const VtiVector &g, const std::string &name="vector")
Write a 3-component vector field as a VTK ImageData PointData vector (ASCII), ParaView-openable.
std::array< Real, Dim > Vec
Multi-dimensional real vector.
std::array< Index, Dim > IVec
Multi-dimensional integer index / coordinate (x-fastest order by convention).
std::int64_t Index
Signed index type for grids and particles (supersedes block_decomposer's long int IndxT).
A signed-distance field sampled on a regular axis-aligned grid (negative inside solid).
Vec< 3 > origin
World position of sample (0,0,0).
std::vector< float > values
Sample values, x-fastest: idx = i + j*nx + k*nx*ny.
Vec< 3 > spacing
World-space distance between samples per axis.
IVec< 3 > dims
Sample count per axis (nx, ny, nz).
A sampled vector field on a regular grid (3 interleaved components per point, x-fastest).
std::vector< float > values