28 std::ifstream in(fname.c_str());
32 ERR(
"CsvInterface::getColumnNames(): Could not open file {:s}.", fname);
33 return std::vector<std::string>();
36 if (!std::getline(in, line))
38 ERR(
"CsvInterface::getColumnNames(): Could not read line from file "
50 if (fields.size() < 2)
52 for (
char const d : {
'\t',
';',
','})
55 if (fields.size() > 1)
61 return {begin(fields), end(fields)};
65 std::vector<GeoLib::Point*>& points)
67 std::ifstream in(fname.c_str());
71 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
76 std::getline(in, line);
78 std::size_t line_count(0);
79 std::size_t error_count(0);
80 std::list<std::string>::const_iterator it;
81 while (std::getline(in, line))
86 if (fields.size() < 3)
88 ERR(
"Line {:d} contains not enough columns of data. Skipping "
97 std::array<double, 3> point{};
98 point[0] = std::stod(*it);
99 point[1] = std::stod(*(++it));
100 point[2] = std::stod(*(++it));
101 points.push_back(
new GeoLib::Point(point[0], point[1], point[2]));
103 catch (
const std::invalid_argument&)
105 ERR(
"Error converting data to coordinates in line {:d}.",
113 std::vector<GeoLib::Point*>& points,
114 std::string
const& x_column_name,
115 std::string
const& y_column_name,
116 std::string
const& z_column_name)
118 std::ifstream in(fname.c_str());
119 std::array<std::string, 3>
const column_names = {
120 {x_column_name, y_column_name, z_column_name}};
124 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
129 std::getline(in, line);
130 std::array<std::size_t, 3>
const column_idx = {
133 (z_column_name.empty())
137 for (std::size_t i = 0; i < 3; ++i)
139 if (column_idx[i] == std::numeric_limits<std::size_t>::max())
141 ERR(
"Column '{:s}' not found in file header.", column_names[i]);
146 return readPoints(in, delim, points, column_idx);
150 std::vector<GeoLib::Point*>& points,
151 std::size_t x_column_idx, std::size_t y_column_idx,
152 std::size_t z_column_idx)
154 std::ifstream in(fname.c_str());
158 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
162 if (z_column_idx == std::numeric_limits<std::size_t>::max())
164 z_column_idx = y_column_idx;
166 std::array<std::size_t, 3>
const column_idx = {
167 {x_column_idx, y_column_idx, z_column_idx}};
169 return readPoints(in, delim, points, column_idx);
173 std::vector<GeoLib::Point*>& points,
174 std::array<std::size_t, 3>
const& column_idx)
176 std::array<std::size_t, 3> order = {{0, 1, 2}};
177 std::sort(order.begin(), order.end(),
178 [&column_idx](std::size_t idx1, std::size_t idx2)
179 { return column_idx[idx1] < column_idx[idx2]; });
180 std::array<std::size_t, 3>
const column_advance = {
181 {column_idx[order[0]], column_idx[order[1]] - column_idx[order[0]],
182 column_idx[order[2]] - column_idx[order[1]]}};
185 std::size_t line_count(0);
186 std::size_t error_count(0);
187 std::list<std::string>::const_iterator it;
189 while (std::getline(in, line))
194 if (fields.size() < column_idx[order[2]] + 1)
196 ERR(
"Line {:d} contains not enough columns of data. Skipping "
206 std::advance(it, column_advance[0]);
207 std::array<double, 3> point{};
208 point[order[0]] = std::stod(*it);
209 std::advance(it, column_advance[1]);
210 point[order[1]] = std::stod(*it);
211 std::advance(it, column_advance[2]);
213 (column_idx[1] == column_idx[2]) ? 0 : std::stod(*it);
214 points.push_back(
new GeoLib::Point(point[0], point[1], point[2]));
216 catch (
const std::invalid_argument&)
218 ERR(
"Error converting data to coordinates in line {:d}.",
227 std::string
const& column_name)
232 return std::numeric_limits<std::size_t>::max();
235 std::size_t count(0);
236 for (
const auto& field : fields)
238 if (field == column_name)
246 if (count == fields.size())
248 return std::numeric_limits<std::size_t>::max();
256 std::vector<int> idx_vec(s);
257 std::iota(idx_vec.begin(), idx_vec.end(), 0);
265 ERR(
"CsvInterface::write() - No data to write.");
269 std::size_t
const n_vecs(
_data.size());
275 for (std::size_t i = 1; i < n_vecs; ++i)
282 for (std::size_t j = 0; j < vec_size; ++j)
285 for (std::size_t i = 1; i < n_vecs; ++i)
297 if (
_data[idx].type() ==
typeid(std::vector<std::string>))
299 return std::any_cast<std::vector<std::string>>(
_data[idx]).size();
301 if (
_data[idx].type() ==
typeid(std::vector<double>))
303 return std::any_cast<std::vector<double>>(
_data[idx]).size();
305 if (
_data[idx].type() ==
typeid(std::vector<int>))
307 return std::any_cast<std::vector<int>>(
_data[idx]).size();
314 if (
_data[vec_idx].type() ==
typeid(std::vector<std::string>))
316 out << std::any_cast<std::vector<std::string>>(
317 _data[vec_idx])[in_vec_idx];
319 else if (
_data[vec_idx].type() ==
typeid(std::vector<double>))
321 out << std::any_cast<std::vector<double>>(
_data[vec_idx])[in_vec_idx];
323 else if (
_data[vec_idx].type() ==
typeid(std::vector<int>))
325 out << std::any_cast<std::vector<int>>(
_data[vec_idx])[in_vec_idx];
Definition of the CsvInterface class.
Definition of the Point class.
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
std::ostringstream out
The stream to write to.
std::vector< std::any > _data
void writeValue(std::size_t vec_idx, std::size_t in_vec_idx)
std::vector< std::string > _vec_names
static std::vector< std::string > getColumnNames(std::string const &fname, char delim)
bool addVectorForWriting(std::string const &vec_name, std::vector< T > const &vec)
static std::size_t findColumn(std::string const &line, char delim, std::string const &column_name)
void addIndexVectorForWriting(std::size_t s)
Adds an index vector of size s to the CSV file.
std::size_t getVectorSize(std::size_t idx) const
Returns the size of the vector with the given index.
CsvInterface()
Constructor (only needed for writing files)
bool write() override
Writes the CSV file.
static int readPoints(std::string const &fname, char delim, std::vector< GeoLib::Point * > &points)
std::vector< std::string > splitString(std::string const &str)