Implemented poly2ogr, a tool which converts polygons in working directories to layers in any format writable using the OGR library.
This commit is contained in:
parent
e78a1aef88
commit
50e591df63
6 changed files with 370 additions and 2 deletions
13
configure.ac
13
configure.ac
|
@ -110,6 +110,10 @@ AC_ARG_ENABLE(ogrdecode,
|
|||
AC_HELP_STRING([--disable-ogrdecode],
|
||||
[enable ogrdecode tool (default depending on OGR availability)]))
|
||||
|
||||
AC_ARG_ENABLE(poly2ogr,
|
||||
AC_HELP_STRING([--disable-poly2ogr],
|
||||
[enable poly2ogr tool (default depending on OGR availability)]))
|
||||
|
||||
if test "$with_gdal" != "no" ; then
|
||||
if test "`basename xx/$with_gdal`" = "gdal-config" ; then
|
||||
# gdal-config was specified
|
||||
|
@ -159,7 +163,15 @@ if test x$have_ogr != xyes -a x$enable_ogrdecode = xyes; then
|
|||
using --with-gdal.])
|
||||
fi
|
||||
|
||||
if test x$have_ogr != xyes -a x$enable_poly2ogr = xyes; then
|
||||
AC_MSG_ERROR([poly2ogr was forcefully enabled but OGR was not found.
|
||||
Please make sure that you have GDAL installed with OGR enabled
|
||||
and gdal-config in your PATH resp. the path to gdal-config provided
|
||||
using --with-gdal.])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(WANT_OGRDECODE, test x$have_ogr = xyes -a x$enable_ogrdecode != xno)
|
||||
AM_CONDITIONAL(WANT_POLY2OGR, test x$have_ogr = xyes -a x$enable_poly2ogr != xno)
|
||||
|
||||
dnl Check for MS Windows environment
|
||||
AC_CHECK_HEADER(windows.h)
|
||||
|
@ -486,6 +498,7 @@ AC_CONFIG_FILES([ \
|
|||
src/Utils/Makefile \
|
||||
src/Utils/cdrom/Makefile \
|
||||
src/Utils/download-map/Makefile \
|
||||
src/Utils/poly2ogr/Makefile \
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
|
|
|
@ -325,8 +325,8 @@ void make_gpc_poly( const TGPolygon& in, gpc_polygon *out ) {
|
|||
|
||||
for ( int j = 0; j < in.contour_size( i ); ++j ) {
|
||||
p = in.get_pt( i, j );
|
||||
v_list.vertex[j].x = p.x();
|
||||
v_list.vertex[j].y = p.y();
|
||||
v_list.vertex[j].x = p.x()+2*SG_EPSILON;
|
||||
v_list.vertex[j].y = p.y()+2*SG_EPSILON;
|
||||
}
|
||||
v_list.num_vertices = in.contour_size( i );
|
||||
gpc_add_contour( out, &v_list, in.get_hole_flag( i ) );
|
||||
|
|
|
@ -3,3 +3,8 @@ EXTRA_DIST = mirror-dem
|
|||
SUBDIRS = \
|
||||
cdrom \
|
||||
download-map
|
||||
|
||||
if WANT_POLY2OGR
|
||||
SUBDIRS+=poly2ogr
|
||||
endif
|
||||
|
||||
|
|
1
src/Utils/poly2ogr/.gitignore
vendored
Normal file
1
src/Utils/poly2ogr/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
poly2ogr
|
12
src/Utils/poly2ogr/Makefile.am
Normal file
12
src/Utils/poly2ogr/Makefile.am
Normal file
|
@ -0,0 +1,12 @@
|
|||
bin_PROGRAMS = poly2ogr
|
||||
|
||||
poly2ogr_SOURCES = poly2ogr.cxx
|
||||
|
||||
poly2ogr_CXXFLAGS=$(GDAL_CFLAGS)
|
||||
|
||||
poly2ogr_LDADD = \
|
||||
$(GDAL_LIBS) \
|
||||
$(top_builddir)/src/Lib/Polygon/libPolygon.a \
|
||||
-lsgstructure -lsgmisc -lsgdebug -lz
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/Lib
|
337
src/Utils/poly2ogr/poly2ogr.cxx
Normal file
337
src/Utils/poly2ogr/poly2ogr.cxx
Normal file
|
@ -0,0 +1,337 @@
|
|||
// poly2ogr.cxx -- Translate the polygon definitions in a given TerraGear
|
||||
// working directory to vector data, writing it out using
|
||||
// the OGR library.
|
||||
//
|
||||
// Written by Ralf Gerlich, started December 2007.
|
||||
//
|
||||
// Copyright (C) 2007 Ralf Gerlich - ralf.gerlich@custom-scenery.org
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include STL_STRING
|
||||
#include <map>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <getopt.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
|
||||
#include <Polygon/polygon.hxx>
|
||||
#include <Polygon/point2d.hxx>
|
||||
|
||||
#include <ogrsf_frmts.h>
|
||||
|
||||
typedef std::map<std::string,OGRLayer*> LayerMap;
|
||||
|
||||
const char* format_name="ESRI Shapefile";
|
||||
bool do_split=false;
|
||||
|
||||
OGRDataSource *datasource;
|
||||
OGRLayer *defaultLayer;
|
||||
LayerMap layerMap;
|
||||
|
||||
bool endswith(const std::string& s, const std::string& suffix) {
|
||||
size_t slen,sufflen;
|
||||
slen=s.size();
|
||||
sufflen=suffix.size();
|
||||
if (slen<sufflen)
|
||||
return false;
|
||||
return s.compare(slen-sufflen,sufflen,suffix)==0;
|
||||
}
|
||||
|
||||
OGRLayer* create_layer(const std::string& material) {
|
||||
OGRLayer* layer;
|
||||
|
||||
OGRSpatialReference srs;
|
||||
srs.SetWellKnownGeogCS("WGS84");
|
||||
layer=datasource->CreateLayer(material.c_str(),&srs,wkbPolygon25D,NULL);
|
||||
if (!layer) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Creation of layer '" << material << "' failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OGRFieldDefn materialField("Material", OFTString);
|
||||
materialField.SetWidth(128);
|
||||
|
||||
OGRFieldDefn fileField("File",OFTString);
|
||||
fileField.SetWidth(256);
|
||||
|
||||
if( layer->CreateField( &materialField ) != OGRERR_NONE ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Creation of field 'Material' failed");
|
||||
}
|
||||
|
||||
if( layer->CreateField( &fileField ) != OGRERR_NONE ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Creation of field 'Material' failed");
|
||||
}
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
OGRLayer* get_layer_for_material(const std::string& material) {
|
||||
if (!do_split) {
|
||||
if (!defaultLayer) {
|
||||
defaultLayer=create_layer("default");
|
||||
}
|
||||
return defaultLayer;
|
||||
}
|
||||
|
||||
OGRLayer* layer;
|
||||
LayerMap::iterator it=layerMap.find(material);
|
||||
if (it==layerMap.end()) {
|
||||
layer=create_layer(material);
|
||||
if (!layer)
|
||||
return NULL;
|
||||
layerMap[material]=layer;
|
||||
} else {
|
||||
layer=(*it).second;
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
void process_polygon_file(const std::string& path) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Loading polygon file " << path);
|
||||
|
||||
sg_gzifstream in( path );
|
||||
|
||||
while (!in.eof()) {
|
||||
string first_line,material;
|
||||
bool poly3d=false;
|
||||
in >> first_line;
|
||||
if ( first_line == "#2D" ) {
|
||||
poly3d = false;
|
||||
in >> material;
|
||||
} else if ( first_line == "#3D" ) {
|
||||
poly3d = true;
|
||||
in >> material;
|
||||
} else {
|
||||
// support old format (default to 2d)
|
||||
poly3d = false;
|
||||
material=first_line;
|
||||
}
|
||||
|
||||
int contours;
|
||||
in >> contours;
|
||||
|
||||
OGRPolygon* polygon=new OGRPolygon();
|
||||
|
||||
for (int contour=0;contour<contours;contour++) {
|
||||
int count,hole_flag;
|
||||
bool skip_ring=false;
|
||||
|
||||
in >> count;
|
||||
|
||||
if (count<3) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Polygon with less than 3 points");
|
||||
skip_ring=true;
|
||||
}
|
||||
|
||||
in >> hole_flag;
|
||||
|
||||
// FIXME: Current we ignore the hole-flag and instead assume
|
||||
// that the first ring is not a hole and the rest
|
||||
// are holes
|
||||
|
||||
OGRLinearRing *ring=new OGRLinearRing();
|
||||
|
||||
for (int pt=0;pt<count;pt++) {
|
||||
OGRPoint *point=new OGRPoint();
|
||||
double x,y,z;
|
||||
|
||||
in >> x >> y;
|
||||
point->setX(x);
|
||||
point->setY(y);
|
||||
if (poly3d) {
|
||||
in >> z;
|
||||
point->setZ(z);
|
||||
} else {
|
||||
point->setZ(0.0);
|
||||
}
|
||||
|
||||
ring->addPoint(point);
|
||||
}
|
||||
|
||||
ring->closeRings();
|
||||
|
||||
if (!skip_ring)
|
||||
polygon->addRingDirectly(ring);
|
||||
}
|
||||
|
||||
OGRLayer* layer=get_layer_for_material(material);
|
||||
OGRFeature* feature;
|
||||
|
||||
feature = new OGRFeature( layer->GetLayerDefn() );
|
||||
feature->SetField("Material", material.c_str());
|
||||
feature->SetField("File", path.c_str());
|
||||
feature->SetGeometry(polygon);
|
||||
|
||||
if( layer->CreateFeature( feature ) != OGRERR_NONE )
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create feature in shapefile");
|
||||
}
|
||||
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
void process_file(const std::string& path) {
|
||||
struct stat sbuf;
|
||||
|
||||
if ( stat(path.c_str(),&sbuf) != 0 ) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to stat path '" << path << "'");
|
||||
return;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sbuf.st_mode)) {
|
||||
DIR* dir;
|
||||
|
||||
dir=opendir(path.c_str());
|
||||
if (!dir) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to open directory '" << path << "'");
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *de;
|
||||
|
||||
while ((de=readdir(dir))) {
|
||||
if (!strcmp(de->d_name,".") || !strcmp(de->d_name,"..")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string subpath=path+"/"+de->d_name;
|
||||
process_file(subpath);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
} else if (!endswith(path,".gz") &&
|
||||
!endswith(path,".arr") &&
|
||||
!endswith(path,".fit") &&
|
||||
!endswith(path,".btg") &&
|
||||
!endswith(path,".stg") &&
|
||||
!endswith(path,".ind")) {
|
||||
// should be a polygon file
|
||||
process_polygon_file(path);
|
||||
}
|
||||
}
|
||||
|
||||
void usage(const char* progname, const std::string& msg) {
|
||||
if (msg.size()!=0)
|
||||
SG_LOG(SG_GENERAL,SG_ALERT, msg);
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Usage: " << progname << " [options] dst_datasource path...");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Options:");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t-h");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t--help");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tShow this help screen");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t-v");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t--version");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tShow the version");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t-s");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t--split");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tCreate one layer per material");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t-f format");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t--format format");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tSpecify the output format");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tAvailable formats:");
|
||||
OGRSFDriverRegistrar* registrar=OGRSFDriverRegistrar::GetRegistrar();
|
||||
for (int i=0;i<registrar->GetDriverCount();i++) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\t\t-f \"" << registrar->GetDriver(i)->GetName() << "\"");
|
||||
}
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "\t\tDefault: ESRI Shapefile");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "The polygons from the given paths are read and transferred");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "to layers in the given destination datasource.");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "If one of the paths is a directory, the files in this directory");
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "and its subdirectories are read.");
|
||||
}
|
||||
|
||||
struct option options[]={
|
||||
{"help",no_argument,NULL,'h'},
|
||||
{"version",no_argument,NULL,'v'},
|
||||
{"split",no_argument,NULL,'s'},
|
||||
{"format",required_argument,NULL,'f'},
|
||||
{NULL,0,NULL,0}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
sglog().setLogLevels( SG_ALL, SG_DEBUG );
|
||||
|
||||
OGRRegisterAll();
|
||||
|
||||
int option;
|
||||
|
||||
while ((option=getopt_long(argc,argv,"hvsf:",options,NULL))!=-1) {
|
||||
switch (option) {
|
||||
case 'h':
|
||||
usage(argv[0],"");
|
||||
break;
|
||||
case 'f':
|
||||
format_name=optarg;
|
||||
break;
|
||||
case 's':
|
||||
do_split=true;
|
||||
break;
|
||||
case 'v':
|
||||
SG_LOG(SG_GENERAL,SG_INFO,argv[0] << " Version 1.0");
|
||||
exit(0);
|
||||
break;
|
||||
case '?':
|
||||
usage(argv[0],std::string("Unknown option:")+(char)optopt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind+1>argc) {
|
||||
usage(argv[0],"A datasource must be specified");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (optind+2>argc) {
|
||||
usage(argv[0],"At least one input file must be specified");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const char* dst_datasource=argv[optind++];
|
||||
OGRSFDriver *ogrdriver;
|
||||
|
||||
ogrdriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(format_name);
|
||||
if (!ogrdriver) {
|
||||
usage(argv[0],std::string("Unknown datasource format driver:")+format_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
datasource = ogrdriver->CreateDataSource(dst_datasource,NULL);
|
||||
if (!datasource) {
|
||||
usage(argv[0],std::string("Unable to create datasource:")+dst_datasource);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i=optind;i<argc;i++) {
|
||||
process_file(argv[i]);
|
||||
}
|
||||
|
||||
OGRDataSource::DestroyDataSource( datasource );
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue