[osmcoastline] 01/06: Imported Upstream version 2.1.2
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Thu Jan 7 07:16:37 UTC 2016
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository osmcoastline.
commit 373bcb54746eaf8d3a3af7d691c3588b90db2c60
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Thu Jan 7 07:40:03 2016 +0100
Imported Upstream version 2.1.2
---
.ycm_extra_conf.py | 2 +-
CHANGELOG.md | 23 +-
CMakeLists.txt | 8 +-
README.md | 15 +-
cmake/FindOsmium.cmake | 13 +-
include/gdalcpp.hpp | 406 +++++++++++++++++++++++++++++
man/manpage.template | 2 +-
man/osmcoastline.md | 3 +
man/osmcoastline_filter.md | 3 +
man/osmcoastline_readmeta.md | 9 +
man/osmcoastline_segments.md | 3 +
man/osmcoastline_ways.md | 9 +
osmcoastline_readmeta | 16 ++
src/CMakeLists.txt | 4 +-
src/coastline_handlers.hpp | 2 +-
src/coastline_polygons.cpp | 99 ++++---
src/coastline_polygons.hpp | 15 +-
src/coastline_ring.cpp | 14 +-
src/coastline_ring.hpp | 2 +-
src/coastline_ring_collection.cpp | 27 +-
src/coastline_ring_collection.hpp | 4 +-
src/ogr_include.hpp | 42 ---
src/options.cpp | 15 +-
src/options.hpp | 2 +-
src/osmcoastline.cpp | 24 +-
src/osmcoastline_filter.cpp | 70 +++--
src/osmcoastline_segments.cpp | 76 ++----
src/osmcoastline_ways.cpp | 115 +++-----
src/output_database.cpp | 236 ++++++++++-------
src/output_database.hpp | 89 +++----
src/output_layers.cpp | 321 -----------------------
src/output_layers.hpp | 124 ---------
src/{osmcoastline.hpp => return_codes.hpp} | 2 +-
src/srs.cpp | 2 +-
src/srs.hpp | 2 +-
src/stats.hpp | 2 +-
src/util.hpp | 41 +++
37 files changed, 951 insertions(+), 891 deletions(-)
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
index 53b3175..fdc78cb 100644
--- a/.ycm_extra_conf.py
+++ b/.ycm_extra_conf.py
@@ -29,7 +29,7 @@ flags = [
'-x',
'c++',
-# libosmium include dirs
+'-Iinclude',
'-I%s/../libosmium/include' % basedir,
'-I/usr/include/gdal',
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c56fb4f..d1068a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,26 @@ This project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
+## [2.1.2] - 2016-01-05
+
+### Added
+
+- Add --help/-h and --version/-V options to all programs.
+
+### Changed
+
+- Use a better approximation for the southernmost coordinate for Mercator
+ projection.
+- Updated for newest libosmium version (2.5.2).
+- Uses gdalcpp.hpp from https://github.com/joto/gdalcpp instead of directly
+ talking to GDAL/OGR. Makes this compatible with GDAL 2.
+- Improved internal code using unique_ptr where possible.
+
+### Fixed
+
+- "Fixed" flag in rings layer now correct.
+
+
## [2.1.1] - 2015-08-31
### Changed
@@ -39,7 +59,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added man pages
-[unreleased]: https://github.com/osmcode/osmium-tool/compare/v2.1.1...HEAD
+[unreleased]: https://github.com/osmcode/osmium-tool/compare/v2.1.2...HEAD
+[2.1.2]: https://github.com/osmcode/osmium-tool/compare/v2.1.1...v2.1.2
[2.1.1]: https://github.com/osmcode/osmium-tool/compare/v2.1.0...v2.1.1
[2.1.0]: https://github.com/osmcode/osmium-tool/compare/v2.0.1...v2.1.0
[2.0.1]: https://github.com/osmcode/osmium-tool/compare/v2.0.0...v2.0.1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c53c294..894b51a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,11 +22,13 @@ project(osmcoastline)
set(OSMCOASTLINE_VERSION_MAJOR 2)
set(OSMCOASTLINE_VERSION_MINOR 1)
-set(OSMCOASTLINE_VERSION_PATCH 1)
+set(OSMCOASTLINE_VERSION_PATCH 2)
set(OSMCOASTLINE_VERSION
${OSMCOASTLINE_VERSION_MAJOR}.${OSMCOASTLINE_VERSION_MINOR}.${OSMCOASTLINE_VERSION_PATCH})
+add_definitions(-DOSMCOASTLINE_VERSION="${OSMCOASTLINE_VERSION}")
+
set(AUTHOR "Jochen Topf <jochen at topf.org>")
@@ -36,6 +38,8 @@ set(AUTHOR "Jochen Topf <jochen at topf.org>")
#
#-----------------------------------------------------------------------------
+include_directories(include)
+
find_package(Osmium COMPONENTS io gdal)
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
@@ -242,7 +246,7 @@ configure_file(
configure_file(
${PROJECT_SOURCE_DIR}/osmcoastline_readmeta
${PROJECT_BINARY_DIR}/osmcoastline_readmeta
- COPYONLY
+ @ONLY
)
install(PROGRAMS osmcoastline_readmeta DESTINATION bin)
diff --git a/README.md b/README.md
index 7a8c656..081808a 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,21 @@ https://github.com/osmcode/osmcoastline
### Libosmium
- http://github.com/osmcode/libosmium
+ https://github.com/osmcode/libosmium
http://osmcode.org/libosmium
+ At least version 2.5.0 is needed.
+
+### Protozero
+
+ https://github.com/mapbox/protozero
+ Debian/Ubuntu: protozero
+ Also included in the libosmium repository.
+
+### Utfcpp
+
+ http://utfcpp.sourceforge.net/
+ Debian/Ubuntu: libutfcpp-dev
+ Also included in the libosmium repository.
### zlib (for PBF support)
diff --git a/cmake/FindOsmium.cmake b/cmake/FindOsmium.cmake
index b3a4c95..fba8ffb 100644
--- a/cmake/FindOsmium.cmake
+++ b/cmake/FindOsmium.cmake
@@ -62,6 +62,8 @@ find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp
/opt
)
+set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
+
#----------------------------------------------------------------------
#
# Check for optional components
@@ -251,20 +253,15 @@ endif()
# Check that all required libraries are available
#
#----------------------------------------------------------------------
-list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
+if (OSMIUM_EXTRA_FIND_VARS)
+ list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
+endif()
# Handle the QUIETLY and REQUIRED arguments and set OSMIUM_FOUND to TRUE if
# all listed variables are TRUE.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Osmium REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS})
unset(OSMIUM_EXTRA_FIND_VARS)
-# Copy the results to the output variables.
-if(OSMIUM_FOUND)
- set(OSMIUM_INCLUDE_DIRS ${OSMIUM_INCLUDE_DIR} ${OSMIUM_INCLUDE_DIRS})
-else()
- set(OSMIUM_INCLUDE_DIRS "")
-endif()
-
#----------------------------------------------------------------------
#
# Add compiler flags
diff --git a/include/gdalcpp.hpp b/include/gdalcpp.hpp
new file mode 100644
index 0000000..1502f2f
--- /dev/null
+++ b/include/gdalcpp.hpp
@@ -0,0 +1,406 @@
+#ifndef GDALCPP_HPP
+#define GDALCPP_HPP
+
+/*
+
+C++11 wrapper classes for GDAL/OGR.
+
+Version 1.1.1
+
+https://github.com/joto/gdalcpp
+
+Copyright 2015 Jochen Topf <jochen at topf.org>
+
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include <algorithm>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <gdal_priv.h>
+#include <gdal_version.h>
+#include <ogr_api.h>
+#include <ogrsf_frmts.h>
+
+namespace gdalcpp {
+
+#if GDAL_VERSION_MAJOR >= 2
+ using gdal_driver_type = GDALDriver;
+ using gdal_dataset_type = GDALDataset;
+#else
+ using gdal_driver_type = OGRSFDriver;
+ using gdal_dataset_type = OGRDataSource;
+#endif
+
+ /**
+ * Exception thrown for all errors in this class.
+ */
+ class gdal_error : public std::runtime_error {
+
+ std::string m_driver;
+ std::string m_dataset;
+ std::string m_layer;
+ std::string m_field;
+ OGRErr m_error;
+
+ public:
+
+ gdal_error(const std::string& message,
+ OGRErr error,
+ const std::string& driver = "",
+ const std::string& dataset = "",
+ const std::string& layer = "",
+ const std::string& field = "") :
+ std::runtime_error(message),
+ m_driver(driver),
+ m_dataset(dataset),
+ m_layer(layer),
+ m_field(field),
+ m_error(error) {
+ }
+
+ const std::string& driver() const {
+ return m_driver;
+ }
+
+ const std::string& dataset() const {
+ return m_dataset;
+ }
+
+ const std::string& layer() const {
+ return m_layer;
+ }
+
+ const std::string& field() const {
+ return m_field;
+ }
+
+ OGRErr error() const {
+ return m_error;
+ }
+
+ }; // class gdal_error
+
+ namespace detail {
+
+ struct init_wrapper {
+ init_wrapper() { OGRRegisterAll(); }
+ ~init_wrapper() { OGRCleanupAll(); }
+ };
+
+ struct init_library {
+ init_library() {
+ static init_wrapper iw;
+ }
+ };
+
+ class Driver : private init_library {
+
+ gdal_driver_type* m_driver;
+
+ public:
+
+ Driver(const std::string& driver_name) :
+ init_library(),
+#if GDAL_VERSION_MAJOR >= 2
+ m_driver(GetGDALDriverManager()->GetDriverByName(driver_name.c_str())) {
+#else
+ m_driver(OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str())) {
+#endif
+ if (!m_driver) {
+ throw gdal_error(std::string("unknown driver: '") + driver_name + "'", OGRERR_NONE, driver_name);
+ }
+ }
+
+ gdal_driver_type& get() const {
+ return *m_driver;
+ }
+
+ }; // struct Driver
+
+ struct Options {
+
+ std::vector<std::string> m_options;
+ std::unique_ptr<const char*[]> m_ptrs;
+
+ Options(const std::vector<std::string>& options) :
+ m_options(options),
+ m_ptrs(new const char*[options.size()+1]) {
+ std::transform(m_options.begin(), m_options.end(), m_ptrs.get(), [&](const std::string& s) {
+ return s.data();
+ });
+ m_ptrs[options.size()] = nullptr;
+ }
+
+ char** get() const {
+ return const_cast<char**>(m_ptrs.get());
+ }
+
+ }; // struct Options
+
+ } // namespace detail
+
+ class SRS {
+
+ OGRSpatialReference m_spatial_reference;
+
+ public:
+
+ SRS() :
+ m_spatial_reference() {
+ auto result = m_spatial_reference.SetWellKnownGeogCS("WGS84");
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("can not initialize spatial reference system WGS84"), result);
+ }
+ }
+
+ explicit SRS(int epsg) :
+ m_spatial_reference() {
+ auto result = m_spatial_reference.importFromEPSG(epsg);
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("can not initialize spatial reference system for EPSG:") + std::to_string(epsg), result);
+ }
+ }
+
+ explicit SRS(const char* name) :
+ m_spatial_reference() {
+ auto result = m_spatial_reference.importFromProj4(name);
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("can not initialize spatial reference system '") + name + "'", result);
+ }
+ }
+
+ explicit SRS(const std::string& name) :
+ m_spatial_reference() {
+ auto result = m_spatial_reference.importFromProj4(name.c_str());
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("can not initialize spatial reference system '") + name + "'", result);
+ }
+ }
+
+ explicit SRS(const OGRSpatialReference& spatial_reference) :
+ m_spatial_reference(spatial_reference) {
+ }
+
+ OGRSpatialReference& get() {
+ return m_spatial_reference;
+ }
+
+ const OGRSpatialReference& get() const {
+ return m_spatial_reference;
+ }
+
+ }; // class SRS
+
+ class Dataset {
+
+ struct gdal_dataset_deleter {
+
+ void operator()(gdal_dataset_type* ds) {
+#if GDAL_VERSION_MAJOR >= 2
+ GDALClose(ds);
+#else
+ OGRDataSource::DestroyDataSource(ds);
+#endif
+ }
+
+ }; // struct gdal_dataset_deleter
+
+ std::string m_driver_name;
+ std::string m_dataset_name;
+ detail::Options m_options;
+ SRS m_srs;
+ std::unique_ptr<gdal_dataset_type, gdal_dataset_deleter> m_dataset;
+
+ public:
+
+ Dataset(const std::string& driver_name, const std::string& dataset_name, const SRS& srs = SRS{}, const std::vector<std::string>& options = {}) :
+ m_driver_name(driver_name),
+ m_dataset_name(dataset_name),
+ m_options(options),
+ m_srs(srs),
+#if GDAL_VERSION_MAJOR >= 2
+ m_dataset(detail::Driver(driver_name).get().Create(dataset_name.c_str(), 0, 0, 0, GDT_Unknown, m_options.get())) {
+#else
+ m_dataset(detail::Driver(driver_name).get().CreateDataSource(dataset_name.c_str(), m_options.get())) {
+#endif
+ if (!m_dataset) {
+ throw gdal_error(std::string("failed to create dataset '") + dataset_name + "'", OGRERR_NONE, driver_name, dataset_name);
+ }
+ }
+
+ const std::string& driver_name() const {
+ return m_driver_name;
+ }
+
+ const std::string& dataset_name() const {
+ return m_dataset_name;
+ }
+
+ gdal_dataset_type& get() const {
+ return *m_dataset;
+ }
+
+ SRS& srs() {
+ return m_srs;
+ }
+
+ void exec(const char* sql) {
+ auto result = m_dataset->ExecuteSQL(sql, nullptr, nullptr);
+ if (result) {
+ m_dataset->ReleaseResultSet(result);
+ }
+ }
+
+ void exec(const std::string& sql) {
+ exec(sql.c_str());
+ }
+
+
+ Dataset& start_transaction() {
+#if GDAL_VERSION_MAJOR >= 2
+ m_dataset->StartTransaction();
+#endif
+ return *this;
+ }
+
+ Dataset& commit_transaction() {
+#if GDAL_VERSION_MAJOR >= 2
+ m_dataset->CommitTransaction();
+#endif
+ return *this;
+ }
+
+ }; // class Dataset
+
+ class Layer {
+
+ detail::Options m_options;
+ Dataset& m_dataset;
+ OGRLayer* m_layer;
+
+ public:
+
+ Layer(Dataset& dataset, const std::string& layer_name, OGRwkbGeometryType type, const std::vector<std::string>& options = {}) :
+ m_options(options),
+ m_dataset(dataset),
+ m_layer(dataset.get().CreateLayer(layer_name.c_str(), &dataset.srs().get(), type, m_options.get())) {
+ if (!m_layer) {
+ throw gdal_error(std::string("failed to create layer '") + layer_name + "'", OGRERR_NONE,
+ dataset.driver_name(), dataset.dataset_name(), layer_name);
+ }
+ }
+
+ OGRLayer& get() {
+ return *m_layer;
+ }
+
+ const OGRLayer& get() const {
+ return *m_layer;
+ }
+
+ Dataset& dataset() const {
+ return m_dataset;
+ }
+
+ const char* name() const {
+ return m_layer->GetName();
+ }
+
+ Layer& add_field(const std::string& field_name, OGRFieldType type, int width, int precision=0) {
+ OGRFieldDefn field(field_name.c_str(), type);
+ field.SetWidth(width);
+ field.SetPrecision(precision);
+
+ if (m_layer->CreateField(&field) != OGRERR_NONE) {
+ throw gdal_error(std::string("failed to create field '") + field_name + "' in layer '" + name() + "'", OGRERR_NONE,
+ m_dataset.driver_name(), m_dataset.dataset_name(), name(), field_name);
+ }
+
+ return *this;
+ }
+
+ Layer& start_transaction() {
+ OGRErr result = m_layer->StartTransaction();
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("starting transaction on layer '") + name() + "' failed", result, m_dataset.driver_name(), m_dataset.dataset_name(), name());
+ }
+ return *this;
+ }
+
+ Layer& commit_transaction() {
+ OGRErr result = m_layer->CommitTransaction();
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("committing transaction on layer '") + name() + "' failed", result, m_dataset.driver_name(), m_dataset.dataset_name(), name());
+ }
+ return *this;
+ }
+
+ }; // class Layer
+
+ class Feature {
+
+ Layer& m_layer;
+ OGRFeature m_feature;
+
+ public:
+
+ Feature(Layer& layer, std::unique_ptr<OGRGeometry>&& geometry) :
+ m_layer(layer),
+ m_feature(m_layer.get().GetLayerDefn()) {
+ OGRErr result = m_feature.SetGeometryDirectly(geometry.release());
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("setting feature geometry in layer '") + m_layer.name() + "' failed", result, m_layer.dataset().driver_name(), m_layer.dataset().dataset_name());
+ }
+ }
+
+ void add_to_layer() {
+ OGRErr result = m_layer.get().CreateFeature(&m_feature);
+ if (result != OGRERR_NONE) {
+ throw gdal_error(std::string("creating feature in layer '") + m_layer.name() + "' failed", result, m_layer.dataset().driver_name(), m_layer.dataset().dataset_name());
+ }
+ }
+
+ template <class T>
+ Feature& set_field(int n, T&& arg) {
+ m_feature.SetField(n, std::forward<T>(arg));
+ return *this;
+ }
+
+ template <class T>
+ Feature& set_field(const char* name, T&& arg) {
+ m_feature.SetField(name, std::forward<T>(arg));
+ return *this;
+ }
+
+ }; // class Feature
+
+} // namespace gdalcpp
+
+#endif // GDALCPP_HPP
diff --git a/man/manpage.template b/man/manpage.template
index 2f2405d..0328c7d 100644
--- a/man/manpage.template
+++ b/man/manpage.template
@@ -15,7 +15,7 @@ $endfor$
$if(author)$
.SH COPYRIGHT
.PP
-Copyright (C) 2012\-2015 Jochen Topf <jochen at topf.org>.
+Copyright (C) 2012\-2016 Jochen Topf <jochen at topf.org>.
License GPLv3+: GNU GPL version 3 or later
<http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
diff --git a/man/osmcoastline.md b/man/osmcoastline.md
index a115fb8..f1bc1d5 100644
--- a/man/osmcoastline.md
+++ b/man/osmcoastline.md
@@ -91,6 +91,9 @@ description of the options below and the README.md for details.
: Gives you detailed information on what **osmcoastline** is doing,
including timing.
+-V, --version
+: Display program version and license information.
+
# NOTES
diff --git a/man/osmcoastline_filter.md b/man/osmcoastline_filter.md
index edc1219..e750d39 100644
--- a/man/osmcoastline_filter.md
+++ b/man/osmcoastline_filter.md
@@ -40,6 +40,9 @@ the **osmcoastline** and **osmcoastline_ways** programs work fine with it.
-o, --output=OSMFILE
: Where to write output (default: none)
+-V, --version
+: Display program version and license information.
+
# EXAMPLES
diff --git a/man/osmcoastline_readmeta.md b/man/osmcoastline_readmeta.md
index e096179..0a477ab 100644
--- a/man/osmcoastline_readmeta.md
+++ b/man/osmcoastline_readmeta.md
@@ -9,6 +9,15 @@ osmcoastline_readmeta - display metadata from database create by osmcoastline
**osmcoastline_readmeta** \[*COASTLINE-DB*\]
+# OPTIONS
+
+-h, --help
+: Display usage information.
+
+-V, --version
+: Display program version and license information.
+
+
# DESCRIPTION
This program displays various meta data from a database created by the
diff --git a/man/osmcoastline_segments.md b/man/osmcoastline_segments.md
index fc0ab81..cfff865 100644
--- a/man/osmcoastline_segments.md
+++ b/man/osmcoastline_segments.md
@@ -31,6 +31,9 @@ coastline changes between different runs of the **osmcoastline** program.
-f, --format=FORMAT
: OGR format for writing out geometries.
+-V, --version
+: Display program version and license information.
+
# DIAGNOSTICS
diff --git a/man/osmcoastline_ways.md b/man/osmcoastline_ways.md
index 8ec3b25..e432960 100644
--- a/man/osmcoastline_ways.md
+++ b/man/osmcoastline_ways.md
@@ -9,6 +9,15 @@ osmcoastline_ways - extract coastline ways from OSM data
**osmcoastline_ways** *INPUT-FILE* \[*OUTPUT-DB*\]
+# OPTIONS
+
+-h, --help
+: Display usage information.
+
+-V, --version
+: Display program version and license information.
+
+
# DESCRIPTION
**osmcoastline_ways** extracts coastline ways from OSM data and writes them
diff --git a/osmcoastline_readmeta b/osmcoastline_readmeta
index f1478b3..a12bf9e 100755
--- a/osmcoastline_readmeta
+++ b/osmcoastline_readmeta
@@ -3,8 +3,24 @@
# osmcoastline_readmeta [COASTLINEDB]
#
+OSMCOASTLINE_VERSION=@OSMCOASTLINE_VERSION@
+
SQLEXEC="sqlite3"
+if [ "x$1" = "x--help" -o "x$1" = "x-h" ]; then
+ echo "Usage: osmcoastline_readmeta [COASTLINEDB]"
+ exit 0
+fi
+
+if [ "x$1" = "x--version" -o "x$1" = "x-V" ]; then
+ echo "osmcoastline_readmeta version $OSMCOASTLINE_VERSION"
+ echo "Copyright (C) 2012-2016 Jochen Topf <jochen at topf.org>"
+ echo "License: GNU GENERAL PUBLIC LICENSE Version 3 <http://gnu.org/licenses/gpl.html>."
+ echo "This is free software: you are free to change and redistribute it."
+ echo "There is NO WARRANTY, to the extent permitted by law.";
+ exit 0
+fi
+
if [ "x$1" = "x" ]; then
DBFILE=testdata.db
else
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 907dd1c..ce62288 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,7 +6,7 @@
#
#-----------------------------------------------------------------------------
-add_executable(osmcoastline osmcoastline.cpp coastline_ring.cpp coastline_ring_collection.cpp coastline_polygons.cpp output_database.cpp output_layers.cpp srs.cpp options.cpp)
+add_executable(osmcoastline osmcoastline.cpp coastline_ring.cpp coastline_ring_collection.cpp coastline_polygons.cpp output_database.cpp srs.cpp options.cpp)
target_link_libraries(osmcoastline ${OSMIUM_IO_LIBRARIES} ${GDAL_LIBRARIES} ${GEOS_C_LIBRARIES})
install(TARGETS osmcoastline DESTINATION bin)
@@ -18,7 +18,7 @@ add_executable(osmcoastline_segments osmcoastline_segments.cpp srs.cpp)
target_link_libraries(osmcoastline_segments ${GDAL_LIBRARIES})
install(TARGETS osmcoastline_segments DESTINATION bin)
-add_executable(osmcoastline_ways osmcoastline_ways.cpp osmcoastline.hpp)
+add_executable(osmcoastline_ways osmcoastline_ways.cpp return_codes.hpp)
target_link_libraries(osmcoastline_ways ${OSMIUM_IO_LIBRARIES} ${GDAL_LIBRARIES})
install(TARGETS osmcoastline_ways DESTINATION bin)
diff --git a/src/coastline_handlers.hpp b/src/coastline_handlers.hpp
index 2eeca6f..449b2d4 100644
--- a/src/coastline_handlers.hpp
+++ b/src/coastline_handlers.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/coastline_polygons.cpp b/src/coastline_polygons.cpp
index 8094327..255e7b8 100644
--- a/src/coastline_polygons.cpp
+++ b/src/coastline_polygons.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -28,8 +28,9 @@
#include "coastline_polygons.hpp"
#include "output_database.hpp"
-#include "osmcoastline.hpp"
+#include "return_codes.hpp"
#include "srs.hpp"
+#include "util.hpp"
extern SRS srs;
extern bool debug;
@@ -73,7 +74,7 @@ unsigned int CoastlinePolygons::fix_direction() {
// Workaround for bug in OGR: reverseWindingOrder sets dimensions to 3
polygon->getInteriorRing(i)->setCoordinateDimension(2);
}
- m_output.add_error_line(static_cast<OGRLineString*>(er->clone()), "direction");
+ m_output.add_error_line(make_unique_ptr_clone<OGRLineString>(er), "direction");
warnings++;
}
}
@@ -83,26 +84,26 @@ unsigned int CoastlinePolygons::fix_direction() {
void CoastlinePolygons::transform() {
for (const auto& polygon : m_polygons) {
- srs.transform(polygon);
+ srs.transform(polygon.get());
}
}
-void CoastlinePolygons::split_geometry(std::unique_ptr<OGRGeometry> geom, int level) {
+void CoastlinePolygons::split_geometry(std::unique_ptr<OGRGeometry>&& geom, int level) {
if (geom->getGeometryType() == wkbPolygon) {
geom->assignSpatialReference(srs.out());
- split_polygon(static_cast<OGRPolygon*>(geom.release()), level);
+ split_polygon(static_cast_unique_ptr<OGRPolygon>(std::move(geom)), level);
} else { // wkbMultiPolygon
- const auto mp = static_cast<OGRMultiPolygon*>(geom.get());
+ const auto mp = static_cast_unique_ptr<OGRMultiPolygon>(std::move(geom));
while (mp->getNumGeometries() > 0) {
std::unique_ptr<OGRPolygon> polygon { static_cast<OGRPolygon*>(mp->getGeometryRef(0)) };
mp->removeGeometry(0, false);
polygon->assignSpatialReference(srs.out());
- split_polygon(polygon.release(), level);
+ split_polygon(std::move(polygon), level);
}
}
}
-void CoastlinePolygons::split_polygon(OGRPolygon* polygon, int level) {
+void CoastlinePolygons::split_polygon(std::unique_ptr<OGRPolygon>&& polygon, int level) {
if (level > m_max_split_depth) {
m_max_split_depth = level;
}
@@ -190,10 +191,11 @@ void CoastlinePolygons::split_polygon(OGRPolygon* polygon, int level) {
void CoastlinePolygons::split() {
polygon_vector_type v;
- std::swap(v, m_polygons);
+ using std::swap;
+ swap(v, m_polygons);
m_polygons.reserve(v.size());
for (auto& polygon : v) {
- split_polygon(polygon, 0);
+ split_polygon(std::move(polygon), 0);
}
}
@@ -201,16 +203,17 @@ void CoastlinePolygons::output_land_polygons(bool make_copy) {
if (make_copy) {
// because adding to a layer destroys the geometry, we need to copy it if it is needed later
for (const auto& polygon : m_polygons) {
- m_output.add_land_polygon(static_cast<OGRPolygon*>(polygon->clone()));
+ m_output.add_land_polygon(make_unique_ptr_clone<OGRPolygon>(polygon.get()));
}
} else {
for (auto& polygon : m_polygons) {
- m_output.add_land_polygon(polygon);
+ m_output.add_land_polygon(std::move(polygon));
}
+ m_polygons.clear();
}
}
-bool CoastlinePolygons::add_segment_to_line(OGRLineString* line, OGRPoint* point1, OGRPoint* point2) {
+bool CoastlinePolygons::add_segment_to_line(OGRLineString* line, OGRPoint* point1, OGRPoint* point2) const {
// segments along southern edge of the map are not added to line output
if (point1->getY() < srs.min_y() && point2->getY() < srs.min_y()) {
if (debug) {
@@ -235,9 +238,15 @@ bool CoastlinePolygons::add_segment_to_line(OGRLineString* line, OGRPoint* point
return true;
}
+void CoastlinePolygons::add_line_to_output(std::unique_ptr<OGRLineString> line, OGRSpatialReference* srs) const {
+ line->setCoordinateDimension(2);
+ line->assignSpatialReference(srs);
+ m_output.add_line(std::move(line));
+}
+
// Add a coastline ring as LineString to output. Segments in this line that are
// near the southern edge of the map or near the antimeridian are suppressed.
-void CoastlinePolygons::output_polygon_ring_as_lines(int max_points, OGRLinearRing* ring) {
+void CoastlinePolygons::output_polygon_ring_as_lines(int max_points, const OGRLinearRing* ring) const {
int num = ring->getNumPoints();
assert(num > 2);
@@ -253,11 +262,10 @@ void CoastlinePolygons::output_polygon_ring_as_lines(int max_points, OGRLinearRi
if (line->getNumPoints() >= max_points || !added) {
if (line->getNumPoints() >= 2) {
- line->setCoordinateDimension(2);
- line->assignSpatialReference(ring->getSpatialReference());
std::unique_ptr<OGRLineString> new_line { new OGRLineString };
- std::swap(line, new_line);
- m_output.add_line(std::move(new_line));
+ using std::swap;
+ swap(line, new_line);
+ add_line_to_output(std::move(new_line), ring->getSpatialReference());
}
}
@@ -266,14 +274,12 @@ void CoastlinePolygons::output_polygon_ring_as_lines(int max_points, OGRLinearRi
}
if (line->getNumPoints() >= 2) {
- line->setCoordinateDimension(2);
- line->assignSpatialReference(ring->getSpatialReference());
- m_output.add_line(std::move(line));
+ add_line_to_output(std::move(line), ring->getSpatialReference());
}
}
-void CoastlinePolygons::output_lines(int max_points) {
- for (OGRPolygon* polygon : m_polygons) {
+void CoastlinePolygons::output_lines(int max_points) const {
+ for (const auto& polygon : m_polygons) {
output_polygon_ring_as_lines(max_points, polygon->getExteriorRing());
for (int i=0; i < polygon->getNumInteriorRings(); ++i) {
output_polygon_ring_as_lines(max_points, polygon->getInteriorRing(i));
@@ -287,25 +293,27 @@ void CoastlinePolygons::split_bbox(OGREnvelope e, polygon_vector_type&& v) {
try {
std::unique_ptr<OGRGeometry> geom { create_rectangular_polygon(e.MinX, e.MinY, e.MaxX, e.MaxY, m_expand) };
assert(geom->getSpatialReference() != nullptr);
- for (const OGRPolygon* polygon : v) {
- OGRGeometry* diff = geom->Difference(polygon);
+ for (const auto& polygon : v) {
+ std::unique_ptr<OGRGeometry> diff { geom->Difference(polygon.get()) };
// for some reason there is sometimes no srs on the geometries, so we add them on
diff->assignSpatialReference(srs.out());
- geom.reset(diff);
+ geom = std::move(diff);
}
if (geom) {
switch (geom->getGeometryType()) {
case wkbPolygon:
- m_output.add_water_polygon(static_cast<OGRPolygon*>(geom.release()));
+ m_output.add_water_polygon(static_cast_unique_ptr<OGRPolygon>(std::move(geom)));
break;
- case wkbMultiPolygon:
- for (int i=static_cast<OGRMultiPolygon*>(geom.get())->getNumGeometries() - 1; i >= 0; --i) {
- OGRPolygon* p = static_cast<OGRPolygon*>(static_cast<OGRMultiPolygon*>(geom.get())->getGeometryRef(i));
- p->assignSpatialReference(geom->getSpatialReference());
- static_cast<OGRMultiPolygon*>(geom.get())->removeGeometry(i, FALSE);
- m_output.add_water_polygon(p);
+ case wkbMultiPolygon: {
+ auto mp = static_cast_unique_ptr<OGRMultiPolygon>(std::move(geom));
+ for (int i = mp->getNumGeometries() - 1; i >= 0; --i) {
+ auto p = std::unique_ptr<OGRPolygon>(static_cast<OGRPolygon*>(mp->getGeometryRef(i)));
+ p->assignSpatialReference(mp->getSpatialReference());
+ mp->removeGeometry(i, FALSE);
+ m_output.add_water_polygon(std::move(p));
+ }
+ break;
}
- break;
case wkbGeometryCollection:
// XXX
break;
@@ -355,19 +363,24 @@ void CoastlinePolygons::split_bbox(OGREnvelope e, polygon_vector_type&& v) {
polygon_vector_type v1;
polygon_vector_type v2;
- for (OGRPolygon* polygon : v) {
+ for (auto& polygon : v) {
/* You might think re-computing the envelope of all those polygons
again and again might take a lot of time, but I benchmarked it and
it has no measurable impact. */
OGREnvelope e;
polygon->getEnvelope(&e);
- if (e1.Intersects(e)) {
- v1.push_back(polygon);
- }
- if (e2.Intersects(e)) {
- v2.push_back(polygon);
+ bool e1_intersects_e = e1.Intersects(e);
+ bool e2_intersects_e = e2.Intersects(e);
+
+ if (e1_intersects_e && e2_intersects_e) {
+ v1.emplace_back(static_cast<OGRPolygon*>(polygon->clone()));
+ v2.push_back(std::move(polygon));
+ } else if (e1_intersects_e) {
+ v1.push_back(std::move(polygon));
+ } else if (e2_intersects_e) {
+ v2.push_back(std::move(polygon));
}
}
split_bbox(e1, std::move(v1));
@@ -379,9 +392,9 @@ void CoastlinePolygons::split_bbox(OGREnvelope e, polygon_vector_type&& v) {
unsigned int CoastlinePolygons::output_water_polygons() {
unsigned int warnings = 0;
polygon_vector_type v;
- for (OGRPolygon* polygon : m_polygons) {
+ for (auto& polygon : m_polygons) {
if (polygon->IsValid()) {
- v.push_back(polygon);
+ v.push_back(std::move(polygon));
} else {
std::cerr << "Invalid polygon, trying buffer(0).\n";
++warnings;
diff --git a/src/coastline_polygons.hpp b/src/coastline_polygons.hpp
index 7d7e8a4..9296248 100644
--- a/src/coastline_polygons.hpp
+++ b/src/coastline_polygons.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -34,7 +34,7 @@ class OGRMultiPolygon;
class OGREnvelope;
class OutputDatabase;
-typedef std::vector<OGRPolygon*> polygon_vector_type;
+typedef std::vector<std::unique_ptr<OGRPolygon>> polygon_vector_type;
/**
* A collection of land polygons created out of coastlines.
@@ -74,12 +74,13 @@ class CoastlinePolygons {
std::unique_ptr<OGRPolygon> create_rectangular_polygon(double x1, double y1, double x2, double y2, double expand=0) const;
- void split_geometry(std::unique_ptr<OGRGeometry> geom, int level);
- void split_polygon(OGRPolygon* polygon, int level);
+ void split_geometry(std::unique_ptr<OGRGeometry>&& geom, int level);
+ void split_polygon(std::unique_ptr<OGRPolygon>&& polygon, int level);
void split_bbox(OGREnvelope e, polygon_vector_type&& v);
- bool add_segment_to_line(OGRLineString* line, OGRPoint* point1, OGRPoint* point2);
- void output_polygon_ring_as_lines(int max_points, OGRLinearRing* ring);
+ void add_line_to_output(std::unique_ptr<OGRLineString> line, OGRSpatialReference* srs) const;
+ bool add_segment_to_line(OGRLineString* line, OGRPoint* point1, OGRPoint* point2) const;
+ void output_polygon_ring_as_lines(int max_points, const OGRLinearRing* ring) const;
public:
@@ -120,7 +121,7 @@ public:
unsigned int output_water_polygons();
/// Write all coastlines to the output database (as lines).
- void output_lines(int max_points);
+ void output_lines(int max_points) const;
};
diff --git a/src/coastline_ring.cpp b/src/coastline_ring.cpp
index 8a078a1..ef4057f 100644
--- a/src/coastline_ring.cpp
+++ b/src/coastline_ring.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -90,18 +90,18 @@ void CoastlineRing::close_ring() {
}
void CoastlineRing::close_antarctica_ring(int epsg) {
- double min = epsg == 4326 ? -90.0 : -85.0511;
+ double min = epsg == 4326 ? -90.0 : -85.0511288;
- for (double lat = -78.0; lat > min; --lat) {
- m_way_node_list.emplace_back(0, osmium::Location(-179.99999, static_cast<double>(lat)));
+ for (int lat = -78; lat > int(min); --lat) {
+ m_way_node_list.emplace_back(0, osmium::Location(-179.99999, double(lat)));
}
for (int lon = -180; lon < 180; ++lon) {
- m_way_node_list.emplace_back(0, osmium::Location(static_cast<double>(lon), min));
+ m_way_node_list.emplace_back(0, osmium::Location(double(lon), min));
}
- for (double lat = min; lat < -78.0; ++lat) {
- m_way_node_list.emplace_back(0, osmium::Location(179.99999, static_cast<double>(lat)));
+ for (int lat = int(min); lat < -78; ++lat) {
+ m_way_node_list.emplace_back(0, osmium::Location(179.99999, double(lat)));
}
m_way_node_list.push_back(m_way_node_list.front());
diff --git a/src/coastline_ring.hpp b/src/coastline_ring.hpp
index e930b7a..48d7c86 100644
--- a/src/coastline_ring.hpp
+++ b/src/coastline_ring.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/coastline_ring_collection.cpp b/src/coastline_ring_collection.cpp
index 3101514..56b0c43 100644
--- a/src/coastline_ring_collection.cpp
+++ b/src/coastline_ring_collection.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -126,7 +126,16 @@ unsigned int CoastlineRingCollection::check_positions(bool output_missing) {
return missing_positions;
}
-void CoastlineRingCollection::add_polygons_to_vector(std::vector<OGRGeometry*>& vector) {
+bool is_valid_polygon(const OGRGeometry* geometry) {
+ if (geometry && geometry->getGeometryType() == wkbPolygon) {
+ const auto polygon = static_cast<const OGRPolygon*>(geometry);
+ return (polygon->getExteriorRing()->getNumPoints() > 3) && (polygon->getNumInteriorRings() == 0) && geometry->IsValid();
+ }
+ return false;
+}
+
+std::vector<OGRGeometry*> CoastlineRingCollection::add_polygons_to_vector() {
+ std::vector<OGRGeometry*> vector;
vector.reserve(m_list.size());
for (const auto& ring : m_list) {
@@ -137,15 +146,17 @@ void CoastlineRingCollection::add_polygons_to_vector(std::vector<OGRGeometry*>&
vector.push_back(p.release());
} else {
std::unique_ptr<OGRGeometry> geom { p->Buffer(0) };
- if (geom && (geom->getGeometryType() == wkbPolygon) && (static_cast<OGRPolygon*>(geom.get())->getExteriorRing()->getNumPoints() > 3) && (static_cast<OGRPolygon*>(geom.get())->getNumInteriorRings() == 0) && geom->IsValid()) {
+ if (is_valid_polygon(geom.get())) {
geom->assignSpatialReference(srs.wgs84());
- vector.push_back(static_cast<OGRPolygon*>(geom.release()));
+ vector.push_back(geom.release());
} else {
std::cerr << "Ignoring invalid polygon geometry (ring_id=" << ring->ring_id() << ").\n";
}
}
}
}
+
+ return vector;
}
unsigned int CoastlineRingCollection::output_rings(OutputDatabase& output) {
@@ -154,18 +165,18 @@ unsigned int CoastlineRingCollection::output_rings(OutputDatabase& output) {
for (const auto& ring : m_list) {
if (ring->is_closed()) {
if (ring->npoints() > 3) {
- output.add_ring(ring->ogr_polygon(m_factory, true).release(), ring->ring_id(), ring->nways(), ring->npoints(), ring->is_fixed());
+ output.add_ring(ring->ogr_polygon(m_factory, true), ring->ring_id(), ring->nways(), ring->npoints(), ring->is_fixed());
} else if (ring->npoints() == 1) {
output.add_error_point(ring->ogr_first_point(), "single_point_in_ring", ring->first_node_id());
warnings++;
} else { // ring->npoints() == 2 or 3
- output.add_error_line(ring->ogr_linestring(m_factory, true).release(), "not_a_ring", ring->ring_id());
+ output.add_error_line(ring->ogr_linestring(m_factory, true), "not_a_ring", ring->ring_id());
output.add_error_point(ring->ogr_first_point(), "not_a_ring", ring->first_node_id());
output.add_error_point(ring->ogr_last_point(), "not_a_ring", ring->last_node_id());
warnings++;
}
} else {
- output.add_error_line(ring->ogr_linestring(m_factory, true).release(), "not_closed", ring->ring_id());
+ output.add_error_line(ring->ogr_linestring(m_factory, true), "not_closed", ring->ring_id());
output.add_error_point(ring->ogr_first_point(), "end_point", ring->first_node_id());
output.add_error_point(ring->ogr_last_point(), "end_point", ring->last_node_id());
warnings++;
@@ -409,7 +420,7 @@ unsigned int CoastlineRingCollection::output_questionable(const CoastlinePolygon
// go through all the polygons that have been created before and mark the outer rings
for (const auto& polygon : polygons) {
- OGRLinearRing* exterior_ring = polygon->getExteriorRing();
+ const OGRLinearRing* exterior_ring = polygon->getExteriorRing();
osmium::Location pos(exterior_ring->getX(0), exterior_ring->getY(0));
std::vector<pos_ring_ptr_t>::iterator rings_it = lower_bound(rings.begin(), rings.end(), std::make_pair<osmium::Location, CoastlineRing*>(std::move(pos), nullptr));
if (rings_it != rings.end()) {
diff --git a/src/coastline_ring_collection.hpp b/src/coastline_ring_collection.hpp
index 21e6f7e..bef8eb1 100644
--- a/src/coastline_ring_collection.hpp
+++ b/src/coastline_ring_collection.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -105,7 +105,7 @@ public:
unsigned int check_positions(bool output_missing);
- void add_polygons_to_vector(std::vector<OGRGeometry*>& vector);
+ std::vector<OGRGeometry*> add_polygons_to_vector();
unsigned int output_rings(OutputDatabase& output);
diff --git a/src/ogr_include.hpp b/src/ogr_include.hpp
deleted file mode 100644
index d372d6a..0000000
--- a/src/ogr_include.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef OGR_INCLUDE_HPP
-#define OGR_INCLUDE_HPP
-
-#ifdef _MSC_VER
-# pragma warning(push)
-# pragma warning(disable : 4458)
-# pragma warning(disable : 4251)
-#else
-# pragma GCC diagnostic push
-# ifdef __clang__
-# pragma GCC diagnostic ignored "-Wdocumentation-unknown-command"
-# endif
-# pragma GCC diagnostic ignored "-Wfloat-equal"
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-# pragma GCC diagnostic ignored "-Wpadded"
-# pragma GCC diagnostic ignored "-Wredundant-decls"
-# pragma GCC diagnostic ignored "-Wshadow"
-#endif
-
-/* Strictly speaking the following include would be enough here,
- but everybody using this file will very likely need the other includes,
- so we are adding them here, so that not everybody will need all those
- pragmas to disable warnings. */
-//#include <ogr_geometry.h>
-#include <ogr_api.h>
-#include <ogrsf_frmts.h>
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#else
-# pragma GCC diagnostic pop
-#endif
-
-struct OGRDataSourceDestroyer {
- void operator()(OGRDataSource* ptr) {
- if (ptr) {
- OGRDataSource::DestroyDataSource(ptr);
- }
- }
-};
-
-#endif // OGR_INCLUDE_HPP
diff --git a/src/options.cpp b/src/options.cpp
index 7c11a24..fd51edd 100644
--- a/src/options.cpp
+++ b/src/options.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -25,7 +25,7 @@
#include <cstdlib>
#include <getopt.h>
-#include "osmcoastline.hpp"
+#include "return_codes.hpp"
#include "options.hpp"
Options::Options(int argc, char* argv[]) :
@@ -62,11 +62,12 @@ Options::Options(int argc, char* argv[]) :
{"srs", required_argument, 0, 's'},
{"write-segments", required_argument, 0, 'S'},
{"verbose", no_argument, 0, 'v'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
while (1) {
- int c = getopt_long(argc, argv, "b:c:idhlm:o:p:rfs:S:v", long_options, 0);
+ int c = getopt_long(argc, argv, "b:c:idhlm:o:p:rfs:S:vV", long_options, 0);
if (c == -1)
break;
@@ -131,6 +132,13 @@ Options::Options(int argc, char* argv[]) :
case 'v':
verbose = true;
break;
+ case 'V':
+ std::cout << "osmcoastline version " OSMCOASTLINE_VERSION "\n"
+ << "Copyright (C) 2012-2016 Jochen Topf <jochen at topf.org>\n"
+ << "License: GNU GENERAL PUBLIC LICENSE Version 3 <http://gnu.org/licenses/gpl.html>.\n"
+ << "This is free software: you are free to change and redistribute it.\n"
+ << "There is NO WARRANTY, to the extent permitted by law.\n";
+ exit(return_code_ok);
default:
exit(return_code_cmdline);
}
@@ -197,6 +205,7 @@ void Options::print_help() const {
<< " -s, --srs=EPSGCODE - Set SRS (4326 for WGS84 (default) or 3857)\n"
<< " -S, --write-segments=FILE - Write segments to given file\n"
<< " -v, --verbose - Verbose output\n"
+ << " -V, --version - Show version and exit\n"
<< "\n";
}
diff --git a/src/options.hpp b/src/options.hpp
index f6d8dc6..57e04dc 100644
--- a/src/options.hpp
+++ b/src/options.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/osmcoastline.cpp b/src/osmcoastline.cpp
index 5f8adcf..262b81b 100644
--- a/src/osmcoastline.cpp
+++ b/src/osmcoastline.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -27,17 +27,17 @@
#include <osmium/io/any_input.hpp>
#include <osmium/visitor.hpp>
-#include "osmcoastline.hpp"
+#include "return_codes.hpp"
#include "coastline_ring.hpp"
#include "coastline_ring_collection.hpp"
#include "coastline_polygons.hpp"
#include "output_database.hpp"
-#include "output_layers.hpp"
#include "options.hpp"
#include "stats.hpp"
#include "coastline_handlers.hpp"
#include "srs.hpp"
+#include "util.hpp"
#include "verbose_output.hpp"
// The global SRS object is used in many places to transform
@@ -56,8 +56,7 @@ const unsigned int max_warnings = 500;
* This function assembles all the coastline rings into one huge multipolygon.
*/
polygon_vector_type create_polygons(CoastlineRingCollection& coastline_rings, OutputDatabase& output, unsigned int* warnings, unsigned int* errors) {
- std::vector<OGRGeometry*> all_polygons;
- coastline_rings.add_polygons_to_vector(all_polygons);
+ std::vector<OGRGeometry*> all_polygons = coastline_rings.add_polygons_to_vector();
int is_valid;
const char* options[] = { "METHOD=ONLY_CCW", nullptr };
@@ -69,8 +68,10 @@ polygon_vector_type create_polygons(CoastlineRingCollection& coastline_rings, Ou
std::cerr << "organizePolygons() done\n";
}
- assert(mega_geometry->getGeometryType() == wkbMultiPolygon);
- OGRMultiPolygon* mega_multipolygon = static_cast<OGRMultiPolygon*>(mega_geometry.get());
+ if (mega_geometry->getGeometryType() != wkbMultiPolygon) {
+ throw std::runtime_error("mega geometry isn't a multipolygon. Something is very wrong!");
+ }
+ OGRMultiPolygon* mega_multipolygon = static_cast<OGRMultiPolygon*>(mega_geometry.release());
polygon_vector_type polygons;
polygons.reserve(mega_multipolygon->getNumGeometries());
@@ -79,13 +80,13 @@ polygon_vector_type create_polygons(CoastlineRingCollection& coastline_rings, Ou
assert(geom->getGeometryType() == wkbPolygon);
std::unique_ptr<OGRPolygon> p { static_cast<OGRPolygon*>(geom) };
if (p->IsValid()) {
- polygons.push_back(p.release());
+ polygons.push_back(std::move(p));
} else {
- output.add_error_line(static_cast<OGRLineString*>(p->getExteriorRing()->clone()), "invalid");
+ output.add_error_line(make_unique_ptr_clone<OGRLineString>(p->getExteriorRing()), "invalid");
std::unique_ptr<OGRGeometry> buf0 { p->Buffer(0) };
if (buf0 && buf0->getGeometryType() == wkbPolygon && buf0->IsValid()) {
buf0->assignSpatialReference(srs.wgs84());
- polygons.emplace_back(static_cast<OGRPolygon*>(buf0.release()));
+ polygons.push_back(static_cast_unique_ptr<OGRPolygon>(std::move(buf0)));
(*warnings)++;
} else {
std::cerr << "Ignoring invalid polygon geometry.\n";
@@ -95,6 +96,7 @@ polygon_vector_type create_polygons(CoastlineRingCollection& coastline_rings, Ou
}
mega_multipolygon->removeGeometry(-1, FALSE);
+ delete mega_multipolygon;
return polygons;
}
@@ -183,7 +185,7 @@ int main(int argc, char *argv[]) {
} else {
vout << "Will NOT create geometry index (because you told me to using --no-index/-i).\n";
}
- OutputDatabase output_database(options.output_database, options.create_index);
+ OutputDatabase output_database(options.output_database, srs, options.create_index);
// The collection of all coastline rings we will be filling and then
// operating on.
diff --git a/src/osmcoastline_filter.cpp b/src/osmcoastline_filter.cpp
index a89bfec..9a3f951 100644
--- a/src/osmcoastline_filter.cpp
+++ b/src/osmcoastline_filter.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -19,22 +19,26 @@
*/
+#include <algorithm>
#include <iostream>
#include <set>
#include <getopt.h>
#include <osmium/io/any_input.hpp>
+#include <osmium/io/input_iterator.hpp>
+#include <osmium/io/output_iterator.hpp>
#include <osmium/io/pbf_output.hpp>
#include <osmium/handler.hpp>
#include <osmium/osm/entity_bits.hpp>
-#include "osmcoastline.hpp"
+#include "return_codes.hpp"
void print_help() {
std::cout << "osmcoastline_filter [OPTIONS] OSMFILE\n"
<< "\nOptions:\n"
<< " -h, --help - This help message\n"
<< " -o, --output=OSMFILE - Where to write output (default: none)\n"
+ << " -V, --version - Show version and exit\n"
<< "\n";
}
@@ -44,11 +48,12 @@ int main(int argc, char* argv[]) {
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"output", required_argument, 0, 'o'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
while (1) {
- int c = getopt_long(argc, argv, "ho:", long_options, 0);
+ int c = getopt_long(argc, argv, "ho:V", long_options, 0);
if (c == -1)
break;
@@ -59,6 +64,13 @@ int main(int argc, char* argv[]) {
case 'o':
output_filename = optarg;
break;
+ case 'V':
+ std::cout << "osmcoastline_filter version " OSMCOASTLINE_VERSION "\n"
+ << "Copyright (C) 2012-2016 Jochen Topf <jochen at topf.org>\n"
+ << "License: GNU GENERAL PUBLIC LICENSE Version 3 <http://gnu.org/licenses/gpl.html>.\n"
+ << "This is free software: you are free to change and redistribute it.\n"
+ << "There is NO WARRANTY, to the extent permitted by law.\n";
+ exit(return_code_ok);
default:
exit(return_code_fatal);
}
@@ -82,55 +94,39 @@ int main(int argc, char* argv[]) {
try {
osmium::io::Writer writer(output_filename, header);
+ auto output_it = osmium::io::make_output_iterator(writer);
- std::set<osmium::object_id_type> ids;
- osmium::memory::Buffer output_buffer(10240);
+ std::vector<osmium::object_id_type> ids;
{
osmium::io::Reader reader(infile, osmium::osm_entity_bits::way);
- while (auto input_buffer = reader.read()) {
- for (auto it = input_buffer.begin<const osmium::Way>(); it != input_buffer.end<const osmium::Way>(); ++it) {
- const char* natural = it->get_value_by_key("natural");
- if (natural && !strcmp(natural, "coastline")) {
- output_buffer.add_item(*it);
- output_buffer.commit();
- if (output_buffer.committed() >= 10240) {
- osmium::memory::Buffer new_buffer(10240);
- std::swap(output_buffer, new_buffer);
- writer(std::move(new_buffer));
- }
- for (const auto& nr : it->nodes()) {
- ids.insert(nr.ref());
- }
+ auto ways = osmium::io::make_input_iterator_range<const osmium::Way>(reader);
+ for (const osmium::Way& way : ways) {
+ const char* natural = way.get_value_by_key("natural");
+ if (natural && !strcmp(natural, "coastline")) {
+ *output_it++ = way;
+ for (const auto& nr : way.nodes()) {
+ ids.push_back(nr.ref());
}
}
}
reader.close();
}
+ std::sort(ids.begin(), ids.end());
+ auto last = std::unique(ids.begin(), ids.end());
+
{
osmium::io::Reader reader(infile, osmium::osm_entity_bits::node);
- while (auto input_buffer = reader.read()) {
- for (auto it = input_buffer.begin<const osmium::Node>(); it != input_buffer.end<const osmium::Node>(); ++it) {
- const char* natural = it->get_value_by_key("natural");
- if ((ids.find(it->id()) != ids.end()) || (natural && !strcmp(natural, "coastline"))) {
- output_buffer.add_item(*it);
- output_buffer.commit();
- if (output_buffer.committed() >= 10240) {
- osmium::memory::Buffer new_buffer(10240);
- std::swap(output_buffer, new_buffer);
- writer(std::move(new_buffer));
- }
- }
- }
- }
+ auto nodes = osmium::io::make_input_iterator_range<const osmium::Node>(reader);
+ std::copy_if(nodes.cbegin(), nodes.cend(), output_it, [&ids, &last](const osmium::Node& node){
+ const char* natural = node.get_value_by_key("natural");
+ return std::binary_search(ids.begin(), last, node.id()) ||
+ (natural && !strcmp(natural, "coastline"));
+ });
reader.close();
}
- if (output_buffer.committed() > 0) {
- writer(std::move(output_buffer));
- }
-
writer.close();
} catch (osmium::io_error& e) {
std::cerr << "io error: " << e.what() << "'\n";
diff --git a/src/osmcoastline_segments.cpp b/src/osmcoastline_segments.cpp
index 1702960..9dd74c5 100644
--- a/src/osmcoastline_segments.cpp
+++ b/src/osmcoastline_segments.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -35,9 +35,9 @@
#include <osmium/osm/undirected_segment.hpp>
#include <osmium/util/memory_mapping.hpp>
-#include "ogr_include.hpp"
-#include "osmcoastline.hpp"
-#include "srs.hpp"
+#include <gdalcpp.hpp>
+
+#include "return_codes.hpp"
typedef std::vector<osmium::UndirectedSegment> segvec;
@@ -73,56 +73,22 @@ public:
void print_help() {
}
-void add_segment(OGRLayer* layer, int change, const osmium::UndirectedSegment& segment) {
- OGRFeature* feature = OGRFeature::CreateFeature(layer->GetLayerDefn());
-
- auto linestring = new OGRLineString();
+void add_segment(gdalcpp::Layer& layer, int change, const osmium::UndirectedSegment& segment) {
+ auto linestring = std::unique_ptr<OGRLineString>(new OGRLineString());
linestring->addPoint(segment.first().lon(), segment.first().lat());
linestring->addPoint(segment.second().lon(), segment.second().lat());
- feature->SetGeometryDirectly(linestring);
- feature->SetField("change", change);
-
- if (layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature on layer 'changes'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
+ gdalcpp::Feature feature(layer, std::move(linestring));
+ feature.set_field("change", change);
+ feature.add_to_layer();
}
void output_ogr(const std::string& filename, const std::string& driver_name, const segvec& removed_segments, const segvec& added_segments) {
- OGRRegisterAll();
+ gdalcpp::Dataset dataset{driver_name, filename};
- OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str());
- if (!driver) {
- std::cerr << driver_name << " driver not available.\n";
- exit(return_code_fatal);
- }
-
- //const char* options[] = { "SPATIALITE=yes", "OGR_SQLITE_SYNCHRONOUS=OFF", "INIT_WITH_EPSG=no", nullptr };
- const char* options[] = { nullptr };
- auto data_source = std::unique_ptr<OGRDataSource, OGRDataSourceDestroyer>(driver->CreateDataSource(filename.c_str(), const_cast<char**>(options)));
- if (!data_source) {
- std::cerr << "Creation of output file failed.\n";
- exit(return_code_fatal);
- }
-
- SRS srs;
- auto layer = data_source->CreateLayer("changes", srs.out(), wkbLineString, const_cast<char**>(options));
- if (!layer) {
- std::cerr << "Creating layer 'changes' failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_change("change", OFTInteger);
- field_change.SetWidth(1);
- if (layer->CreateField(&field_change) != OGRERR_NONE ) {
- std::cerr << "Creating field 'change' on 'changes' layer failed.\n";
- exit(return_code_fatal);
- }
-
- layer->StartTransaction();
+ gdalcpp::Layer layer{dataset, "changes", wkbLineString};
+ layer.add_field("change", OFTInteger, 1);
+ layer.start_transaction();
for (const auto& segment : removed_segments) {
add_segment(layer, 0, segment);
@@ -132,7 +98,7 @@ void output_ogr(const std::string& filename, const std::string& driver_name, con
add_segment(layer, 1, segment);
}
- layer->CommitTransaction();
+ layer.commit_transaction();
}
int main(int argc, char *argv[]) {
@@ -145,11 +111,12 @@ int main(int argc, char *argv[]) {
{"format", required_argument, 0, 'f'},
{"geom", required_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
+ {"version", no_argument, 0, 'V'},
{0, 0, 0, 0}
};
while (1) {
- int c = getopt_long(argc, argv, "df:g:h", long_options, 0);
+ int c = getopt_long(argc, argv, "df:g:hV", long_options, 0);
if (c == -1)
break;
@@ -168,6 +135,13 @@ int main(int argc, char *argv[]) {
print_help();
exit(return_code_ok);
}
+ case 'V':
+ std::cout << "osmcoastline_segments version " OSMCOASTLINE_VERSION "\n"
+ << "Copyright (C) 2012-2016 Jochen Topf <jochen at topf.org>\n"
+ << "License: GNU GENERAL PUBLIC LICENSE Version 3 <http://gnu.org/licenses/gpl.html>.\n"
+ << "This is free software: you are free to change and redistribute it.\n"
+ << "There is NO WARRANTY, to the extent permitted by law.\n";
+ exit(return_code_ok);
default:
break;
}
@@ -185,8 +159,8 @@ int main(int argc, char *argv[]) {
InputFile file1(argv[optind]);
InputFile file2(argv[optind+1]);
- osmium::util::TypedMemoryMapping<osmium::UndirectedSegment> m1(file1.size() / sizeof(osmium::UndirectedSegment), false, file1.fd());
- osmium::util::TypedMemoryMapping<osmium::UndirectedSegment> m2(file2.size() / sizeof(osmium::UndirectedSegment), false, file2.fd());
+ osmium::util::TypedMemoryMapping<osmium::UndirectedSegment> m1(file1.size() / sizeof(osmium::UndirectedSegment), osmium::util::MemoryMapping::mapping_mode::readonly, file1.fd());
+ osmium::util::TypedMemoryMapping<osmium::UndirectedSegment> m2(file2.size() / sizeof(osmium::UndirectedSegment), osmium::util::MemoryMapping::mapping_mode::readonly, file2.fd());
std::set_difference(m1.cbegin(), m1.cend(), m2.cbegin(), m2.cend(), std::back_inserter(removed_segments));
std::set_difference(m2.cbegin(), m2.cend(), m1.cbegin(), m1.cend(), std::back_inserter(added_segments));
diff --git a/src/osmcoastline_ways.cpp b/src/osmcoastline_ways.cpp
index 6dcfe89..cd38493 100644
--- a/src/osmcoastline_ways.cpp
+++ b/src/osmcoastline_ways.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -19,8 +19,9 @@
*/
+#include <cstring>
#include <iostream>
-#include <set>
+#include <memory>
#include <string>
#include <osmium/geom/haversine.hpp>
@@ -30,8 +31,9 @@
#include <osmium/io/any_input.hpp>
#include <osmium/visitor.hpp>
-#include "ogr_include.hpp"
-#include "osmcoastline.hpp"
+#include <gdalcpp.hpp>
+
+#include "return_codes.hpp"
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_type;
typedef osmium::handler::NodeLocationsForWays<index_type, index_type> node_location_handler_type;
@@ -40,94 +42,41 @@ class CoastlineWaysHandler : public osmium::handler::Handler {
double m_length;
- std::unique_ptr<OGRDataSource, OGRDataSourceDestroyer> m_data_source;
- OGRLayer* m_layer_ways;
+ gdalcpp::Dataset m_dataset;
+ gdalcpp::Layer m_layer_ways;
osmium::geom::OGRFactory<> m_factory;
public:
CoastlineWaysHandler(const std::string& db_filename) :
- m_length(0.0) {
- OGRRegisterAll();
-
- const char* driver_name = "SQLite";
- OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name);
- if (!driver) {
- std::cerr << driver_name << " driver not available.\n";
- exit(return_code_fatal);
- }
-
- CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "FALSE");
- const char* options[] = { "SPATIALITE=TRUE", nullptr };
- m_data_source.reset(driver->CreateDataSource(db_filename.c_str(), const_cast<char**>(options)));
- if (!m_data_source) {
- std::cerr << "Creation of output file failed.\n";
- exit(return_code_fatal);
- }
-
- OGRSpatialReference sparef;
- sparef.SetWellKnownGeogCS("WGS84");
- m_layer_ways = m_data_source->CreateLayer("ways", &sparef, wkbLineString, nullptr);
- if (!m_layer_ways) {
- std::cerr << "Layer creation failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_way_id("way_id", OFTString);
- field_way_id.SetWidth(10);
- if (m_layer_ways->CreateField(&field_way_id) != OGRERR_NONE ) {
- std::cerr << "Creating field 'way_id' on 'ways' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_name("name", OFTString);
- field_name.SetWidth(100);
- if (m_layer_ways->CreateField(&field_name) != OGRERR_NONE ) {
- std::cerr << "Creating field 'name' on 'ways' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_source("source", OFTString);
- field_source.SetWidth(255);
- if (m_layer_ways->CreateField(&field_source) != OGRERR_NONE ) {
- std::cerr << "Creating field 'source' on 'ways' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_bogus("bogus", OFTString);
- field_bogus.SetWidth(1);
- if (m_layer_ways->CreateField(&field_bogus) != OGRERR_NONE ) {
- std::cerr << "Creating field 'bogus' on 'ways' layer failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer_ways->StartTransaction();
+ m_length(0.0),
+ m_dataset("SQLite", db_filename, gdalcpp::SRS{}, {"SPATIALITE=TRUE", "OGR_SQLITE_SYNCHRONOUS=OFF", "INIT_WITH_EPSG=no" }),
+ m_layer_ways(m_dataset, "ways", wkbLineString) {
+
+ m_layer_ways.add_field("way_id", OFTString, 10);
+ m_layer_ways.add_field("name", OFTString, 100);
+ m_layer_ways.add_field("source", OFTString, 255);
+ m_layer_ways.add_field("bogus", OFTString, 1);
+ m_layer_ways.start_transaction();
}
~CoastlineWaysHandler() {
- m_layer_ways->CommitTransaction();
+ m_layer_ways.commit_transaction();
}
void way(osmium::Way& way) {
m_length += osmium::geom::haversine::distance(way.nodes());
try {
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer_ways->GetLayerDefn());
std::unique_ptr<OGRLineString> ogrlinestring = m_factory.create_linestring(way);
- feature->SetGeometry(ogrlinestring.get());
- feature->SetField("way_id", std::to_string(way.id()).c_str());
- feature->SetField("name", way.tags().get_value_by_key("name"));
- feature->SetField("source", way.tags().get_value_by_key("source"));
+ gdalcpp::Feature feature(m_layer_ways, std::move(ogrlinestring));
+ feature.set_field("way_id", std::to_string(way.id()).c_str());
+ feature.set_field("name", way.tags().get_value_by_key("name"));
+ feature.set_field("source", way.tags().get_value_by_key("source"));
const char* coastline = way.tags().get_value_by_key("coastline");
- feature->SetField("bogus", (coastline && !strcmp(coastline, "bogus")) ? "t" : "f");
-
- if (m_layer_ways->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature.\n";
- exit(1);
- }
-
- OGRFeature::DestroyFeature(feature);
+ feature.set_field("bogus", (coastline && !std::strcmp(coastline, "bogus")) ? "t" : "f");
+ feature.add_to_layer();
} catch (osmium::geometry_error&) {
std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n";
}
@@ -140,6 +89,22 @@ public:
};
int main(int argc, char* argv[]) {
+ if (argc >= 2) {
+ if (!std::strcmp(argv[1], "--help") || !std::strcmp(argv[1], "-h")) {
+ std::cout << "Usage: osmcoastline_ways OSMFILE [WAYSDB]\n";
+ exit(return_code_ok);
+ }
+
+ if (!std::strcmp(argv[1], "--version") || !std::strcmp(argv[1], "-V")) {
+ std::cout << "osmcoastline_ways version " OSMCOASTLINE_VERSION "\n"
+ << "Copyright (C) 2012-2016 Jochen Topf <jochen at topf.org>\n"
+ << "License: GNU GENERAL PUBLIC LICENSE Version 3 <http://gnu.org/licenses/gpl.html>.\n"
+ << "This is free software: you are free to change and redistribute it.\n"
+ << "There is NO WARRANTY, to the extent permitted by law.\n";
+ exit(return_code_ok);
+ }
+ }
+
if (argc != 2 && argc != 3) {
std::cerr << "Usage: osmcoastline_ways OSMFILE [WAYSDB]\n";
exit(return_code_cmdline);
diff --git a/src/output_database.cpp b/src/output_database.cpp
index 87116d3..b1b385a 100644
--- a/src/output_database.cpp
+++ b/src/output_database.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -22,54 +22,49 @@
#include <iostream>
#include <sstream>
-#include "ogr_include.hpp"
-#include "osmcoastline.hpp"
-#include "output_database.hpp"
-#include "output_layers.hpp"
+#include <gdal_version.h>
+#include <geos_c.h>
+
#include "options.hpp"
+#include "output_database.hpp"
+#include "srs.hpp"
#include "stats.hpp"
-const char* OutputDatabase::options_with_index[] = { nullptr };
-const char* OutputDatabase::options_without_index[] = { "SPATIAL_INDEX=no", nullptr };
-
-OutputDatabase::~OutputDatabase() {
- OGRCleanupAll();
-}
-
-OutputDatabase::OutputDatabase(const std::string& outdb, bool with_index) :
+OutputDatabase::OutputDatabase(const std::string& outdb, SRS& srs, bool with_index) :
m_with_index(with_index),
- m_data_source(),
- m_layer_error_points(),
- m_layer_error_lines(),
- m_layer_rings(),
- m_layer_land_polygons(),
- m_layer_water_polygons(),
- m_layer_lines() {
- OGRRegisterAll();
-
- const char* driver_name = "SQLite";
- OGRSFDriver* driver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name);
- if (!driver) {
- std::cerr << driver_name << " driver not available.\n";
- exit(return_code_fatal);
- }
-
- const char* options[] = { "SPATIALITE=yes", "OGR_SQLITE_SYNCHRONOUS=OFF", "INIT_WITH_EPSG=no", nullptr };
- m_data_source.reset(driver->CreateDataSource(outdb.c_str(), const_cast<char**>(options)));
- if (!m_data_source) {
- std::cerr << "Creation of output file failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer_error_points.reset(new LayerErrorPoints(m_data_source.get(), layer_options()));
- m_layer_error_lines.reset(new LayerErrorLines(m_data_source.get(), layer_options()));
- m_layer_rings.reset(new LayerRings(m_data_source.get(), layer_options()));
- m_layer_land_polygons.reset(new LayerPolygons(m_data_source.get(), layer_options(), "land_polygons"));
- m_layer_water_polygons.reset(new LayerPolygons(m_data_source.get(), layer_options(), "water_polygons"));
- m_layer_lines.reset(new LayerLines(m_data_source.get(), layer_options()));
-
- exec("CREATE TABLE options (overlap REAL, close_distance REAL, max_points_in_polygons INTEGER, split_large_polygons INTEGER)");
- exec("CREATE TABLE meta ("
+ m_srs(srs),
+ m_dataset("SQLite", outdb, gdalcpp::SRS(*srs.out()), { "SPATIALITE=TRUE", "OGR_SQLITE_SYNCHRONOUS=OFF", "INIT_WITH_EPSG=no" }),
+ m_layer_error_points(m_dataset, "error_points", wkbPoint, layer_options()),
+ m_layer_error_lines(m_dataset, "error_lines", wkbLineString, layer_options()),
+ m_layer_rings(m_dataset, "rings", wkbPolygon, layer_options()),
+ m_layer_land_polygons(m_dataset, "land_polygons", wkbPolygon, layer_options()),
+ m_layer_water_polygons(m_dataset, "water_polygons", wkbPolygon, layer_options()),
+ m_layer_lines(m_dataset, "lines", wkbLineString, layer_options()) {
+
+ m_layer_error_points.add_field("osm_id", OFTString, 10);
+ m_layer_error_points.add_field("error", OFTString, 16);
+ m_layer_error_points.start_transaction();
+
+ m_layer_error_lines.add_field("osm_id", OFTString, 10);
+ m_layer_error_lines.add_field("error", OFTString, 16);
+ m_layer_error_lines.start_transaction();
+
+ m_layer_rings.add_field("osm_id", OFTString, 10);
+ m_layer_rings.add_field("nways", OFTInteger, 6);
+ m_layer_rings.add_field("npoints", OFTInteger, 8);
+ m_layer_rings.add_field("fixed", OFTInteger, 1);
+ m_layer_rings.add_field("land", OFTInteger, 1);
+ m_layer_rings.add_field("valid", OFTInteger, 1);
+ m_layer_rings.start_transaction();
+
+ m_layer_land_polygons.start_transaction();
+
+ m_layer_water_polygons.start_transaction();
+
+ m_layer_lines.start_transaction();
+
+ m_dataset.exec("CREATE TABLE options (overlap REAL, close_distance REAL, max_points_in_polygons INTEGER, split_large_polygons INTEGER)");
+ m_dataset.exec("CREATE TABLE meta ("
"timestamp TEXT, "
"runtime INTEGER, "
"memory_usage INTEGER, "
@@ -99,7 +94,7 @@ void OutputDatabase::set_options(const Options& options) {
<< (options.split_large_polygons ? 1 : 0)
<< ")";
- exec(sql.str().c_str());
+ m_dataset.exec(sql.str());
}
void OutputDatabase::set_meta(int runtime, int memory_usage, const Stats& stats) {
@@ -120,59 +115,124 @@ void OutputDatabase::set_meta(int runtime, int memory_usage, const Stats& stats)
<< stats.land_polygons_after_split
<< ")";
- exec(sql.str().c_str());
+ m_dataset.exec(sql.str());
}
void OutputDatabase::commit() {
- m_layer_lines->commit();
- m_layer_water_polygons->commit();
- m_layer_land_polygons->commit();
- m_layer_rings->commit();
- m_layer_error_lines->commit();
- m_layer_error_points->commit();
-}
-
-void OutputDatabase::add_error_point(std::unique_ptr<OGRPoint> point, const char* error, osmium::object_id_type id) {
- m_layer_error_points->add(point.release(), error, id);
-}
-
-void OutputDatabase::add_error_point(OGRPoint* point, const char* error, osmium::object_id_type id) {
- m_layer_error_points->add(point, error, id);
-}
-
-void OutputDatabase::add_error_line(std::unique_ptr<OGRLineString> linestring, const char* error, osmium::object_id_type id) {
- m_layer_error_lines->add(linestring.release(), error, id);
-}
-
-void OutputDatabase::add_error_line(OGRLineString* linestring, const char* error, osmium::object_id_type id) {
- m_layer_error_lines->add(linestring, error, id);
-}
-
-void OutputDatabase::add_ring(std::unique_ptr<OGRPolygon> polygon, int id, int nways, int npoints, bool fixed) {
- layer_rings()->add(polygon.release(), id, nways, npoints, fixed, layer_error_points());
-}
-
-void OutputDatabase::add_ring(OGRPolygon* polygon, int id, int nways, int npoints, bool fixed) {
- layer_rings()->add(polygon, id, nways, npoints, fixed, layer_error_points());
-}
+ m_layer_lines.commit_transaction();
+ m_layer_water_polygons.commit_transaction();
+ m_layer_land_polygons.commit_transaction();
+ m_layer_rings.commit_transaction();
+ m_layer_error_lines.commit_transaction();
+ m_layer_error_points.commit_transaction();
+}
+
+void OutputDatabase::add_error_point(std::unique_ptr<OGRPoint>&& point, const char* error, osmium::object_id_type id) {
+ m_srs.transform(point.get());
+ gdalcpp::Feature feature(m_layer_error_points, std::move(point));
+ feature.set_field("osm_id", std::to_string(id).c_str());
+ feature.set_field("error", error);
+ feature.add_to_layer();
+}
+
+void OutputDatabase::add_error_line(std::unique_ptr<OGRLineString>&& linestring, const char* error, osmium::object_id_type id) {
+ m_srs.transform(linestring.get());
+ gdalcpp::Feature feature(m_layer_error_lines, std::move(linestring));
+ feature.set_field("osm_id", std::to_string(id).c_str());
+ feature.set_field("error", error);
+ feature.add_to_layer();
+}
+
+void OutputDatabase::add_ring(std::unique_ptr<OGRPolygon>&& polygon, int osm_id, int nways, int npoints, bool fixed) {
+ m_srs.transform(polygon.get());
+
+ bool land = polygon->getExteriorRing()->isClockwise();
+ bool valid = polygon->IsValid();
+
+ if (!valid) {
+ /*
+ When the polygon is invalid we find out what and where the problem is.
+ This code is a bit strange because older versions of the GEOS library
+ only export this information as a string. We parse the reason and
+ point coordinates (of a self-intersection-point for instance) from
+ this string and create a point in the error layer for it.
+
+ The exportToGEOS() method on OGR geometries is not documented. Let's
+ hope that it will always be available. We use the GEOSisValidReason()
+ function from the GEOS C interface to get to the reason.
+ */
+
+#if GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR <= 10
+ GEOSGeom p { polygon->exportToGEOS() };
+ char* r = GEOSisValidReason(p);
+ std::string reason = r ? r : "";
+ GEOSFree(r);
+ GEOSGeom_destroy(p);
+#else
+ GEOSContextHandle_t contextHandle = OGRGeometry::createGEOSContext();
+ auto r = GEOSisValidReason(polygon->exportToGEOS(contextHandle));
+ std::string reason = r ? r : "";
+ OGRGeometry::freeGEOSContext(contextHandle);
+#endif
+
+ if (!reason.empty()) {
+ size_t left_bracket = reason.find('[');
+ size_t right_bracket = reason.find(']');
+
+ std::istringstream iss(reason.substr(left_bracket+1, right_bracket-left_bracket-1), std::istringstream::in);
+ double x;
+ double y;
+ iss >> x;
+ iss >> y;
+ reason = reason.substr(0, left_bracket);
+
+ std::unique_ptr<OGRPoint> point { new OGRPoint() };
+ point->assignSpatialReference(polygon->getSpatialReference());
+ point->setX(x);
+ point->setY(y);
+
+ if (reason == "Self-intersection") {
+ reason = "self_intersection";
+ }
+ add_error_point(std::move(point), reason.c_str(), osm_id);
+ } else {
+ std::cerr << "Did not get reason from GEOS why polygon " << osm_id << " is invalid. Could not write info to error points layer\n";
+ }
+ }
-void OutputDatabase::add_land_polygon(OGRPolygon* polygon) {
- layer_land_polygons()->add(polygon);
+ gdalcpp::Feature feature(m_layer_rings, std::move(polygon));
+ feature.set_field("osm_id", osm_id);
+ feature.set_field("nways", nways);
+ feature.set_field("npoints", npoints);
+ feature.set_field("fixed", fixed);
+ feature.set_field("land", land);
+ feature.set_field("valid", valid);
+ feature.add_to_layer();
}
-void OutputDatabase::add_water_polygon(OGRPolygon* polygon) {
- layer_water_polygons()->add(polygon);
+void OutputDatabase::add_land_polygon(std::unique_ptr<OGRPolygon>&& polygon) {
+ m_srs.transform(polygon.get());
+ gdalcpp::Feature feature(m_layer_land_polygons, std::move(polygon));
+ feature.add_to_layer();
}
-void OutputDatabase::add_line(std::unique_ptr<OGRLineString> linestring) {
- layer_lines()->add(linestring.release());
+void OutputDatabase::add_water_polygon(std::unique_ptr<OGRPolygon>&& polygon) {
+ m_srs.transform(polygon.get());
+ gdalcpp::Feature feature(m_layer_water_polygons, std::move(polygon));
+ feature.add_to_layer();
}
-const char** OutputDatabase::layer_options() const {
- return m_with_index ? options_with_index : options_without_index;
+void OutputDatabase::add_line(std::unique_ptr<OGRLineString>&& linestring) {
+ m_srs.transform(linestring.get());
+ gdalcpp::Feature feature(m_layer_lines, std::move(linestring));
+ feature.add_to_layer();
}
-void OutputDatabase::exec(const char* sql) {
- m_data_source->ReleaseResultSet(m_data_source->ExecuteSQL(sql, nullptr, nullptr));
+std::vector<std::string> OutputDatabase::layer_options() const {
+ std::vector<std::string> options;
+ if (!m_with_index) {
+ options.emplace_back("SPATIAL_INDEX=no");
+ }
+ return options;
}
diff --git a/src/output_database.hpp b/src/output_database.hpp
index 2c19dbb..4dac320 100644
--- a/src/output_database.hpp
+++ b/src/output_database.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
@@ -24,18 +24,13 @@
#include <memory>
#include <string>
+#include <vector>
#include <osmium/osm/types.hpp>
-#include <ogr_spatialref.h>
-#include "ogr_include.hpp"
-
-class LayerErrorPoints;
-class LayerErrorLines;
-class LayerRings;
-class LayerPolygons;
-class LayerLines;
+#include <gdalcpp.hpp>
+class SRS;
class Options;
struct Stats;
@@ -46,54 +41,50 @@ struct Stats;
*/
class OutputDatabase {
- static const char* options_without_index[];
- static const char* options_with_index[];
-
bool m_with_index;
- std::unique_ptr<OGRDataSource, OGRDataSourceDestroyer> m_data_source;
+ SRS& m_srs;
+
+ gdalcpp::Dataset m_dataset;
+
+ // Any errors in a linestring
+ gdalcpp::Layer m_layer_error_points;
+
+ // Any errors in a point
+ gdalcpp::Layer m_layer_error_lines;
- std::unique_ptr<LayerErrorPoints> m_layer_error_points;
- std::unique_ptr<LayerErrorLines> m_layer_error_lines;
- std::unique_ptr<LayerRings> m_layer_rings;
- std::unique_ptr<LayerPolygons> m_layer_land_polygons;
- std::unique_ptr<LayerPolygons> m_layer_water_polygons;
- std::unique_ptr<LayerLines> m_layer_lines;
+ // Layer for polygon rings.
+ // Will contain polygons without holes, ie. with just an outer ring.
+ // Polygon outer rings will be oriented according to usual GIS custom with
+ // points going clockwise around the ring, ie "land" is on the right hand
+ // side of the border. This is the other way around from how it looks in
+ // OSM.
+ gdalcpp::Layer m_layer_rings;
- const char** layer_options() const;
+ // Completed land polygons.
+ gdalcpp::Layer m_layer_land_polygons;
- /// Execute arbitrary SQL command on database
- void exec(const char* sql);
+ // Completed water polygons.
+ gdalcpp::Layer m_layer_water_polygons;
+
+ // Coastlines generated from completed polygons.
+ // Lines contain at most max-points points.
+ gdalcpp::Layer m_layer_lines;
+
+ std::vector<std::string> layer_options() const;
public:
- OutputDatabase(const std::string& outdb, bool with_index=false);
-
- ~OutputDatabase();
-
- void create_layer_error_points();
- void create_layer_error_lines();
- void create_layer_rings();
- void create_layer_land_polygons();
- void create_layer_water_polygons();
- void create_layer_lines();
-
- LayerErrorPoints* layer_error_points() const { return m_layer_error_points.get(); }
- LayerErrorLines* layer_error_lines() const { return m_layer_error_lines.get(); }
- LayerRings* layer_rings() const { return m_layer_rings.get(); }
- LayerPolygons* layer_land_polygons() const { return m_layer_land_polygons.get(); }
- LayerPolygons* layer_water_polygons() const { return m_layer_water_polygons.get(); }
- LayerLines* layer_lines() const { return m_layer_lines.get(); }
-
- void add_error_point(std::unique_ptr<OGRPoint> point, const char* error, osmium::object_id_type id=0);
- void add_error_point(OGRPoint* point, const char* error, osmium::object_id_type id=0);
- void add_error_line(std::unique_ptr<OGRLineString> linestring, const char* error, osmium::object_id_type id=0);
- void add_error_line(OGRLineString* linestring, const char* error, osmium::object_id_type id=0);
- void add_ring(std::unique_ptr<OGRPolygon> polygon, int id, int nways, int npoints, bool fixed);
- void add_ring(OGRPolygon* polygon, int id, int nways, int npoints, bool fixed);
- void add_land_polygon(OGRPolygon* polygon);
- void add_water_polygon(OGRPolygon* polygon);
- void add_line(std::unique_ptr<OGRLineString> linestring);
+ OutputDatabase(const std::string& outdb, SRS& srs, bool with_index=false);
+
+ ~OutputDatabase() noexcept = default;
+
+ void add_error_point(std::unique_ptr<OGRPoint>&& point, const char* error, osmium::object_id_type id=0);
+ void add_error_line(std::unique_ptr<OGRLineString>&& linestring, const char* error, osmium::object_id_type id=0);
+ void add_ring(std::unique_ptr<OGRPolygon>&& polygon, int osm_id, int nways, int npoints, bool fixed);
+ void add_land_polygon(std::unique_ptr<OGRPolygon>&& polygon);
+ void add_water_polygon(std::unique_ptr<OGRPolygon>&& polygon);
+ void add_line(std::unique_ptr<OGRLineString>&& linestring);
void set_options(const Options& options);
void set_meta(int runtime, int memory_usage, const Stats& stats);
diff --git a/src/output_layers.cpp b/src/output_layers.cpp
deleted file mode 100644
index 969eea2..0000000
--- a/src/output_layers.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
-
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
-
- This file is part of OSMCoastline.
-
- OSMCoastline 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 3 of the License, or
- (at your option) any later version.
-
- OSMCoastline 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 OSMCoastline. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <cassert>
-#include <iostream>
-#include <sstream>
-#include <stdexcept>
-#include <string>
-
-#include <gdal_version.h>
-#include <geos_c.h>
-
-#include <osmium/osm/types.hpp>
-
-#include "ogr_include.hpp"
-#include "osmcoastline.hpp"
-#include "output_layers.hpp"
-#include "srs.hpp"
-
-extern SRS srs;
-
-/***************************************************************/
-
-void Layer::commit() {
- if (m_layer->CommitTransaction() != OGRERR_NONE) {
- throw std::runtime_error("Layer commit failed");
- }
-}
-
-/***************************************************************/
-
-LayerErrorPoints::LayerErrorPoints(OGRDataSource* data_source, const char** options) :
- Layer() {
- m_layer = data_source->CreateLayer("error_points", srs.out(), wkbPoint, const_cast<char**>(options));
- if (!m_layer) {
- std::cerr << "Creating layer 'error_points' failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_osm_id("osm_id", OFTString);
- field_osm_id.SetWidth(10);
- if (m_layer->CreateField(&field_osm_id) != OGRERR_NONE ) {
- std::cerr << "Creating field 'osm_id' on 'error_points' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_error("error", OFTString);
- field_error.SetWidth(16);
- if (m_layer->CreateField(&field_error) != OGRERR_NONE ) {
- std::cerr << "Creating field 'error' on 'error_points' layer failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer->StartTransaction();
-}
-
-void LayerErrorPoints::add(OGRPoint* point, const char* error, osmium::object_id_type osm_id) {
- srs.transform(point);
-
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
-
- feature->SetGeometryDirectly(point);
- feature->SetField("osm_id", std::to_string(osm_id).c_str());
- feature->SetField("error", error);
-
- if (m_layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature on layer 'error_points'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
-}
-
-/***************************************************************/
-
-LayerErrorLines::LayerErrorLines(OGRDataSource* data_source, const char** options) :
- Layer() {
- m_layer = data_source->CreateLayer("error_lines", srs.out(), wkbLineString, const_cast<char**>(options));
- if (!m_layer) {
- std::cerr << "Creating layer 'error_lines' failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_osm_id("osm_id", OFTString);
- field_osm_id.SetWidth(10);
- if (m_layer->CreateField(&field_osm_id) != OGRERR_NONE ) {
- std::cerr << "Creating field 'osm_id' on 'error_lines' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_error("error", OFTString);
- field_error.SetWidth(16);
- if (m_layer->CreateField(&field_error) != OGRERR_NONE ) {
- std::cerr << "Creating field 'error' on 'error_lines' layer failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer->StartTransaction();
-}
-
-void LayerErrorLines::add(OGRLineString* linestring, const char* error, osmium::object_id_type osm_id) {
- srs.transform(linestring);
-
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
-
- feature->SetGeometryDirectly(linestring);
- feature->SetField("osm_id", std::to_string(osm_id).c_str());
- feature->SetField("error", error);
-
- if (m_layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature on layer 'error_lines'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
-}
-
-/***************************************************************/
-
-LayerRings::LayerRings(OGRDataSource* data_source, const char** options) :
- Layer() {
- m_layer = data_source->CreateLayer("rings", srs.out(), wkbPolygon, const_cast<char**>(options));
- if (!m_layer) {
- std::cerr << "Creating layer 'rings' failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_osm_id("osm_id", OFTString);
- field_osm_id.SetWidth(10);
- if (m_layer->CreateField(&field_osm_id) != OGRERR_NONE ) {
- std::cerr << "Creating field 'osm_id' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_nways("nways", OFTInteger);
- field_nways.SetWidth(6);
- if (m_layer->CreateField(&field_nways) != OGRERR_NONE ) {
- std::cerr << "Creating field 'nways' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_npoints("npoints", OFTInteger);
- field_npoints.SetWidth(8);
- if (m_layer->CreateField(&field_npoints) != OGRERR_NONE ) {
- std::cerr << "Creating field 'npoints' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_fixed("fixed", OFTInteger);
- field_fixed.SetWidth(1);
- if (m_layer->CreateField(&field_fixed) != OGRERR_NONE ) {
- std::cerr << "Creating field 'fixed' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_land("land", OFTInteger);
- field_land.SetWidth(1);
- if (m_layer->CreateField(&field_land) != OGRERR_NONE ) {
- std::cerr << "Creating field 'land' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- OGRFieldDefn field_valid("valid", OFTInteger);
- field_valid.SetWidth(1);
- if (m_layer->CreateField(&field_valid) != OGRERR_NONE ) {
- std::cerr << "Creating field 'valid' on 'rings' layer failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer->StartTransaction();
-}
-
-void LayerRings::add(OGRPolygon* polygon, int osm_id, int nways, int npoints, bool fixed, LayerErrorPoints* layer_error_points) {
- srs.transform(polygon);
-
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
-
- feature->SetGeometryDirectly(polygon);
- feature->SetField("osm_id", osm_id);
- feature->SetField("nways", nways);
- feature->SetField("npoints", npoints);
- feature->SetField("fixed", fixed ? 0 : 1);
-
- if (polygon->getExteriorRing()->isClockwise()) {
- feature->SetField("land", 1);
- } else {
- feature->SetField("land", 0);
- }
-
- if (polygon->IsValid()) {
- feature->SetField("valid", 1);
- } else {
- /*
- When the polygon is invalid we find out what and where the problem is.
- This code is a bit strange because older versions of the GEOS library
- only export this information as a string. We parse the reason and
- point coordinates (of a self-intersection-point for instance) from
- this string and create a point in the error layer for it.
-
- The exportToGEOS() method on OGR geometries is not documented. Let's
- hope that it will always be available. We use the GEOSisValidReason()
- function from the GEOS C interface to get to the reason.
- */
-
-#if GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR <= 10
- GEOSGeom p { polygon->exportToGEOS() };
- char* r = GEOSisValidReason(p);
- std::string reason = r;
- GEOSFree(r);
- GEOSGeom_destroy(p);
-#else
- GEOSContextHandle_t contextHandle = OGRGeometry::createGEOSContext();
- std::string reason = GEOSisValidReason(polygon->exportToGEOS(contextHandle));
- OGRGeometry::freeGEOSContext(contextHandle);
-#endif
- size_t left_bracket = reason.find('[');
- size_t right_bracket = reason.find(']');
-
- std::istringstream iss(reason.substr(left_bracket+1, right_bracket-left_bracket-1), std::istringstream::in);
- double x;
- double y;
- iss >> x;
- iss >> y;
- reason = reason.substr(0, left_bracket);
-
- std::unique_ptr<OGRPoint> point { new OGRPoint() };
- point->assignSpatialReference(polygon->getSpatialReference());
- point->setX(x);
- point->setY(y);
-
- if (reason == "Self-intersection") {
- reason = "self_intersection";
- }
- layer_error_points->add(point.release(), reason.c_str(), osm_id);
-
- feature->SetField("valid", 0);
- }
-
- if (m_layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature in layer 'rings'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
-}
-
-/***************************************************************/
-
-LayerPolygons::LayerPolygons(OGRDataSource* data_source, const char** options, const char* name) :
- Layer(),
- m_name(name) {
- m_layer = data_source->CreateLayer(name, srs.out(), wkbPolygon, const_cast<char**>(options));
- if (!m_layer) {
- std::cerr << "Creating layer '" << name << "' failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer->StartTransaction();
-}
-
-void LayerPolygons::add(OGRPolygon* polygon) {
- srs.transform(polygon);
-
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
-
- feature->SetGeometryDirectly(polygon);
-
- if (m_layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature in layer '" << m_name << "'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
-}
-
-/***************************************************************/
-
-LayerLines::LayerLines(OGRDataSource* data_source, const char** options) :
- Layer() {
- m_layer = data_source->CreateLayer("lines", srs.out(), wkbLineString, const_cast<char**>(options));
- if (!m_layer) {
- std::cerr << "Creating layer 'lines' failed.\n";
- exit(return_code_fatal);
- }
-
- m_layer->StartTransaction();
-}
-
-void LayerLines::add(OGRLineString* linestring) {
- srs.transform(linestring);
-
- OGRFeature* feature = OGRFeature::CreateFeature(m_layer->GetLayerDefn());
-
- feature->SetGeometryDirectly(linestring);
-
- if (m_layer->CreateFeature(feature) != OGRERR_NONE) {
- std::cerr << "Failed to create feature in layer 'lines'.\n";
- exit(return_code_fatal);
- }
-
- OGRFeature::DestroyFeature(feature);
-}
-
diff --git a/src/output_layers.hpp b/src/output_layers.hpp
deleted file mode 100644
index 9c5b314..0000000
--- a/src/output_layers.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef OUTPUT_LAYER_HPP
-#define OUTPUT_LAYER_HPP
-
-/*
-
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
-
- This file is part of OSMCoastline.
-
- OSMCoastline 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 3 of the License, or
- (at your option) any later version.
-
- OSMCoastline 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 OSMCoastline. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <osmium/osm/types.hpp>
-
-#include "srs.hpp"
-
-extern SRS srs;
-
-class OGRLayer;
-class OGRDataSource;
-class OGRPoint;
-class OGRLineString;
-class OGRPolygon;
-
-/**
- * Parent class for all output layers.
- */
-class Layer {
-
-protected:
-
- /// OGRLayer implementing this output layer.
- OGRLayer* m_layer;
-
- Layer() : m_layer(nullptr) {}
-
-public:
-
- /// Commit transaction on this layer.
- void commit();
-
-};
-
-/**
- * Layer for any errors in one point.
- */
-class LayerErrorPoints : public Layer {
-
-public:
-
- LayerErrorPoints(OGRDataSource* data_source, const char** options);
- void add(OGRPoint* point, const char* error, osmium::object_id_type id);
-
-};
-
-/**
- * Layer for any errors in a linestring.
- */
-class LayerErrorLines : public Layer {
-
-public:
-
- LayerErrorLines(OGRDataSource* data_source, const char** options);
- void add(OGRLineString* linestring, const char* error, osmium::object_id_type id);
-
-};
-
-/**
- * Layer for polygon rings.
- * Will contain polygons without holes, ie. with just an outer ring.
- * Polygon outer rings will be oriented according to usual GIS custom with
- * points going clockwise around the ring, ie "land" is on the right hand side of
- * the border. This is the other way around from how it looks in OSM.
- */
-class LayerRings : public Layer {
-
-public:
-
- LayerRings(OGRDataSource* data_source, const char** options);
- void add(OGRPolygon* polygon, int id, int nways, int npoints, bool fixed, LayerErrorPoints* layer_error_points);
-
-};
-
-/**
- * Layer for completed polygons.
- * Polygons can contain inner rings for large water areas such as the Caspian Sea.
- */
-class LayerPolygons : public Layer {
-
- const char* m_name;
-
-public:
-
- LayerPolygons(OGRDataSource* data_source, const char** options, const char* name);
- void add(OGRPolygon* polygon);
-
-};
-
-/**
- * Layer for coastlines generated from completed polygons.
- * Lines containt at most max-points points.
- */
-class LayerLines : public Layer {
-
-public:
-
- LayerLines(OGRDataSource* data_source, const char** options);
- void add(OGRLineString* lines);
-
-};
-
-#endif // OUTPUT_LAYER_HPP
diff --git a/src/osmcoastline.hpp b/src/return_codes.hpp
similarity index 94%
rename from src/osmcoastline.hpp
rename to src/return_codes.hpp
index 27abac2..6ae4cb1 100644
--- a/src/osmcoastline.hpp
+++ b/src/return_codes.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/srs.cpp b/src/srs.cpp
index 11d5d39..78a5809 100644
--- a/src/srs.cpp
+++ b/src/srs.cpp
@@ -1,6 +1,6 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/srs.hpp b/src/srs.hpp
index ff4e530..5ce32b7 100644
--- a/src/srs.hpp
+++ b/src/srs.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/stats.hpp b/src/stats.hpp
index 052c9d6..9284a59 100644
--- a/src/stats.hpp
+++ b/src/stats.hpp
@@ -3,7 +3,7 @@
/*
- Copyright 2012-2015 Jochen Topf <jochen at topf.org>.
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
This file is part of OSMCoastline.
diff --git a/src/util.hpp b/src/util.hpp
new file mode 100644
index 0000000..c16b658
--- /dev/null
+++ b/src/util.hpp
@@ -0,0 +1,41 @@
+#ifndef UTIL_HPP
+#define UTIL_HPP
+
+/*
+
+ Copyright 2012-2016 Jochen Topf <jochen at topf.org>.
+
+ This file is part of OSMCoastline.
+
+ OSMCoastline 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 3 of the License, or
+ (at your option) any later version.
+
+ OSMCoastline 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 OSMCoastline. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <memory>
+#include <type_traits>
+
+template <typename R, typename T>
+std::unique_ptr<R> make_unique_ptr_clone(const T* source) {
+ static_assert(std::is_convertible<T*, R*>::value, "T* must be convertible to R*");
+ return std::unique_ptr<R>(static_cast<R*>(source->clone()));
+}
+
+template <typename TDerived, typename TBase>
+std::unique_ptr<TDerived> static_cast_unique_ptr(std::unique_ptr<TBase>&& ptr) {
+ static_assert(std::is_base_of<TBase, TDerived>::value, "TDerived must be derived from TBase");
+ return std::unique_ptr<TDerived>(static_cast<TDerived*>(ptr.release()));
+}
+
+
+#endif // UTIL_HPP
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/osmcoastline.git
More information about the Pkg-grass-devel
mailing list