29 std::ifstream in(fname.c_str());
33 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
34 return std::vector<std::string>();
37 if (!std::getline(in, line))
42 std::list<std::string> fields;
48 if (fields.size() < 2)
50 for (
char const d : {
'\t',
';',
','})
53 if (fields.size() > 1)
59 return {begin(fields), end(fields)};
63 std::vector<GeoLib::Point*>& points)
65 std::ifstream in(fname.c_str());
69 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
74 std::getline(in, line);
76 std::size_t line_count(0);
77 std::size_t error_count(0);
78 std::list<std::string>::const_iterator it;
79 while (std::getline(in, line))
84 if (fields.size() < 3)
86 ERR(
"Line {:d} contains not enough columns of data. Skipping "
93 std::array<double, 3> point{};
96 point[0] = std::stod(*it);
97 point[1] = std::stod(*(++it));
98 point[2] = std::stod(*(++it));
99 points.push_back(
new GeoLib::Point(point[0], point[1], point[2]));
101 catch (
const std::invalid_argument&)
103 ERR(
"Error converting data to coordinates in line {:d}.",
111 std::vector<GeoLib::Point*>& points,
112 std::string
const& x_column_name,
113 std::string
const& y_column_name,
114 std::string
const& z_column_name)
116 std::ifstream in(fname.c_str());
117 std::array<std::string, 3>
const column_names = {
118 {x_column_name, y_column_name, z_column_name}};
122 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
127 std::getline(in, line);
128 std::array<std::size_t, 3>
const column_idx = {
131 (z_column_name.empty())
135 for (std::size_t i = 0; i < 3; ++i)
137 if (column_idx[i] == std::numeric_limits<std::size_t>::max())
139 ERR(
"Column '{:s}' not found in file header.", column_names[i]);
144 return readPoints(in, delim, points, column_idx);
148 std::vector<GeoLib::Point*>& points,
149 std::size_t x_column_idx, std::size_t y_column_idx,
150 std::size_t z_column_idx)
152 std::ifstream in(fname.c_str());
156 ERR(
"CsvInterface::readPoints(): Could not open file {:s}.", fname);
160 if (z_column_idx == std::numeric_limits<std::size_t>::max())
162 z_column_idx = y_column_idx;
164 std::array<std::size_t, 3>
const column_idx = {
165 {x_column_idx, y_column_idx, z_column_idx}};
167 return readPoints(in, delim, points, column_idx);
171 std::vector<GeoLib::Point*>& points,
172 std::array<std::size_t, 3>
const& column_idx)
174 std::array<std::size_t, 3> order = {{0, 1, 2}};
175 std::sort(order.begin(), order.end(),
176 [&column_idx](std::size_t idx1, std::size_t idx2)
177 { return column_idx[idx1] < column_idx[idx2]; });
178 std::array<std::size_t, 3>
const column_advance = {
179 {column_idx[order[0]], column_idx[order[1]] - column_idx[order[0]],
180 column_idx[order[2]] - column_idx[order[1]]}};
183 std::size_t line_count(0);
184 std::size_t error_count(0);
185 std::list<std::string>::const_iterator it;
187 while (std::getline(in, line))
192 if (fields.size() < column_idx[order[2]] + 1)
194 ERR(
"Line {:d} contains not enough columns of data. Skipping "
201 std::array<double, 3> point{};
205 std::advance(it, column_advance[0]);
206 point[order[0]] = std::stod(*it);
207 std::advance(it, column_advance[1]);
208 point[order[1]] = std::stod(*it);
209 std::advance(it, column_advance[2]);
211 (column_idx[1] == column_idx[2]) ? 0 : std::stod(*it);
212 points.push_back(
new GeoLib::Point(point[0], point[1], point[2]));
214 catch (
const std::invalid_argument&)
216 ERR(
"Error converting data to coordinates in line {:d}.",
225 std::string
const& column_name)
230 return std::numeric_limits<std::size_t>::max();
233 std::size_t count(0);
234 for (
const auto& field : fields)
236 if (field == column_name)
244 if (count == fields.size())
246 return std::numeric_limits<std::size_t>::max();
254 std::vector<int> idx_vec(s);
255 std::iota(idx_vec.begin(), idx_vec.end(), 0);
263 ERR(
"CsvInterface::write() - No data to write.");
267 std::size_t
const n_vecs(
_data.size());
273 for (std::size_t i = 1; i < n_vecs; ++i)
280 for (std::size_t j = 0; j < vec_size; ++j)
283 for (std::size_t i = 1; i < n_vecs; ++i)
295 if (
_data[idx].type() ==
typeid(std::vector<std::string>))
297 return std::any_cast<std::vector<std::string>>(
_data[idx]).size();
299 if (
_data[idx].type() ==
typeid(std::vector<double>))
301 return std::any_cast<std::vector<double>>(
_data[idx]).size();
303 if (
_data[idx].type() ==
typeid(std::vector<int>))
305 return std::any_cast<std::vector<int>>(
_data[idx]).size();
312 if (
_data[vec_idx].type() ==
typeid(std::vector<std::string>))
314 out << std::any_cast<std::vector<std::string>>(
315 _data[vec_idx])[in_vec_idx];
317 else if (
_data[vec_idx].type() ==
typeid(std::vector<double>))
319 out << std::any_cast<std::vector<double>>(
_data[vec_idx])[in_vec_idx];
321 else if (
_data[vec_idx].type() ==
typeid(std::vector<int>))
323 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(char const *fmt, Args const &... 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)