From 80df8365a7603bf05bb11973e6e712d17b8e824c Mon Sep 17 00:00:00 2001 From: Lars Bilke <lars.bilke@ufz.de> Date: Fri, 14 Sep 2012 12:06:28 +0200 Subject: [PATCH] Re-added SHPInterface. --- FileIO/CMakeLists.txt | 16 +++- FileIO/SHPInterface.cpp | 174 ++++++++++++++++++++++++++++++++++++++++ FileIO/SHPInterface.h | 58 ++++++++++++++ 3 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 FileIO/SHPInterface.cpp create mode 100644 FileIO/SHPInterface.h diff --git a/FileIO/CMakeLists.txt b/FileIO/CMakeLists.txt index 60753c25b2f..26cbde362f7 100644 --- a/FileIO/CMakeLists.txt +++ b/FileIO/CMakeLists.txt @@ -1,14 +1,26 @@ # Source files -GET_SOURCE_FILES(SOURCES_FILEIO) +# GET_SOURCE_FILES(SOURCES_FILEIO) +SET( SOURCES + Gmsh2GeoIO.cpp + GMSInterface.cpp + PetrelInterface.cpp + readNonBlankLineFromInputStream.cpp + Writer.cpp +) GET_SOURCE_FILES(SOURCES_LEGACY Legacy) GET_SOURCE_FILES(SOURCES_MESHIO MeshIO) -SET ( SOURCES ${SOURCES_FILEIO} ${SOURCES_LEGACY} ${SOURCES_MESHIO}) +SET ( SOURCES ${SOURCES} ${SOURCES_LEGACY} ${SOURCES_MESHIO}) IF (QT4_FOUND) GET_SOURCE_FILES(SOURCES_XML XmlIO) SET ( SOURCES ${SOURCES} ${SOURCES_XML}) ENDIF (QT4_FOUND) +IF (Shapelib_FOUND) + SET (SOURCES ${SOURCES} SHPInterface.h SHPInterface.cpp ) + INCLUDE_DIRECTORIES (${Shapelib_INCLUDE_DIR}) +ENDIF (Shapelib_FOUND) + # Create the library ADD_LIBRARY(FileIO STATIC ${SOURCES}) diff --git a/FileIO/SHPInterface.cpp b/FileIO/SHPInterface.cpp new file mode 100644 index 00000000000..c8a9e16f155 --- /dev/null +++ b/FileIO/SHPInterface.cpp @@ -0,0 +1,174 @@ +/** + * \file SHPInterface.cpp + * 25/01/2010 KR Initial implementation + */ + +#include "SHPInterface.h" +#include "StringTools.h" + +// MathLib +#include "AnalyticalGeometry.h" + +bool SHPInterface::readSHPInfo(const std::string &filename, int &shapeType, int &numberOfEntities) +{ + SHPHandle hSHP = SHPOpen(filename.c_str(),"rb"); + if(!hSHP) + return false; + + double padfMinBound[4], padfMaxBound[4]; + + // The SHPGetInfo() function retrieves various information about shapefile as a whole. + // The bounds are read from the file header, and may be inaccurate if the file was improperly generated. + SHPGetInfo( hSHP, &numberOfEntities, &shapeType, padfMinBound, padfMaxBound ); + + SHPClose(hSHP); + return true; +} + +void SHPInterface::readSHPFile(const std::string &filename, OGSType choice, std::string listName) +{ + int shapeType, numberOfElements; + double padfMinBound[4], padfMaxBound[4]; + + SHPHandle hSHP = SHPOpen(filename.c_str(),"rb"); + SHPGetInfo( hSHP, &numberOfElements, &shapeType, padfMinBound, padfMaxBound ); + + if ( ((shapeType - 1) % 10 == 0) && (choice == SHPInterface::POINT) ) + readPoints(hSHP, numberOfElements, listName); + if ( ((shapeType - 1) % 10 == 0) && (choice == SHPInterface::STATION) ) + readStations(hSHP, numberOfElements, listName); + if ( ((shapeType - 3) % 10 == 0 || + (shapeType - 5) % 10 == 0) && (choice == SHPInterface::POLYLINE) ) + readPolylines(hSHP, numberOfElements, listName); + if ( ((shapeType - 3) % 10 == 0 || + (shapeType - 5) % 10 == 0) && (choice == SHPInterface::POLYGON) ) + readPolygons(hSHP, numberOfElements, listName); +} + +void SHPInterface::readPoints(const SHPHandle &hSHP, int numberOfElements, std::string listName) +{ + if (numberOfElements > 0) + { + std::vector<GeoLib::Point*>* points = new std::vector<GeoLib::Point*>(); + SHPObject* hSHPObject; + + for (int i = 0; i < numberOfElements; i++) + { + hSHPObject = SHPReadObject(hSHP,i); + + GeoLib::Point* pnt = + new GeoLib::Point( *(hSHPObject->padfX), *(hSHPObject->padfY), + *(hSHPObject->padfZ) ); + points->push_back(pnt); + } + + _geoObjects->addPointVec(points, listName); + SHPDestroyObject(hSHPObject); // de-allocate SHPObject + } +} + +void SHPInterface::readStations(const SHPHandle &hSHP, int numberOfElements, std::string listName) +{ + if (numberOfElements > 0) + { + std::vector<GeoLib::Point*>* stations (new std::vector<GeoLib::Point*>); + stations->reserve (numberOfElements); + SHPObject* hSHPObject; + + for (int i = 0; i < numberOfElements; i++) + { + hSHPObject = SHPReadObject(hSHP,i); + GeoLib::Station* stn = + GeoLib::Station::createStation( number2str(i), *(hSHPObject->padfX), + *(hSHPObject->padfY), + *(hSHPObject->padfZ) ); + stations->push_back(stn); + } + + _geoObjects->addStationVec(stations, listName); + SHPDestroyObject(hSHPObject); // de-allocate SHPObject + } +} + +void SHPInterface::readPolylines(const SHPHandle &hSHP, int numberOfElements, std::string listName) +{ + size_t noOfPoints = 0, noOfParts = 0; + std::vector<GeoLib::Point*>* points = new std::vector<GeoLib::Point*>(); + std::vector<GeoLib::Polyline*>* lines = new std::vector<GeoLib::Polyline*>(); + SHPObject* hSHPObject; + + // for each polyline) + for (int i = 0; i < numberOfElements; i++) + { + hSHPObject = SHPReadObject(hSHP,i); + noOfPoints = hSHPObject->nVertices; + noOfParts = hSHPObject->nParts; + + for (size_t p = 0; p < noOfParts; p++) + { + int firstPnt = *(hSHPObject->panPartStart + p); + int lastPnt = + (p < (noOfParts - 1)) ? *(hSHPObject->panPartStart + p + 1) : noOfPoints; + + GeoLib::Polyline* line = new GeoLib::Polyline(*points); + + // for each point in that polyline + for (int j = firstPnt; j < lastPnt; j++) + { + GeoLib::Point* pnt = + new GeoLib::Point( *(hSHPObject->padfX + j), + *(hSHPObject->padfY + j), + *(hSHPObject->padfZ + j) ); + points->push_back(pnt); + line->addPoint(points->size() - 1); + } + + // add polyline to polyline vector + lines->push_back(line); + } + } + + if (numberOfElements > 0) + { + // add points vector to GEOObjects (and check for duplicate points) + _geoObjects->addPointVec(points, listName); + + // adjust indeces of polylines, remove zero length elements and add vector to GEOObjects + this->adjustPolylines(lines, _geoObjects->getPointVecObj(listName)->getIDMap()); + _geoObjects->addPolylineVec(lines, listName); + + SHPDestroyObject(hSHPObject); // de-allocate SHPObject + } +} + +void SHPInterface::readPolygons(const SHPHandle &hSHP, int numberOfElements, std::string listName) +{ + this->readPolylines(hSHP, numberOfElements, listName); + + const std::vector<GeoLib::Polyline*>* polylines (_geoObjects->getPolylineVec(listName)); + std::vector<GeoLib::Surface*>* sfc_vec(new std::vector<GeoLib::Surface*>); + + for (std::vector<GeoLib::Polyline*>::const_iterator poly_it (polylines->begin()); + poly_it != polylines->end(); poly_it++) + { + std::cout << "triangulation of Polygon with " << (*poly_it)->getNumberOfPoints() << + " points ... " << std::flush; + sfc_vec->push_back(GeoLib::Surface::createSurface(*(*poly_it))); + } + + if (!sfc_vec->empty()) + _geoObjects->addSurfaceVec(sfc_vec, listName); +} + +void SHPInterface::adjustPolylines (std::vector<GeoLib::Polyline*>* lines, + std::vector<size_t> id_map) + +{ + for (size_t i = 0; i < lines->size(); i++) + { + GeoLib::Polyline* line( (*lines)[i] ); + size_t nPoints( line->getNumberOfPoints() ); + for (size_t j = 0; j < nPoints; j++) + line->setPointID(j, id_map[line->getPointID(j)]); + } +} diff --git a/FileIO/SHPInterface.h b/FileIO/SHPInterface.h new file mode 100644 index 00000000000..171dd252eab --- /dev/null +++ b/FileIO/SHPInterface.h @@ -0,0 +1,58 @@ +/** + * \file SHPInterface.cpp + * 25/01/2010 KR Initial implementation + */ +#ifndef SHPINTERFACE_H +#define SHPINTERFACE_H + +#include <string> + +//ShapeLib includes +#include "shapefil.h" + +#include "GEOObjects.h" + +/** + * \brief Manages the import of ESRI shape files into GeoLib. + */ +class SHPInterface +{ +public: + /// Connection between ESRI type system for shape files and OGS GeoLib. + enum OGSType + { + UNDEFINED = 0, + POINT = 1, + STATION = 2, + POLYLINE = 3, + POLYGON = 4 + }; + + /// Constructor + SHPInterface(GeoLib::GEOObjects* geoObjects) : _geoObjects(geoObjects) {} + + /// Reads the header of the shape file. + bool readSHPInfo(const std::string &filename, int &shapeType, int &numberOfEntities); + + /// Reads data from the shape file. + void readSHPFile(const std::string &filename, OGSType choice, std::string listName); + +private: + /// Reads points into a vector of Point objects. + void readPoints (const SHPHandle &hSHP, int numberOfElements, std::string listName); + + /// Reads points into a vector of Point objects and marks them as Station. + void readStations (const SHPHandle &hSHP, int numberOfElements, std::string listName); + + /// Reads lines into a vector of Polyline objects. + void readPolylines (const SHPHandle &hSHP, int numberOfElements, std::string listName); + + /// Reads lines into a vector of Polyline and Surface objects. + void readPolygons (const SHPHandle &hSHP, int numberOfElements, std::string listName); + + void adjustPolylines (std::vector<GeoLib::Polyline*>* lines, std::vector<size_t> id_map); + + GeoLib::GEOObjects* _geoObjects; +}; + +#endif //SHPINTERFACE_H -- GitLab