OGS
FileIO::SHPInterface Class Referencefinal

Detailed Description

Manages the import of ESRI shape files into GeoLib.

Definition at line 30 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 34 of file SHPInterface.h.

35 {
36 UNDEFINED = 0,
37 POINT = 1,
38 STATION = 2,
39 POLYLINE = 3,
40 POLYGON = 4
41 };

Constructor & Destructor Documentation

◆ SHPInterface()

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

Constructor.

Definition at line 44 of file SHPInterface.h.

45 : _geoObjects(geoObjects)
46 {
47 }
GeoLib::GEOObjects & _geoObjects

References _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 317 of file SHPInterface.cpp.

319{
320 unsigned const nNodes(e.getNumberOfBaseNodes());
321 double* padfX = new double[nNodes + 1];
322 double* padfY = new double[nNodes + 1];
323 double* padfZ = new double[nNodes + 1];
324 for (unsigned j = 0; j < nNodes; ++j)
325 {
326 padfX[j] = (*e.getNode(j))[0];
327 padfY[j] = (*e.getNode(j))[1];
328 padfZ[j] = (*e.getNode(j))[2];
329 }
330 // Last node == first node to close the polygon
331 padfX[nNodes] = (*e.getNode(0))[0];
332 padfY[nNodes] = (*e.getNode(0))[1];
333 padfZ[nNodes] = (*e.getNode(0))[2];
334
335 // the generated shape object now handles the memory for padfX/Y/Z
336 return SHPCreateObject(SHPT_POLYGON, shp_record, 0, nullptr, nullptr,
337 nNodes + 1, padfX, padfY, padfZ, nullptr);
338}

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 75 of file SHPInterface.cpp.

77{
78 if (numberOfElements > 0)
79 {
80 std::vector<GeoLib::Point*> points;
81 SHPObject* hSHPObject;
82
83 for (int i = 0; i < numberOfElements; i++)
84 {
85 hSHPObject = SHPReadObject(hSHP, i);
86
87 auto* pnt =
88 new GeoLib::Point(*(hSHPObject->padfX), *(hSHPObject->padfY),
89 *(hSHPObject->padfZ));
90 points.push_back(pnt);
91 }
92
93 _geoObjects.addPointVec(std::move(points), listName,
95 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
96 }
97}
std::map< std::string, std::size_t > NameIdMap
Definition TemplateVec.h:30

References _geoObjects.

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 206 of file SHPInterface.cpp.

209{
210 readPolylines(hSHP, numberOfElements, listName);
211
212 auto const polylines = _geoObjects.getPolylineVec(listName);
213
214 for (auto const* polyline : *polylines)
215 {
216 INFO("Creating a surface by triangulation of the polyline ...");
217 if (FileIO::createSurface(*polyline, _geoObjects, listName, gmsh_path))
218 {
219 INFO("\t done");
220 }
221 else
222 {
223 WARN(
224 "\t Creating a surface by triangulation of the polyline "
225 "failed.");
226 }
227 }
228}
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:28
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
void readPolylines(const SHPHandle &hSHP, int numberOfElements, std::string listName)
Reads lines into a vector of Polyline objects.
bool createSurface(GeoLib::Polyline const &ply, GeoLib::GEOObjects &geometries, std::string const &geometry_name, std::string const &gmsh_binary)

References _geoObjects, FileIO::createSurface(), 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 124 of file SHPInterface.cpp.

126{
127 if (numberOfElements <= 0)
128 {
129 return;
130 }
131 std::vector<GeoLib::Point*> pnts;
132 std::vector<GeoLib::Polyline*> lines;
133
134 std::size_t pnt_id(0);
135 // for each polyline
136 for (int i = 0; i < numberOfElements; ++i)
137 {
138 SHPObject* hSHPObject = SHPReadObject(hSHP, i);
139 int const noOfPoints = hSHPObject->nVertices;
140 int const noOfParts = hSHPObject->nParts;
141
142 for (int p = 0; p < noOfParts; ++p)
143 {
144 int const firstPnt = *(hSHPObject->panPartStart + p);
145 int const lastPnt = (p < (noOfParts - 1))
146 ? *(hSHPObject->panPartStart + p + 1)
147 : noOfPoints;
148
149 // for each point in that polyline
150 for (int j = firstPnt; j < lastPnt; ++j)
151 {
152 pnts.push_back(new GeoLib::Point(
153 *(hSHPObject->padfX + j), *(hSHPObject->padfY + j),
154 *(hSHPObject->padfZ + j), pnt_id));
155 pnt_id++;
156 }
157 }
158 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
159 }
160
161 _geoObjects.addPointVec(std::move(pnts), listName,
163 GeoLib::PointVec const& points(*(_geoObjects.getPointVecObj(listName)));
164 std::vector<std::size_t> const& pnt_id_map(points.getIDMap());
165
166 pnt_id = 0;
167 for (int i = 0; i < numberOfElements; ++i)
168 {
169 SHPObject* hSHPObject = SHPReadObject(hSHP, i);
170 int const noOfPoints = hSHPObject->nVertices;
171 int const noOfParts = hSHPObject->nParts;
172
173 for (int p = 0; p < noOfParts; ++p)
174 {
175 // output for the first part of multipart polyline
176 if (noOfParts > 1 && p == 0)
177 {
178 INFO(
179 "Polygon {:d} consists of {:d} parts (PolylineIDs "
180 "{:d}-{:d}).",
181 i, noOfParts, lines.size(), lines.size() + noOfParts - 1);
182 }
183
184 int const firstPnt = *(hSHPObject->panPartStart + p);
185 int const lastPnt = (p < (noOfParts - 1))
186 ? *(hSHPObject->panPartStart + p + 1)
187 : noOfPoints;
188
189 auto* line = new GeoLib::Polyline(points.getVector());
190
191 // create polyline
192 for (int j = firstPnt; j < lastPnt; ++j)
193 {
194 line->addPoint(pnt_id_map[pnt_id]);
195 pnt_id++;
196 }
197 // add polyline to polyline vector
198 lines.push_back(line);
199 }
200 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
201 }
202 _geoObjects.addPolylineVec(std::move(lines), listName,
204}

References _geoObjects, GeoLib::PointVec::getIDMap(), 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 42 of file SHPInterface.cpp.

45{
46 int shapeType;
47 int numberOfElements;
48 double padfMinBound[4];
49 double padfMaxBound[4];
50
51 SHPHandle hSHP = SHPOpen(filename.c_str(), "rb");
52 SHPGetInfo(hSHP, &numberOfElements, &shapeType, padfMinBound, padfMaxBound);
53
54 if (((shapeType - 1) % 10 == 0) && (choice == SHPInterface::OGSType::POINT))
55 {
56 readPoints(hSHP, numberOfElements, listName);
57 }
58 if (((shapeType - 1) % 10 == 0) &&
60 {
61 readStations(hSHP, numberOfElements, listName);
62 }
63 if (((shapeType - 3) % 10 == 0 || (shapeType - 5) % 10 == 0) &&
65 {
66 readPolylines(hSHP, numberOfElements, listName);
67 }
68 if (((shapeType - 3) % 10 == 0 || (shapeType - 5) % 10 == 0) &&
70 {
71 readPolygons(hSHP, numberOfElements, listName, gmsh_path);
72 }
73}
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.

◆ readSHPInfo()

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

Reads the header of the shape file.

Definition at line 21 of file SHPInterface.cpp.

23{
24 SHPHandle hSHP = SHPOpen(filename.c_str(), "rb");
25 if (!hSHP)
26 {
27 return false;
28 }
29
30 double padfMinBound[4];
31 double padfMaxBound[4];
32
33 // The SHPGetInfo() function retrieves various information about shapefile
34 // as a whole. The bounds are read from the file header, and may be
35 // inaccurate if the file was improperly generated.
36 SHPGetInfo(hSHP, &numberOfEntities, &shapeType, padfMinBound, padfMaxBound);
37
38 SHPClose(hSHP);
39 return true;
40}

◆ 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 99 of file SHPInterface.cpp.

101{
102 if (numberOfElements > 0)
103 {
104 std::vector<GeoLib::Point*> stations;
105 stations.reserve(numberOfElements);
106 SHPObject* hSHPObject;
107
108 for (int i = 0; i < numberOfElements; i++)
109 {
110 hSHPObject = SHPReadObject(hSHP, i);
111 GeoLib::Station* stn =
112 GeoLib::Station::createStation(std::to_string(i),
113 *(hSHPObject->padfX),
114 *(hSHPObject->padfY),
115 *(hSHPObject->padfZ));
116 stations.push_back(stn);
117 }
118
119 _geoObjects.addStationVec(std::move(stations), listName);
120 SHPDestroyObject(hSHPObject); // de-allocate SHPObject
121 }
122}
static Station * createStation(const std::string &line)
Definition Station.cpp:35

References _geoObjects, 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 230 of file SHPInterface.cpp.

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

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 80 of file SHPInterface.h.

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


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