OGS
ConvertSHPToGLI.cpp
Go to the documentation of this file.
1 
15 // STL
16 #include <tclap/CmdLine.h>
17 
18 #include <fstream>
19 #include <vector>
20 
21 // ShapeLib
22 #include <shapefil.h>
23 
24 #include "GeoLib/GEOObjects.h"
27 #include "GeoLib/Point.h"
28 #include "GeoLib/Station.h"
29 #include "InfoLib/GitInfo.h"
30 
31 void convertPoints(DBFHandle dbf_handle,
32  std::string const& out_fname,
33  std::size_t x_id,
34  std::size_t y_id,
35  std::size_t z_id,
36  std::vector<std::size_t> const& name_component_ids,
37  std::string& points_group_name,
38  bool station)
39 {
40  int n_records(DBFGetRecordCount(dbf_handle));
41  INFO("Reading {:d} records.", n_records);
42 
43  auto points = std::make_unique<std::vector<GeoLib::Point*>>();
44  points->reserve(n_records);
45 
46  std::string name;
47  for (int k = 0; k < n_records; k++)
48  {
49  double x(DBFReadDoubleAttribute(dbf_handle, k, x_id));
50  double y(DBFReadDoubleAttribute(dbf_handle, k, y_id));
51  double z(0.0);
52  if (z_id != std::numeric_limits<std::size_t>::max())
53  {
54  z = DBFReadDoubleAttribute(dbf_handle, k, z_id);
55  }
56 
57  name.clear();
58  if (!name_component_ids.empty())
59  {
60  for (unsigned long name_component_id : name_component_ids)
61  {
62  if (name_component_id !=
63  std::numeric_limits<std::size_t>::max())
64  {
65  name += DBFReadStringAttribute(dbf_handle, k,
66  name_component_id);
67  name += " ";
68  }
69  }
70  }
71  else
72  {
73  name = std::to_string(k);
74  }
75 
76  if (station)
77  {
79  points->push_back(pnt);
80  }
81  else
82  {
83  GeoLib::Point* pnt(new GeoLib::Point(x, y, z));
84  points->push_back(pnt);
85  }
86  }
87 
88  GeoLib::GEOObjects geo_objs;
89  if (station)
90  {
91  geo_objs.addStationVec(std::move(points), points_group_name);
92  }
93  else
94  {
95  geo_objs.addPointVec(std::move(points), points_group_name);
96  }
97 
98  if (station)
99  {
100  GeoLib::IO::XmlStnInterface xml(geo_objs);
101  xml.export_name = points_group_name;
103  }
104  else
105  {
106  GeoLib::IO::XmlGmlInterface xml(geo_objs);
107  xml.export_name = points_group_name;
109  }
110 }
111 
112 void printFieldInformationTable(DBFHandle const& dbf_handle,
113  std::size_t n_fields)
114 {
115  char* field_name(new char[256]);
116  int width(0);
117  int n_decimals(0);
118  std::stringstream out;
119  out << std::endl;
120  out << "************************************************" << std::endl;
121  out << "field idx | name of field | data type of field " << std::endl;
122  out << "------------------------------------------------" << std::endl;
123  for (std::size_t field_idx(0); field_idx < n_fields; field_idx++)
124  {
125  DBFGetFieldInfo(dbf_handle, field_idx, field_name, &width, &n_decimals);
126  if (field_idx < 10)
127  {
128  out << " " << field_idx << " |";
129  }
130  else
131  {
132  out << " " << field_idx << " |";
133  }
134  std::string field_name_str(field_name);
135  for (int k(0); k < (14 - static_cast<int>(field_name_str.size())); k++)
136  {
137  out << " ";
138  }
139  out << field_name_str << " |";
140 
141  char native_field_type(DBFGetNativeFieldType(dbf_handle, field_idx));
142  switch (native_field_type)
143  {
144  case 'C':
145  out << " string" << std::endl;
146  break;
147  case 'F':
148  out << " float" << std::endl;
149  break;
150  case 'N':
151  out << " numeric" << std::endl;
152  break;
153  default:
154  out << " n_decimal " << n_decimals << std::endl;
155  break;
156  }
157  }
158  delete[] field_name;
159  out << "************************************************" << std::endl;
160  INFO("{:s}", out.str());
161 }
162 
163 int main(int argc, char* argv[])
164 {
165  TCLAP::CmdLine cmd(
166  "Converts points contained in shape file\n\n"
167  "OpenGeoSys-6 software, version " +
169  ".\n"
170  "Copyright (c) 2012-2021, OpenGeoSys Community "
171  "(http://www.opengeosys.org)",
173  TCLAP::ValueArg<std::string> shapefile_arg("s",
174  "shape-file",
175  "the name of the shape file ",
176  true,
177  "",
178  "shape file");
179  cmd.add(shapefile_arg);
180 
181  cmd.parse(argc, argv);
182 
183  std::string fname(shapefile_arg.getValue());
184 
185  int shape_type;
186  int number_of_elements;
187 
188  SHPHandle hSHP = SHPOpen(fname.c_str(), "rb");
189  if (hSHP)
190  {
191  SHPGetInfo(hSHP, &number_of_elements, &shape_type,
192  nullptr /*padfMinBound*/, nullptr /*padfMinBound*/);
193 
194  if ((shape_type - 1) % 10 == 0)
195  INFO("Shape file contains {:d} points.", number_of_elements);
196  if (((shape_type - 3) % 10 == 0 || (shape_type - 5) % 10 == 0))
197  {
198  ERR("Shape file contains {:d} polylines.", number_of_elements);
199  ERR("This programme only handles only files containing points.");
200  SHPClose(hSHP);
201  return EXIT_SUCCESS;
202  }
203  SHPClose(hSHP);
204  }
205  else
206  {
207  ERR("Could not open shapefile {:s}.", fname);
208  }
209 
210  DBFHandle dbf_handle = DBFOpen(fname.c_str(), "rb");
211  if (dbf_handle)
212  {
213  std::size_t n_fields(DBFGetFieldCount(dbf_handle));
214  printFieldInformationTable(dbf_handle, n_fields);
215 
216  std::size_t x_id;
217  std::size_t y_id;
218  std::size_t z_id;
219  INFO(
220  "Please give the field idx that should be used for reading the x "
221  "coordinate: ");
222  std::cin >> x_id;
223  INFO(
224  "Please give the field idx that should be used for reading the y "
225  "coordinate: ");
226  std::cin >> y_id;
227  INFO(
228  "Please give the field idx that should be used for reading the z "
229  "coordinate: ");
230  std::cin >> z_id;
231 
232  if (z_id > n_fields)
233  {
234  z_id = std::numeric_limits<std::size_t>::max();
235  }
236 
237  std::size_t n_name_components;
238  INFO("Please give the number of fields that should be added to name: ");
239  std::cin >> n_name_components;
240 
241  std::vector<std::size_t> name_component_ids(
242  n_name_components, std::numeric_limits<std::size_t>::max());
243  if (n_name_components != 0)
244  {
245  for (std::size_t j(0); j < n_name_components; j++)
246  {
247  INFO(
248  "- please give the field idx that should be used for "
249  "reading the name: ");
250  std::cin >> name_component_ids[j];
251  }
252  }
253  for (std::size_t j(0); j < n_name_components; j++)
254  {
255  if (name_component_ids[j] > n_fields)
256  {
257  name_component_ids[j] = std::numeric_limits<std::size_t>::max();
258  }
259  }
260 
261  std::size_t station(0);
262 
263  INFO(
264  "Should I read the information as GeoLib::Station (0) or as "
265  "GeoLib::Point (1)? Please give the number: ");
266  std::cin >> station;
267 
268  std::string fname_base(fname);
269  if (station == 0)
270  {
271  fname += ".stn";
272  }
273  else
274  {
275  fname += ".gml";
276  }
277 
278  INFO("Writing to {:s}.", fname);
279  convertPoints(dbf_handle,
280  fname,
281  x_id,
282  y_id,
283  z_id,
284  name_component_ids,
285  fname_base,
286  station == 0);
287  DBFClose(dbf_handle);
288  INFO("\tok.");
289  }
290  else
291  {
292  ERR("Could not open the database file.");
293  }
294 
295  return EXIT_SUCCESS;
296 }
int main(int argc, char *argv[])
void convertPoints(DBFHandle dbf_handle, std::string const &out_fname, std::size_t x_id, std::size_t y_id, std::size_t z_id, std::vector< std::size_t > const &name_component_ids, std::string &points_group_name, bool station)
void printFieldInformationTable(DBFHandle const &dbf_handle, std::size_t n_fields)
Definition of the GEOObjects class.
Definition of the Point class.
Git information.
void INFO(char const *fmt, Args const &... args)
Definition: Logging.h:32
void ERR(char const *fmt, Args const &... args)
Definition: Logging.h:42
Definition of the Station class.
Definition of the XmlGmlInterface class.
Definition of the XmlStnInterface class.
std::string writeToString()
Writes the object to a string.
Definition: Writer.cpp:31
Container class for geometric objects.
Definition: GEOObjects.h:61
void addStationVec(std::unique_ptr< std::vector< Point * >> stations, std::string &name)
Adds a vector of stations with the given name and colour to GEOObjects.
Definition: GEOObjects.cpp:122
void addPointVec(std::unique_ptr< std::vector< Point * >> points, std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> pnt_id_name_map=nullptr, double eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:51
Reads and writes GeoObjects to and from XML files.
Reads and writes Observation Sites to and from XML files.
A Station (observation site) is basically a Point with some additional information.
Definition: Station.h:37
static Station * createStation(const std::string &line)
Creates a Station-object from information contained in a string (assuming the string has the right fo...
Definition: Station.cpp:45
int writeStringToFile(std::string content, std::filesystem::path const &file_path)
Definition: Writer.cpp:45
GITINFOLIB_EXPORT const std::string ogs_version