OGS
FileIO::SHPInterface Class Referencefinal

Detailed Description

Manages the import of ESRI shape files into GeoLib.

Definition at line 40 of file SHPInterface.h.

#include <SHPInterface.h>

Collaboration diagram for FileIO::SHPInterface:
[legend]

Public Types

enum class  OGSType {
  UNDEFINED = 0 , POINT = 1 , STATION = 2 , POLYLINE = 3 ,
  POLYGON = 4
}
 Connection between ESRI type system for shape files and OGS GeoLib. More...
 

Public Member Functions

 SHPInterface (GeoLib::GEOObjects &geoObjects)
 Constructor.
 
void readSHPFile (const std::string &filename, OGSType choice, const std::string &listName, std::string const &gmsh_path)
 Reads data from the shape file.
 

Static Public Member Functions

static bool readSHPInfo (const std::string &filename, int &shapeType, int &numberOfEntities)
 Reads the header of the shape file.
 
static bool write2dMeshToSHP (const std::string &file_name, const MeshLib::Mesh &mesh)
 

Private Member Functions

void readPoints (const SHPHandle &hSHP, int numberOfElements, std::string listName)
 Reads points into a vector of Point objects.
 
void readStations (const SHPHandle &hSHP, int numberOfElements, std::string listName)
 Reads points into a vector of Point objects and marks them as Station.
 
void readPolylines (const SHPHandle &hSHP, int numberOfElements, std::string listName)
 Reads lines into a vector of Polyline objects.
 
void readPolygons (const SHPHandle &hSHP, int numberOfElements, const std::string &listName, std::string const &gmsh_path)
 Reads lines into a vector of Polyline and Surface objects.
 

Static Private Member Functions

static SHPObject * createShapeObject (MeshLib::Element const &e, std::size_t const shp_record)
 Creates a shape object polygon out of a 2D mesh element.
 

Private Attributes

GeoLib::GEOObjects_geoObjects
 

Member Enumeration Documentation

◆ OGSType

enum class FileIO::SHPInterface::OGSType
strong

Connection between ESRI type system for shape files and OGS GeoLib.

Enumerator
UNDEFINED 
POINT 
STATION 
POLYLINE 
POLYGON 

Definition at line 44 of file SHPInterface.h.

Constructor & Destructor Documentation

◆ SHPInterface()

FileIO::SHPInterface::SHPInterface ( GeoLib::GEOObjects & geoObjects)
inlineexplicit

Constructor.

Definition at line 54 of file SHPInterface.h.

55 : _geoObjects(geoObjects)
56 {
57 }
GeoLib::GEOObjects & _geoObjects

Member Function Documentation

◆ createShapeObject()

SHPObject * FileIO::SHPInterface::createShapeObject ( MeshLib::Element const & e,
std::size_t const shp_record )
staticprivate

Creates a shape object polygon out of a 2D mesh element.

Definition at line 327 of file SHPInterface.cpp.

329{
330 unsigned const nNodes(e.getNumberOfBaseNodes());
331 double* padfX = new double[nNodes + 1];
332 double* padfY = new double[nNodes + 1];
333 double* padfZ = new double[nNodes + 1];
334 for (unsigned j = 0; j < nNodes; ++j)
335 {
336 padfX[j] = (*e.getNode(j))[0];
337 padfY[j] = (*e.getNode(j))[1];
338 padfZ[j] = (*e.getNode(j))[2];
339 }
340 // Last node == first node to close the polygon
341 padfX[nNodes] = (*e.getNode(0))[0];
342 padfY[nNodes] = (*e.getNode(0))[1];
343 padfZ[nNodes] = (*e.getNode(0))[2];
344
345 // the generated shape object now handles the memory for padfX/Y/Z
346 return SHPCreateObject(SHPT_POLYGON, shp_record, 0, nullptr, nullptr,
347 nNodes + 1, padfX, padfY, padfZ, nullptr);
348}

References MeshLib::Element::getNode(), and MeshLib::Element::getNumberOfBaseNodes().

Referenced by write2dMeshToSHP().

◆ readPoints()

void FileIO::SHPInterface::readPoints ( const SHPHandle & hSHP,
int numberOfElements,
std::string listName )
private

Reads points into a vector of Point objects.

Definition at line 85 of file SHPInterface.cpp.

87{
88 if (numberOfElements > 0)
89 {
90 std::vector<GeoLib::Point*> points;
91 SHPObject* hSHPObject;
92
93 for (int i = 0; i < numberOfElements; i++)
94 {
95 hSHPObject = SHPReadObject(hSHP, i);
96
97 auto* pnt =
98 new GeoLib::Point(*(hSHPObject->padfX), *(hSHPObject->padfY),
99 *(hSHPObject->padfZ));
100 points.push_back(pnt);
101 }
102
103 _geoObjects.addPointVec(std::move(points), listName,
105 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
106 }
107}
void addPointVec(std::vector< Point * > &&points, std::string &name, PointVec::NameIdMap &&pnt_id_name_map, double const eps=std::sqrt(std::numeric_limits< double >::epsilon()))
std::map< std::string, std::size_t > NameIdMap
Definition TemplateVec.h:41

References _geoObjects, and GeoLib::GEOObjects::addPointVec().

Referenced by readSHPFile().

◆ readPolygons()

void FileIO::SHPInterface::readPolygons ( const SHPHandle & hSHP,
int numberOfElements,
const std::string & listName,
std::string const & gmsh_path )
private

Reads lines into a vector of Polyline and Surface objects.

Definition at line 216 of file SHPInterface.cpp.

219{
220 readPolylines(hSHP, numberOfElements, listName);
221
222 auto const polylines = _geoObjects.getPolylineVec(listName);
223
224 for (auto const* polyline : *polylines)
225 {
226 INFO("Creating a surface by triangulation of the polyline ...");
227 if (FileIO::createSurface(*polyline, _geoObjects, listName, gmsh_path))
228 {
229 INFO("\t done");
230 }
231 else
232 {
233 WARN(
234 "\t Creating a surface by triangulation of the polyline "
235 "failed.");
236 }
237 }
238}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:35
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void readPolylines(const SHPHandle &hSHP, int numberOfElements, std::string listName)
Reads lines into a vector of Polyline objects.
const std::vector< Polyline * > * getPolylineVec(const std::string &name) const
bool createSurface(GeoLib::Polyline const &ply, GeoLib::GEOObjects &geometries, std::string const &geometry_name, std::string const &gmsh_binary)

References _geoObjects, FileIO::createSurface(), GeoLib::GEOObjects::getPolylineVec(), INFO(), readPolylines(), and WARN().

Referenced by readSHPFile().

◆ readPolylines()

void FileIO::SHPInterface::readPolylines ( const SHPHandle & hSHP,
int numberOfElements,
std::string listName )
private

Reads lines into a vector of Polyline objects.

Definition at line 134 of file SHPInterface.cpp.

136{
137 if (numberOfElements <= 0)
138 {
139 return;
140 }
141 std::vector<GeoLib::Point*> pnts;
142 std::vector<GeoLib::Polyline*> lines;
143
144 std::size_t pnt_id(0);
145 // for each polyline
146 for (int i = 0; i < numberOfElements; ++i)
147 {
148 SHPObject* hSHPObject = SHPReadObject(hSHP, i);
149 int const noOfPoints = hSHPObject->nVertices;
150 int const noOfParts = hSHPObject->nParts;
151
152 for (int p = 0; p < noOfParts; ++p)
153 {
154 int const firstPnt = *(hSHPObject->panPartStart + p);
155 int const lastPnt = (p < (noOfParts - 1))
156 ? *(hSHPObject->panPartStart + p + 1)
157 : noOfPoints;
158
159 // for each point in that polyline
160 for (int j = firstPnt; j < lastPnt; ++j)
161 {
162 pnts.push_back(new GeoLib::Point(
163 *(hSHPObject->padfX + j), *(hSHPObject->padfY + j),
164 *(hSHPObject->padfZ + j), pnt_id));
165 pnt_id++;
166 }
167 }
168 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
169 }
170
171 _geoObjects.addPointVec(std::move(pnts), listName,
173 GeoLib::PointVec const& points(*(_geoObjects.getPointVecObj(listName)));
174 std::vector<std::size_t> const& pnt_id_map(points.getIDMap());
175
176 pnt_id = 0;
177 for (int i = 0; i < numberOfElements; ++i)
178 {
179 SHPObject* hSHPObject = SHPReadObject(hSHP, i);
180 int const noOfPoints = hSHPObject->nVertices;
181 int const noOfParts = hSHPObject->nParts;
182
183 for (int p = 0; p < noOfParts; ++p)
184 {
185 // output for the first part of multipart polyline
186 if (noOfParts > 1 && p == 0)
187 {
188 INFO(
189 "Polygon {:d} consists of {:d} parts (PolylineIDs "
190 "{:d}-{:d}).",
191 i, noOfParts, lines.size(), lines.size() + noOfParts - 1);
192 }
193
194 int const firstPnt = *(hSHPObject->panPartStart + p);
195 int const lastPnt = (p < (noOfParts - 1))
196 ? *(hSHPObject->panPartStart + p + 1)
197 : noOfPoints;
198
199 auto* line = new GeoLib::Polyline(points.getVector());
200
201 // create polyline
202 for (int j = firstPnt; j < lastPnt; ++j)
203 {
204 line->addPoint(pnt_id_map[pnt_id]);
205 pnt_id++;
206 }
207 // add polyline to polyline vector
208 lines.push_back(line);
209 }
210 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
211 }
212 _geoObjects.addPolylineVec(std::move(lines), listName,
214}
void addPolylineVec(std::vector< Polyline * > &&lines, std::string const &name, PolylineVec::NameIdMap &&ply_names)
const PointVec * getPointVecObj(const std::string &name) const
This class manages pointers to Points in a std::vector along with a name. It also handles the deletio...
Definition PointVec.h:36
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition Polyline.h:40

References _geoObjects, GeoLib::GEOObjects::addPointVec(), GeoLib::GEOObjects::addPolylineVec(), GeoLib::PointVec::getIDMap(), GeoLib::GEOObjects::getPointVecObj(), GeoLib::TemplateVec< T >::getVector(), and INFO().

Referenced by readPolygons(), and readSHPFile().

◆ readSHPFile()

void FileIO::SHPInterface::readSHPFile ( const std::string & filename,
OGSType choice,
const std::string & listName,
std::string const & gmsh_path )

Reads data from the shape file.

Definition at line 52 of file SHPInterface.cpp.

55{
56 int shapeType;
57 int numberOfElements;
58 double padfMinBound[4];
59 double padfMaxBound[4];
60
61 SHPHandle hSHP = SHPOpen(filename.c_str(), "rb");
62 SHPGetInfo(hSHP, &numberOfElements, &shapeType, padfMinBound, padfMaxBound);
63
64 if (((shapeType - 1) % 10 == 0) && (choice == SHPInterface::OGSType::POINT))
65 {
66 readPoints(hSHP, numberOfElements, listName);
67 }
68 if (((shapeType - 1) % 10 == 0) &&
70 {
71 readStations(hSHP, numberOfElements, listName);
72 }
73 if (((shapeType - 3) % 10 == 0 || (shapeType - 5) % 10 == 0) &&
75 {
76 readPolylines(hSHP, numberOfElements, listName);
77 }
78 if (((shapeType - 3) % 10 == 0 || (shapeType - 5) % 10 == 0) &&
80 {
81 readPolygons(hSHP, numberOfElements, listName, gmsh_path);
82 }
83}
void readPoints(const SHPHandle &hSHP, int numberOfElements, std::string listName)
Reads points into a vector of Point objects.
void readStations(const SHPHandle &hSHP, int numberOfElements, std::string listName)
Reads points into a vector of Point objects and marks them as Station.
void readPolygons(const SHPHandle &hSHP, int numberOfElements, const std::string &listName, std::string const &gmsh_path)
Reads lines into a vector of Polyline and Surface objects.

References POINT, POLYGON, POLYLINE, readPoints(), readPolygons(), readPolylines(), readStations(), and STATION.

Referenced by SHPImportDialog::accept().

◆ readSHPInfo()

bool FileIO::SHPInterface::readSHPInfo ( const std::string & filename,
int & shapeType,
int & numberOfEntities )
static

Reads the header of the shape file.

Definition at line 31 of file SHPInterface.cpp.

33{
34 SHPHandle hSHP = SHPOpen(filename.c_str(), "rb");
35 if (!hSHP)
36 {
37 return false;
38 }
39
40 double padfMinBound[4];
41 double padfMaxBound[4];
42
43 // The SHPGetInfo() function retrieves various information about shapefile
44 // as a whole. The bounds are read from the file header, and may be
45 // inaccurate if the file was improperly generated.
46 SHPGetInfo(hSHP, &numberOfEntities, &shapeType, padfMinBound, padfMaxBound);
47
48 SHPClose(hSHP);
49 return true;
50}

Referenced by SHPImportDialog::setupDialog().

◆ readStations()

void FileIO::SHPInterface::readStations ( const SHPHandle & hSHP,
int numberOfElements,
std::string listName )
private

Reads points into a vector of Point objects and marks them as Station.

Definition at line 109 of file SHPInterface.cpp.

111{
112 if (numberOfElements > 0)
113 {
114 std::vector<GeoLib::Point*> stations;
115 stations.reserve(numberOfElements);
116 SHPObject* hSHPObject;
117
118 for (int i = 0; i < numberOfElements; i++)
119 {
120 hSHPObject = SHPReadObject(hSHP, i);
121 GeoLib::Station* stn =
122 GeoLib::Station::createStation(std::to_string(i),
123 *(hSHPObject->padfX),
124 *(hSHPObject->padfY),
125 *(hSHPObject->padfZ));
126 stations.push_back(stn);
127 }
128
129 _geoObjects.addStationVec(std::move(stations), listName);
130 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
131 }
132}
void addStationVec(std::vector< Point * > &&stations, std::string &name)
Adds a vector of stations with the given name and colour to GEOObjects.
A Station (observation site) is basically a Point with some additional information.
Definition Station.h:37
static Station * createStation(const std::string &line)
Definition Station.cpp:46

References _geoObjects, GeoLib::GEOObjects::addStationVec(), and GeoLib::Station::createStation().

Referenced by readSHPFile().

◆ write2dMeshToSHP()

bool FileIO::SHPInterface::write2dMeshToSHP ( const std::string & file_name,
const MeshLib::Mesh & mesh )
static

Writes a 2D mesh into a shapefile using one polygon for every element (based on request by AS, open for discussion)

Definition at line 240 of file SHPInterface.cpp.

242{
243 if (mesh.getDimension() != 2)
244 {
245 ERR("SHPInterface::write2dMeshToSHP(): Mesh to Shape conversion is "
246 "only working for 2D Meshes.");
247 return false;
248 }
249
250 std::size_t const n_elements = mesh.getNumberOfElements();
251 if (n_elements < 1)
252 {
253 ERR("SHPInterface::write2dMeshToSHP(): Mesh contains no elements.");
254 return false;
255 }
256
257 // DBF-export requires a limit of records because of the limits to the
258 // integer values. The exponent controls maximum number of elements and
259 // the maximum number of digits written in the DBF file.
260 std::size_t const max_exp = 8;
261 if (n_elements >= std::pow(10, max_exp))
262 {
263 ERR("SHPInterface::write2dMeshToSHP(): Mesh contains too many elements "
264 "for currently implemented DBF-boundaries.");
265 return false;
266 }
267
268 SHPHandle hSHP = SHPCreate(file_name.c_str(), SHPT_POLYGON);
269 DBFHandle hDBF = DBFCreate(file_name.c_str());
270 int const elem_id_field =
271 DBFAddField(hDBF, "Elem_ID", FTInteger, max_exp, 0);
272
273 // Writing mesh elements to shape file
274 std::size_t shp_record(0);
275 std::vector<MeshLib::Element*> const& elems = mesh.getElements();
276 for (MeshLib::Element const* const e : elems)
277 {
278 // ignore all elements except triangles and quads
279 if ((e->getGeomType() == MeshLib::MeshElemType::TRIANGLE) ||
280 (e->getGeomType() == MeshLib::MeshElemType::QUAD))
281 {
282 SHPObject* object = createShapeObject(*e, shp_record);
283 SHPWriteObject(hSHP, -1, object);
284 SHPDestroyObject(object);
285
286 // write element ID to DBF-file
287 DBFWriteIntegerAttribute(hDBF, shp_record, elem_id_field,
288 e->getID());
289 shp_record++;
290 }
291 }
292 SHPClose(hSHP);
293
294 // Write scalar arrays to database file
295 int const n_recs = DBFGetRecordCount(hDBF);
296 for (auto [name, property] : mesh.getProperties())
297 {
298 if (auto p = dynamic_cast<MeshLib::PropertyVector<int>*>(property))
299 {
300 int const field =
301 DBFAddField(hDBF, std::string(name).c_str(), FTInteger, 16, 0);
302 for (int i = 0; i < n_recs; ++i)
303 {
304 std::size_t const elem_idx =
305 DBFReadIntegerAttribute(hDBF, i, elem_id_field);
306 DBFWriteIntegerAttribute(hDBF, i, field, (*p)[elem_idx]);
307 }
308 }
309 else if (auto p =
310 dynamic_cast<MeshLib::PropertyVector<double>*>(property))
311 {
312 int const field =
313 DBFAddField(hDBF, std::string(name).c_str(), FTDouble, 33, 16);
314 for (int i = 0; i < n_recs; ++i)
315 {
316 std::size_t const elem_idx =
317 DBFReadIntegerAttribute(hDBF, i, elem_id_field);
318 DBFWriteDoubleAttribute(hDBF, i, field, (*p)[elem_idx]);
319 }
320 }
321 }
322 DBFClose(hDBF);
323 INFO("Shape export of 2D mesh '{:s}' finished.", mesh.getName());
324 return true;
325}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
static SHPObject * createShapeObject(MeshLib::Element const &e, std::size_t const shp_record)
Creates a shape object polygon out of a 2D mesh element.
std::vector< Element * > const & getElements() const
Get the element-vector for the mesh.
Definition Mesh.h:109
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
Definition Mesh.h:88
Properties & getProperties()
Definition Mesh.h:134
const std::string getName() const
Get name of the mesh.
Definition Mesh.h:103
std::size_t getNumberOfElements() const
Get the number of elements.
Definition Mesh.h:97

References createShapeObject(), ERR(), MeshLib::Mesh::getDimension(), MeshLib::Mesh::getElements(), MeshLib::Mesh::getName(), MeshLib::Mesh::getNumberOfElements(), MeshLib::Mesh::getProperties(), INFO(), MeshLib::QUAD, and MeshLib::TRIANGLE.

Referenced by MeshView::exportToShapefile(), and main().

Member Data Documentation

◆ _geoObjects

GeoLib::GEOObjects& FileIO::SHPInterface::_geoObjects
private

Definition at line 90 of file SHPInterface.h.

Referenced by readPoints(), readPolygons(), readPolylines(), and readStations().


The documentation for this class was generated from the following files: