Squashed 'third_party/libosmium/' content from commit 2282c84
git-subtree-dir: third_party/libosmium git-subtree-split: 2282c8450bae55839372a2002db7ca754530d2fc
This commit is contained in:
commit
8511256779
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.swp
|
||||||
|
.ycm_extra_conf.pyc
|
159
.travis.yml
Normal file
159
.travis.yml
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Configuration for continuous integration service at travis-ci.org
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
language: cpp
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
|
||||||
|
# 1/ Linux Clang Builds
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.5', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.5' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.5', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.5' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.6' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.6' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.7', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.7' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: clang
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['clang-3.7', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='clang++-3.7' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
# 2/ Linux GCC Builds
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-4.8', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-4.8' COMPILER_FLAGS='-Wno-return-type' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-4.8', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-4.8' COMPILER_FLAGS='-Wno-return-type' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-4.9', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-4.9' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-4.9', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-4.9' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-5', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-5' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
- os: linux
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||||
|
packages: ['g++-5', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||||
|
env: COMPILER='g++-5' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
|
||||||
|
# 3/ OSX Clang Builds
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode6.4
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode6.4
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode7
|
||||||
|
compiler: clang
|
||||||
|
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||||
|
|
||||||
|
|
||||||
|
install:
|
||||||
|
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||||
|
- mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
||||||
|
- git clone --quiet --depth 1 https://github.com/osmcode/osm-testdata.git
|
||||||
|
- |
|
||||||
|
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
||||||
|
brew remove gdal
|
||||||
|
brew install cmake boost google-sparsehash gdal
|
||||||
|
fi
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- cd ${TRAVIS_BUILD_DIR}
|
||||||
|
- mkdir build && cd build
|
||||||
|
- CXX=${COMPILER} CXXFLAGS=${COMPILER_FLAGS} cmake -LA .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DOSM_TESTDATA="${TRAVIS_BUILD_DIR}/deps/osm-testdata"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make VERBOSE=1
|
||||||
|
- ctest --output-on-failure
|
||||||
|
|
48
.ycm_extra_conf.py
Normal file
48
.ycm_extra_conf.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Configuration for YouCompleteMe Vim plugin
|
||||||
|
#
|
||||||
|
# http://valloric.github.io/YouCompleteMe/
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from os.path import realpath, dirname
|
||||||
|
|
||||||
|
basedir = dirname(realpath(__file__))
|
||||||
|
|
||||||
|
# some default flags
|
||||||
|
# for more information install clang-3.2-doc package and
|
||||||
|
# check UsersManual.html
|
||||||
|
flags = [
|
||||||
|
'-Werror',
|
||||||
|
'-Wall',
|
||||||
|
'-Wextra',
|
||||||
|
'-pedantic',
|
||||||
|
'-Wno-return-type',
|
||||||
|
'-Wno-unused-parameter',
|
||||||
|
'-Wno-unused-variable',
|
||||||
|
|
||||||
|
'-std=c++11',
|
||||||
|
|
||||||
|
# '-x' and 'c++' also required
|
||||||
|
# use 'c' for C projects
|
||||||
|
'-x',
|
||||||
|
'c++',
|
||||||
|
|
||||||
|
# libosmium include dirs
|
||||||
|
'-I%s/include' % basedir,
|
||||||
|
'-I%s/test/include' % basedir,
|
||||||
|
'-I%s/test/data-test/include' % basedir,
|
||||||
|
|
||||||
|
# include third party libraries
|
||||||
|
'-I/usr/include/gdal',
|
||||||
|
]
|
||||||
|
|
||||||
|
# youcompleteme is calling this function to get flags
|
||||||
|
# You can also set database for flags. Check: JSONCompilationDatabase.html in
|
||||||
|
# clang-3.2-doc package
|
||||||
|
def FlagsForFile( filename ):
|
||||||
|
return {
|
||||||
|
'flags': flags,
|
||||||
|
'do_cache': True
|
||||||
|
}
|
292
CHANGELOG.md
Normal file
292
CHANGELOG.md
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
|
||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [unreleased] -
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
|
||||||
|
## [2.6.1] - 2016-02-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add `WITH_PROFILING` option to CMake config. When enabled, this sets the
|
||||||
|
`-fno-omit-frame-pointer` compiler option.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Massive speed improvements when building multipolygons.
|
||||||
|
- Uses (and includes) new version 1.3.0 of protozero library.
|
||||||
|
- Removed dependency on Boost Iterator for PBF writer.
|
||||||
|
- Example program `osmium_area_test` now uses `cerr` instead of `cout` for
|
||||||
|
debug output.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.6.0] - 2016-02-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The new handler osmium::handler::CheckOrder can be used to check that a
|
||||||
|
file is properly ordered.
|
||||||
|
- Add new method to build OSM nodes, ways, relations, changesets, and areas
|
||||||
|
in buffers that wraps the older Builder classes. The new code is much easier
|
||||||
|
to use and very flexible. There is no documentation yet, but the tests in
|
||||||
|
`test/t/builder/test_attr.cpp` can give you an idea how it works.
|
||||||
|
- Add util class to get memory usage of current process on Linux.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- New Buffer memory management speeds up Buffer use, because it doesn't clear
|
||||||
|
the memory unnecessarily.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- osmium::Box::extend() function now ignores invalid locations.
|
||||||
|
- Install of external library headers.
|
||||||
|
- Check way has at least one node before calling `is_closed()` in area
|
||||||
|
assembler.
|
||||||
|
- Declaration/definition of some friend functions was in the wrong namespace.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.4] - 2015-12-03
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Included gdalcpp.hpp header was updated to version 1.1.1.
|
||||||
|
- Included protozero library was updated to version 1.2.3.
|
||||||
|
- Workarounds for missing constexpr support in Visual Studio removed. All
|
||||||
|
constexpr features we need are supported now.
|
||||||
|
- Some code cleanup after running clang-tidy on the code.
|
||||||
|
- Re-added `Buffer::value_type` typedef. Turns out it is needed when using
|
||||||
|
`std::back_inserter` on the Buffer.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Bugs with Timestamp code on 32 bit platforms. This necessitated
|
||||||
|
some changes in Timestamp which might lead to changes in user
|
||||||
|
code.
|
||||||
|
- Bug in segment intersection code (which appeared on i686 platform).
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.3] - 2015-11-17
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `osmium::make_diff_iterator()` helper function.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Deprecated `osmium::Buffer::set_full_callback()`.
|
||||||
|
- Removed DataFile class which was never used anywhere.
|
||||||
|
- Removed unused and obscure `Buffer::value_type` typedef.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Possible overrun in Buffer when using the full-callback.
|
||||||
|
- Incorrect swapping of Buffer.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.2] - 2015-11-06
|
||||||
|
|
||||||
|
# Fixed
|
||||||
|
|
||||||
|
- Writing data through an OutputIterator was extremly slow due to
|
||||||
|
lock contention.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.1] - 2015-11-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Header `osmium/fwd.hpp` with forward declarations of the most commonly
|
||||||
|
used Osmium classes.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Moved `osmium/io/overwrite.hpp` to `osmium/io/writer_options.hpp`
|
||||||
|
If you still include the old file, you'll get a warning.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.5.0] - 2015-11-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Helper functions to make input iterator ranges and output iterators.
|
||||||
|
- Add support for reading o5m and o5c files.
|
||||||
|
- Option for osmium::io::Writer to fsync file after writing.
|
||||||
|
- Lots of internal asserts() and other robustness checks.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Updated included protozero library to version 1.2.0.
|
||||||
|
- Complete overhaul of the I/O system making it much more robust against
|
||||||
|
wrong data and failures during I/O operations.
|
||||||
|
- Speed up PBF writing by running parts of it in parallel.
|
||||||
|
- OutputIterator doesn't hold an internal buffer any more, but it uses
|
||||||
|
one in Writer. Calling flush() on the OutputIterator isn't needed any
|
||||||
|
more.
|
||||||
|
- Reader now throws when trying to read after eof or an error.
|
||||||
|
- I/O functions that used to throw std::runtime_error now throw
|
||||||
|
osmium::io_error or derived.
|
||||||
|
- Optional parameters on osmium::io::Writer now work in any order.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- PBF reader now decodes locations of invisible nodes properly.
|
||||||
|
- Invalid Delta encode iterator dereference.
|
||||||
|
- Lots of includes fixed to include (only) what's used.
|
||||||
|
- Dangling reference in area assembly code.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.4.1] - 2015-08-29
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- CRC calculation of tags and changesets.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.4.0] - 2015-08-29
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Checks that user names, member roles and tag keys and values are not longer
|
||||||
|
than 256 * 4 bytes. That is the maximum length 256 Unicode characters
|
||||||
|
can have in UTF-8 encoding.
|
||||||
|
- Support for GDAL 2. GDAL 1 still works.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Improved CMake build scripts.
|
||||||
|
- Updated internal version of Protozero to 1.1.0.
|
||||||
|
- Removed `toogr*` examples. They are in their own repository now.
|
||||||
|
See https://github.com/osmcode/osm-gis-export.
|
||||||
|
- Files about to be memory-mapped (for instance index files) are now set
|
||||||
|
to binary mode on Windows so the application doesn't have to do this.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Hanging program when trying to open file with an unknown file format.
|
||||||
|
- Building problems with old boost versions.
|
||||||
|
- Initialization errors in PBF writer.
|
||||||
|
- Bug in byte swap code.
|
||||||
|
- Output on Windows now always uses binary mode, even when writing to
|
||||||
|
stdout, so OSM xml and opl files always use LF line endings.
|
||||||
|
|
||||||
|
|
||||||
|
## [2.3.0] - 2015-08-18
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Allow instantiating osmium::geom::GEOSFactory with existing GEOS factory.
|
||||||
|
- Low-level functions to support generating a architecture- and endian-
|
||||||
|
independant CRC from OSM data. This is intended to be uses with boost::crc.
|
||||||
|
- Add new debug output format. This format is not intended to be read
|
||||||
|
automatically, but for human consumption. It formats the data nicely.
|
||||||
|
- Make writing of metadata configurable for XML and OPL output (use
|
||||||
|
`add_metadata=false` as file option).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Changed `add_user()` and `add_role()` in builders to use string length
|
||||||
|
without the 0-termination.
|
||||||
|
- Improved code setting file format from suffix/format argument.
|
||||||
|
- Memory mapping utility class now supports readonly, private writable or
|
||||||
|
shared writable operation.
|
||||||
|
- Allow empty version (0) in PBF files.
|
||||||
|
- Use utf8cpp header-only lib instead of boost for utf8 decoding. The library
|
||||||
|
is included in the libosmium distribution.
|
||||||
|
- New PBF reader and writer based on the protozero. A complete rewrite of the
|
||||||
|
code for reading and writing OSM PBF files. It doesn't use the Google
|
||||||
|
protobuf library and it doesn't use the OSMPBF/OSM-Binary library any more.
|
||||||
|
Instead is uses the protozero lightweight protobuf header library which is
|
||||||
|
included in the code. Not only does the new code have less dependencies, it
|
||||||
|
is faster and more robust. https://github.com/mapbox/protozero
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Various smaller bug fixes.
|
||||||
|
- Add encoding for relation member roles in OPL format.
|
||||||
|
- Change character encoding to new format in OPL: variable length hex code
|
||||||
|
between % characters instead of a % followed by 4-digit hex code. This is
|
||||||
|
necessary because unicode characters can be longer than the 4-digit hex
|
||||||
|
code.
|
||||||
|
- XML writer: The linefeed, carriage return, and tab characters are now
|
||||||
|
escaped properly.
|
||||||
|
- Reading large XML files could block.
|
||||||
|
|
||||||
|
## [2.2.0] - 2015-07-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Conversion functions for some low-level types.
|
||||||
|
- BoolVector index class.
|
||||||
|
- `min_op`/`max_op` utility functions.
|
||||||
|
- More tests here and there.
|
||||||
|
- Helper methods `is_between()` and `is_visible_at()` to DiffObject.
|
||||||
|
- GeoJSON factory using the RapidJSON library.
|
||||||
|
- Support for tile calculations.
|
||||||
|
- Create simple polygons from ways in geom factories.
|
||||||
|
- `MemoryMapping` and `TypedMemoryMapping` helper classes.
|
||||||
|
- `close()` function to `mmap_vector_base` class.
|
||||||
|
- Function on `Buffer` class to get iterator to specific offset.
|
||||||
|
- Explicit cast operator from `osmium::Timestamp` to `uint32_t`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Throw exception on illegal values in functions parsing strings to get ids,
|
||||||
|
versions, etc.
|
||||||
|
- Improved error message for geometry exceptions.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Throw exception from `dump_as_array()` and `dump_as_list()` functions if not
|
||||||
|
implemented in an index.
|
||||||
|
- After writing OSM files, program could stall up to a second.
|
||||||
|
- Dense location store was written out only partially.
|
||||||
|
- Use `uint64_t` as counter in benchmarks, so there can be no overflows.
|
||||||
|
- Example programs now read packed XML files, too.
|
||||||
|
- Refactoring of memory mapping code. Removes leak on Windows.
|
||||||
|
- Better check for invalid locations.
|
||||||
|
- Mark `cbegin()` and `cend()` of `mmap_vector_base` as const functions.
|
||||||
|
|
||||||
|
## [2.1.0] - 2015-03-31
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- When writing PBF files, sorting the PBF stringtables is now optional.
|
||||||
|
- More tests and documentation.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Some functions are now declared `noexcept`.
|
||||||
|
- XML parser fails now if the top-level element is not `osm` or `osmChange`.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Race condition in PBF reader.
|
||||||
|
- Multipolygon collector was accessing non-existent NodeRef.
|
||||||
|
- Doxygen documentation wan't showing all classes/functions due to a bug in
|
||||||
|
Doxygen (up to version 1.8.8). This version contains a workaround to fix
|
||||||
|
this.
|
||||||
|
|
||||||
|
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.6.1...HEAD
|
||||||
|
[2.6.1]: https://github.com/osmcode/libosmium/compare/v2.6.0...v2.6.1
|
||||||
|
[2.6.0]: https://github.com/osmcode/libosmium/compare/v2.5.4...v2.6.0
|
||||||
|
[2.5.4]: https://github.com/osmcode/libosmium/compare/v2.5.3...v2.5.4
|
||||||
|
[2.5.3]: https://github.com/osmcode/libosmium/compare/v2.5.2...v2.5.3
|
||||||
|
[2.5.2]: https://github.com/osmcode/libosmium/compare/v2.5.1...v2.5.2
|
||||||
|
[2.5.1]: https://github.com/osmcode/libosmium/compare/v2.5.0...v2.5.1
|
||||||
|
[2.5.0]: https://github.com/osmcode/libosmium/compare/v2.4.1...v2.5.0
|
||||||
|
[2.4.1]: https://github.com/osmcode/libosmium/compare/v2.4.0...v2.4.1
|
||||||
|
[2.4.0]: https://github.com/osmcode/libosmium/compare/v2.3.0...v2.4.0
|
||||||
|
[2.3.0]: https://github.com/osmcode/libosmium/compare/v2.2.0...v2.3.0
|
||||||
|
[2.2.0]: https://github.com/osmcode/libosmium/compare/v2.1.0...v2.2.0
|
||||||
|
[2.1.0]: https://github.com/osmcode/libosmium/compare/v2.0.0...v2.1.0
|
||||||
|
|
515
CMakeLists.txt
Normal file
515
CMakeLists.txt
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Libosmium
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project version
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Coverage"
|
||||||
|
CACHE STRING
|
||||||
|
"List of available configuration types"
|
||||||
|
FORCE)
|
||||||
|
|
||||||
|
project(libosmium)
|
||||||
|
|
||||||
|
set(LIBOSMIUM_VERSION_MAJOR 2)
|
||||||
|
set(LIBOSMIUM_VERSION_MINOR 6)
|
||||||
|
set(LIBOSMIUM_VERSION_PATCH 1)
|
||||||
|
|
||||||
|
set(LIBOSMIUM_VERSION
|
||||||
|
"${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}")
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Build options
|
||||||
|
#
|
||||||
|
# (Change with -DOPTION=VALUE on cmake command line.)
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Dev")
|
||||||
|
set(dev_build ON)
|
||||||
|
else()
|
||||||
|
set(dev_build OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(BUILD_EXAMPLES "compile example programs" ON)
|
||||||
|
option(BUILD_TESTING "compile unit tests, please run them with ctest" ON)
|
||||||
|
|
||||||
|
option(BUILD_HEADERS "compile every header file on its own" ${dev_build})
|
||||||
|
option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build})
|
||||||
|
option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${dev_build})
|
||||||
|
|
||||||
|
option(INSTALL_GDALCPP "also install gdalcpp headers" OFF)
|
||||||
|
option(INSTALL_PROTOZERO "also install protozero headers" OFF)
|
||||||
|
option(INSTALL_UTFCPP "also install utfcpp headers" OFF)
|
||||||
|
|
||||||
|
option(WITH_PROFILING "add flags needed for profiling" OFF)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Coverage support
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag("-fkeep-inline-functions" HAS_KEEP_INLINE_FUNCTIONS)
|
||||||
|
if(HAS_KEEP_INLINE_FUNCTIONS)
|
||||||
|
set(extra_coverage_flags_ "-fkeep-inline-functions")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
"-g -O0 -fno-inline-functions -fno-inline --coverage ${extra_coverage_flags_}"
|
||||||
|
CACHE STRING "Flags used by the compiler during coverage builds.")
|
||||||
|
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
"--coverage"
|
||||||
|
CACHE STRING "Flags used by the linker during coverage builds.")
|
||||||
|
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||||
|
if(BUILD_EXAMPLES OR BUILD_HEADERS OR BUILD_BENCHMARKS OR BUILD_DATA_TESTS)
|
||||||
|
message(WARNING "Coverage builds don't work for anything but the unit tests")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "llvm-cov-\\1.\\2"
|
||||||
|
gcov_ ${CMAKE_CXX_COMPILER_VERSION})
|
||||||
|
else()
|
||||||
|
set(gcov_ "gcov")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_program(GCOV ${gcov_} DOC "Coverage tool")
|
||||||
|
find_program(GCOVR "gcovr" DOC "Coverage report tool")
|
||||||
|
|
||||||
|
set(coverage_report_dir "${CMAKE_BINARY_DIR}/coverage")
|
||||||
|
file(MAKE_DIRECTORY ${coverage_report_dir})
|
||||||
|
add_custom_target(coverage
|
||||||
|
${GCOVR}
|
||||||
|
${CMAKE_BINARY_DIR}
|
||||||
|
--root=${CMAKE_SOURCE_DIR}
|
||||||
|
--html --html-details
|
||||||
|
#--verbose
|
||||||
|
#--keep
|
||||||
|
'--filter=.*include/osmium.*'
|
||||||
|
--sort-percentage
|
||||||
|
--gcov-executable=${GCOV}
|
||||||
|
--output=${coverage_report_dir}/index.html)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Find external dependencies
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
find_package(Boost 1.38)
|
||||||
|
mark_as_advanced(CLEAR BOOST_ROOT)
|
||||||
|
|
||||||
|
if(Boost_FOUND)
|
||||||
|
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
set(BOOST_ROOT "NOT FOUND: please choose" CACHE PATH "")
|
||||||
|
message(FATAL_ERROR "PLEASE, specify the directory where the Boost library is installed in BOOST_ROOT")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# set OSMIUM_INCLUDE_DIR so FindOsmium will not set anything different
|
||||||
|
set(OSMIUM_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
|
|
||||||
|
include_directories(${OSMIUM_INCLUDE_DIR})
|
||||||
|
|
||||||
|
find_package(Osmium COMPONENTS io gdal geos proj sparsehash)
|
||||||
|
|
||||||
|
# The find_package put the directory where it found the libosmium includes
|
||||||
|
# into OSMIUM_INCLUDE_DIRS. We remove it again, because we want to make
|
||||||
|
# sure to use our own include directory already set up above.
|
||||||
|
list(FIND OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}" _own_index)
|
||||||
|
list(REMOVE_AT OSMIUM_INCLUDE_DIRS ${_own_index})
|
||||||
|
set(_own_index)
|
||||||
|
|
||||||
|
include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
find_path(GETOPT_INCLUDE_DIR getopt.h)
|
||||||
|
find_library(GETOPT_LIBRARY NAMES wingetopt)
|
||||||
|
if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY)
|
||||||
|
include_directories(SYSTEM ${GETOPT_INCLUDE_DIR})
|
||||||
|
list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY})
|
||||||
|
else()
|
||||||
|
set(GETOPT_MISSING 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Decide which C++ version to use (Minimum/default: C++11).
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
if(NOT MSVC)
|
||||||
|
if(NOT USE_CPP_VERSION)
|
||||||
|
set(USE_CPP_VERSION c++11)
|
||||||
|
endif()
|
||||||
|
message(STATUS "Use C++ version: ${USE_CPP_VERSION}")
|
||||||
|
# following only available from cmake 2.8.12:
|
||||||
|
# add_compile_options(-std=${USE_CPP_VERSION})
|
||||||
|
# so using this instead:
|
||||||
|
add_definitions(-std=${USE_CPP_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Compiler and Linker flags
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
if(MSVC)
|
||||||
|
set(USUAL_COMPILE_OPTIONS "/Ox")
|
||||||
|
set(USUAL_LINK_OPTIONS "/debug")
|
||||||
|
else()
|
||||||
|
set(USUAL_COMPILE_OPTIONS "-O3 -g")
|
||||||
|
set(USUAL_LINK_OPTIONS "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32
|
||||||
|
-DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}"
|
||||||
|
CACHE STRING "Flags used by the compiler during developer builds."
|
||||||
|
FORCE)
|
||||||
|
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_DEV "${USUAL_LINK_OPTIONS}"
|
||||||
|
CACHE STRING "Flags used by the linker during developer builds."
|
||||||
|
FORCE)
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_CXX_FLAGS_DEV
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_DEV
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}"
|
||||||
|
CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds."
|
||||||
|
FORCE)
|
||||||
|
|
||||||
|
if(WITH_PROFILING)
|
||||||
|
add_definitions(-fno-omit-frame-pointer)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Build Type
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# In 'Dev' mode: compile with very strict warnings and turn them into errors.
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Dev")
|
||||||
|
if(NOT MSVC)
|
||||||
|
add_definitions(-Werror)
|
||||||
|
endif()
|
||||||
|
add_definitions(${OSMIUM_WARNING_OPTIONS})
|
||||||
|
# add_definitions(${OSMIUM_WARNING_OPTIONS} ${OSMIUM_DRACONIC_CLANG_OPTIONS} -Wno-documentation -Wno-format-nonliteral -Wno-deprecated -Wno-covered-switch-default -Wno-shadow)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Force RelWithDebInfo build type if none was given
|
||||||
|
if(CMAKE_BUILD_TYPE)
|
||||||
|
set(build_type ${CMAKE_BUILD_TYPE})
|
||||||
|
else()
|
||||||
|
set(build_type "RelWithDebInfo")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_BUILD_TYPE ${build_type}
|
||||||
|
CACHE STRING
|
||||||
|
"Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}."
|
||||||
|
FORCE)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Unit and data tests
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
if(BUILD_TESTING OR BUILD_DATA_TESTS)
|
||||||
|
find_program(MEMORYCHECK_COMMAND valgrind)
|
||||||
|
|
||||||
|
set(MEMORYCHECK_COMMAND_OPTIONS
|
||||||
|
"--trace-children=yes --leak-check=full --show-reachable=yes --error-exitcode=1")
|
||||||
|
|
||||||
|
set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.supp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_DATA_TESTS)
|
||||||
|
add_subdirectory(test/data-tests)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Optional "cppcheck" target that checks C++ code
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Looking for cppcheck")
|
||||||
|
find_program(CPPCHECK cppcheck)
|
||||||
|
|
||||||
|
if(CPPCHECK)
|
||||||
|
message(STATUS "Looking for cppcheck - found")
|
||||||
|
set(CPPCHECK_OPTIONS
|
||||||
|
--enable=warning,style,performance,portability,information,missingInclude --force -Uassert)
|
||||||
|
|
||||||
|
# cpp doesn't find system includes for some reason, suppress that report
|
||||||
|
set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem)
|
||||||
|
|
||||||
|
file(GLOB_RECURSE ALL_INCLUDES include/osmium/*.hpp)
|
||||||
|
file(GLOB ALL_EXAMPLES examples/*.cpp)
|
||||||
|
file(GLOB ALL_BENCHMARKS benchmarks/*.cpp)
|
||||||
|
file(GLOB ALL_UNIT_TESTS test/t/*/test_*.cpp)
|
||||||
|
file(GLOB ALL_DATA_TESTS test/data-tests/*.cpp)
|
||||||
|
|
||||||
|
if(Osmium_DEBUG)
|
||||||
|
message(STATUS "Checking includes : ${ALL_INCLUDES}")
|
||||||
|
message(STATUS "Checking example code : ${ALL_EXAMPLES}")
|
||||||
|
message(STATUS "Checking benchmarks : ${ALL_BENCHMARKS}")
|
||||||
|
message(STATUS "Checking unit test code: ${ALL_UNIT_TESTS}")
|
||||||
|
message(STATUS "Checking data test code: ${ALL_DATA_TESTS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CPPCHECK_FILES
|
||||||
|
${ALL_INCLUDES}
|
||||||
|
${ALL_EXAMPLES}
|
||||||
|
${ALL_BENCHMARKS}
|
||||||
|
${ALL_UNIT_TESTS}
|
||||||
|
${ALL_DATA_TESTS})
|
||||||
|
|
||||||
|
add_custom_target(cppcheck
|
||||||
|
${CPPCHECK}
|
||||||
|
--std=c++11 ${CPPCHECK_OPTIONS}
|
||||||
|
-I ${CMAKE_SOURCE_DIR}/include
|
||||||
|
${CPPCHECK_FILES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(STATUS "Looking for cppcheck - not found")
|
||||||
|
message(STATUS " Build target 'cppcheck' will not be available.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Examples, benchmarks and documentation
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
add_subdirectory(examples)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_BENCHMARKS)
|
||||||
|
add_subdirectory(benchmarks)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(doc)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Headers
|
||||||
|
#
|
||||||
|
# This will try to compile include files on their own to detect missing
|
||||||
|
# include directives and other dependency-related problems. Note that if this
|
||||||
|
# work, it is not enough to be sure it will compile in production code.
|
||||||
|
# But if it reports an error we know we are missing something.
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
if(BUILD_HEADERS)
|
||||||
|
file(GLOB_RECURSE
|
||||||
|
ALL_HPPS
|
||||||
|
RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/include"
|
||||||
|
include/osmium/*.hpp)
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY header_check)
|
||||||
|
|
||||||
|
foreach(hpp ${ALL_HPPS})
|
||||||
|
string(REPLACE ".hpp" "" tmp ${hpp})
|
||||||
|
string(REPLACE "/" "__" libname ${tmp})
|
||||||
|
|
||||||
|
# Create a dummy .cpp file that includes the header file we want to
|
||||||
|
# check.
|
||||||
|
set(DUMMYCPP ${CMAKE_BINARY_DIR}/header_check/${libname}.cpp)
|
||||||
|
file(WRITE ${DUMMYCPP} "#include <${hpp}>\n")
|
||||||
|
|
||||||
|
# There is no way in CMake to just compile but not link a C++ file,
|
||||||
|
# so we pretend to build a library here.
|
||||||
|
add_library(${libname} STATIC ${DUMMYCPP} include/${hpp})
|
||||||
|
|
||||||
|
#### this is better but only supported from cmake 3.0:
|
||||||
|
###add_library(${libname} OBJECT ${DUMMYCPP} include/${hpp})
|
||||||
|
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Optional "clang-tidy" target
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Looking for clang-tidy")
|
||||||
|
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-3.9 clang-tidy-3.8 clang-tidy-3.7 clang-tidy-3.6 clang-tidy-3.5)
|
||||||
|
|
||||||
|
if(CLANG_TIDY)
|
||||||
|
message(STATUS "Looking for clang-tidy - found")
|
||||||
|
|
||||||
|
if(BUILD_EXAMPLES)
|
||||||
|
file(GLOB CT_ALL_EXAMPLES examples/*.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
file(GLOB CT_ALL_UNIT_TESTS test/t/*/test_*.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_HEADERS)
|
||||||
|
file(GLOB_RECURSE CT_ALL_INCLUDES ${CMAKE_BINARY_DIR}/header_check/osmium__*.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_BENCHMARKS)
|
||||||
|
file(GLOB CT_ALL_BENCHMARKS benchmarks/*.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_DATA_TESTS)
|
||||||
|
file(GLOB CT_ALL_DATA_TESTS test/data-tests/*.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(Osmium_DEBUG)
|
||||||
|
message(STATUS "Checking example code : ${CT_ALL_EXAMPLES}")
|
||||||
|
message(STATUS "Checking unit test code: ${CT_ALL_UNIT_TESTS}")
|
||||||
|
message(STATUS "Checking includes : ${CT_ALL_INCLUDES}")
|
||||||
|
message(STATUS "Checking benchmarks : ${CT_ALL_BENCHMARKS}")
|
||||||
|
message(STATUS "Checking data test code: ${CT_ALL_DATA_TESTS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CT_CHECK_FILES
|
||||||
|
${CT_ALL_EXAMPLES}
|
||||||
|
${CT_ALL_UNIT_TESTS}
|
||||||
|
${CT_ALL_INCLUDES}
|
||||||
|
${CT_ALL_BENCHMARKS}
|
||||||
|
${CT_ALL_DATA_TESTS})
|
||||||
|
|
||||||
|
# For a list of check options, see:
|
||||||
|
# http://clang.llvm.org/extra/clang-tidy/checks/list.html
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "cert-*"
|
||||||
|
"-cert-err60-cpp") # even the std lib doesn't do this
|
||||||
|
|
||||||
|
# disabled, because it is slow
|
||||||
|
# list(APPEND CT_CHECKS "clang-analyzer-*")
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "google-*"
|
||||||
|
"-google-explicit-constructor"
|
||||||
|
"-google-readability-casting"
|
||||||
|
"-google-readability-function")
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "llvm-*"
|
||||||
|
"-llvm-include-order")
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "misc-*"
|
||||||
|
"-misc-argument-comment")
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "modernize-*")
|
||||||
|
|
||||||
|
list(APPEND CT_CHECKS "readability-*"
|
||||||
|
"-readability-identifier-naming"
|
||||||
|
"-readability-named-parameter")
|
||||||
|
|
||||||
|
string(REPLACE ";" "," ALL_CHECKS "${CT_CHECKS}")
|
||||||
|
|
||||||
|
add_custom_target(clang-tidy
|
||||||
|
${CLANG_TIDY}
|
||||||
|
-p ${CMAKE_BINARY_DIR}
|
||||||
|
-header-filter='include/osmium/.*'
|
||||||
|
-checks="${ALL_CHECKS}"
|
||||||
|
${CT_CHECK_FILES}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(STATUS "Looking for clang-tidy - not found")
|
||||||
|
message(STATUS " Build target 'clang-tidy' will not be available.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Installation
|
||||||
|
#
|
||||||
|
# External libraries are only installed if the options are set in case they
|
||||||
|
# are installed from somewhere else.
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
install(DIRECTORY include/osmium DESTINATION include)
|
||||||
|
|
||||||
|
if(INSTALL_GDALCPP)
|
||||||
|
install(FILES include/gdalcpp.hpp DESTINATION include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(INSTALL_PROTOZERO)
|
||||||
|
install(DIRECTORY include/protozero DESTINATION include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(INSTALL_UTFCPP)
|
||||||
|
install(FILES include/utf8.h DESTINATION include)
|
||||||
|
install(DIRECTORY include/utf8 DESTINATION include)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Packaging
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${LIBOSMIUM_VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${LIBOSMIUM_VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${LIBOSMIUM_VERSION_PATCH})
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(CPACK_GENERATOR ZIP)
|
||||||
|
else()
|
||||||
|
set(CPACK_GENERATOR TGZ)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CPack)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Print warnings at the end
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
if(BUILD_DATA_TESTS AND OSM_TESTDATA STREQUAL "OSM_TESTDATA-NOTFOUND")
|
||||||
|
message("\n========================== WARNING ==========================")
|
||||||
|
message("osm-testdata directory not found, data tests were disabled!\n")
|
||||||
|
message("You can get it from https://github.com/osmcode/osm-testdata")
|
||||||
|
message("Clone it into the same directory libosmium is in")
|
||||||
|
message("or set the OSM_TESTDATA cmake variable to its path.")
|
||||||
|
message("=============================================================\n")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
143
CONTRIBUTING.md
Normal file
143
CONTRIBUTING.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
|
||||||
|
# Notes for Developers
|
||||||
|
|
||||||
|
Read this if you want to contribute to Libosmium.
|
||||||
|
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
Osmium is currently considered in beta and doesn't use versioning yet. Proper
|
||||||
|
versions will be introduced as soon as it is somewhat stable.
|
||||||
|
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
|
||||||
|
All Osmium code MUST be in the `osmium` namespace or one of its sub-namespaces.
|
||||||
|
|
||||||
|
|
||||||
|
## Include-Only
|
||||||
|
|
||||||
|
Osmium is a include-only library. You can't compile the library itself. There
|
||||||
|
is no libosmium.so.
|
||||||
|
|
||||||
|
One drawback ist that you can't have static data in classes, because there
|
||||||
|
is no place to put this data.
|
||||||
|
|
||||||
|
All free functions must be declared `inline`.
|
||||||
|
|
||||||
|
|
||||||
|
## Coding Conventions
|
||||||
|
|
||||||
|
These coding conventions have been changing over time and some code is still
|
||||||
|
different.
|
||||||
|
|
||||||
|
* All include files have `#ifdef` guards around them, macros are the path name
|
||||||
|
in all uppercase where the slashes (`/`) have been changed to underscore (`_`).
|
||||||
|
* Class names begin with uppercase chars and use CamelCase. Smaller helper
|
||||||
|
classes are usually defined as struct and have lowercase names.
|
||||||
|
* Macros (and only macros) are all uppercase. Use macros sparingly, usually
|
||||||
|
a simple (maybe constexpr) inline function is better. Undef macros after use
|
||||||
|
if possible.
|
||||||
|
* Macros should only be used for controlling which parts of the code should be
|
||||||
|
included when compiling or to avoid major code repetitions.
|
||||||
|
* Variables, attributes, and function names are lowercase with
|
||||||
|
`underscores_between_words`.
|
||||||
|
* Class attribute names start with `m_` (member).
|
||||||
|
* Use `descriptive_variable_names`, exceptions are well-established conventions
|
||||||
|
like `i` for a loop variable. Iterators are usually called `it`.
|
||||||
|
* Declare variables where they are first used (C++ style), not at the beginning
|
||||||
|
of a function (old C style).
|
||||||
|
* Names from external namespaces (even `std`) are always mentioned explicitly.
|
||||||
|
Do not use `using` (except for `std::swap`). This way we can't even by
|
||||||
|
accident pollute the namespace of the code using Osmium.
|
||||||
|
* Always use the standard swap idiom: `using std::swap; swap(foo, bar);`.
|
||||||
|
* `#include` directives appear in three "blocks" after the copyright notice.
|
||||||
|
The blocks are separated by blank lines. First block contains `#include`s for
|
||||||
|
standard C/C++ includes, second block for any external libs used, third
|
||||||
|
block for osmium internal includes. Within each block `#include`s are usually
|
||||||
|
sorted by path name. All `#include`s use `<>` syntax not `""`.
|
||||||
|
* Names not to be used from outside the library should be in a namespace
|
||||||
|
called `detail` under the namespace where they would otherwise appear. If
|
||||||
|
whole include files are never meant to be included from outside they should
|
||||||
|
be in a subdirectory called `detail`.
|
||||||
|
* All files have suffix `.hpp`.
|
||||||
|
* Closing } of all classes and namespaces should have a trailing comment
|
||||||
|
with the name of the class/namespace.
|
||||||
|
* All constructors with one (or more arguments if they have a default) should
|
||||||
|
be declared "explicit" unless there is a reason for them not to be. Document
|
||||||
|
that reason.
|
||||||
|
* If a class has any of the special methods (copy/move constructor/assigment,
|
||||||
|
destructor) it should have all of them, possibly marking them as default or
|
||||||
|
deleted.
|
||||||
|
* Typedefs have `names_like_this_type` which end in `_type`. Typedefs should
|
||||||
|
use the new `using foo_type = bar` syntax instead of the old
|
||||||
|
`typedef bar foo_type`.
|
||||||
|
* Template parameters are single uppercase letters or start with uppercase `T`
|
||||||
|
and use CamelCase.
|
||||||
|
* Always use `typename` in templates, not `class`: `template <typename T>`.
|
||||||
|
* The ellipsis in variadic template never has a space to the left of it and
|
||||||
|
always has a space to the right: `template <typename... TArgs>` etc.
|
||||||
|
|
||||||
|
Keep to the indentation and other styles used in the code. Use `make indent`
|
||||||
|
in the toplevel directory to fix indentation and styling. It calls `astyle`
|
||||||
|
with the right parameters. This program is in the `astyle` Debian package.
|
||||||
|
|
||||||
|
|
||||||
|
## C++11
|
||||||
|
|
||||||
|
Osmium uses C++11 and you can use its features such as auto, lambdas,
|
||||||
|
threading, etc. There are a few features we do not use, because even modern
|
||||||
|
compilers don't support them yet. This list might change as we get more data
|
||||||
|
about which compilers support which feature and what operating system versions
|
||||||
|
or distributions have which versions of these compilers installed.
|
||||||
|
|
||||||
|
GCC 4.6 - too old, not supported (Ubuntu 12.04 LTS)
|
||||||
|
GCC 4.7.2 - can probably not be supported (Debian wheezy)
|
||||||
|
GCC 4.7.3 - probably works
|
||||||
|
GCC 4.8 - works and is supported from here on
|
||||||
|
clang 3.0 - too old, not supported (Debian wheezy, Ubuntu 12.04 LTS)
|
||||||
|
clang 3.2 - probably works
|
||||||
|
clang 3.5 - works and is supported from here on
|
||||||
|
|
||||||
|
Use `include/osmium/util/compatibility.hpp` if there are compatibility problems
|
||||||
|
between compilers due to different C++11 support.
|
||||||
|
|
||||||
|
|
||||||
|
## Checking your code
|
||||||
|
|
||||||
|
The Osmium makefiles use pretty draconian warning options for the compiler.
|
||||||
|
This is good. Code MUST never produce any warnings, even with those settings.
|
||||||
|
If absolutely necessary pragmas can be used to disable certain warnings in
|
||||||
|
specific areas of the code.
|
||||||
|
|
||||||
|
If the static code checker `cppcheck` is installed, the CMake configuration
|
||||||
|
will add a new build target `cppcheck` that will check all `.cpp` and `.hpp`
|
||||||
|
files. Cppcheck finds some bugs that gcc/clang doesn't. But take the result
|
||||||
|
with a grain of salt, it also sometimes produces wrong warnings.
|
||||||
|
|
||||||
|
Set `BUILD_HEADERS=ON` in the CMake config to enable compiling all include
|
||||||
|
files on their own to check whether dependencies are all okay. All include
|
||||||
|
files MUST include all other include files they depend on.
|
||||||
|
|
||||||
|
Call `cmake/iwyu.sh` to check for proper includes and forward declarations.
|
||||||
|
This uses the clang-based `include-what-you-use` program. Note that it does
|
||||||
|
produce some false reports and crashes often. The `osmium.imp` file can be
|
||||||
|
used to define mappings for iwyu. See the IWYU tool at
|
||||||
|
<http://code.google.com/p/include-what-you-use/>.
|
||||||
|
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
There are a unit tests using the Catch Unit Test Framework in the `test`
|
||||||
|
directory and some data tests in `test/osm-testdata`. They are built by the
|
||||||
|
default cmake config. Run `ctest` to run them. Many more tests are needed.
|
||||||
|
|
||||||
|
|
||||||
|
## Documenting the code
|
||||||
|
|
||||||
|
All namespaces, classes, functions, attributes, etc. should be documented.
|
||||||
|
|
||||||
|
Osmium uses the Doxygen (www.doxygen.org) source code documentation system.
|
||||||
|
If it is installed, the CMake configuration will add a new build target, so
|
||||||
|
you can build it with `make doc`.
|
||||||
|
|
233
EXTERNAL_LICENSES.txt
Normal file
233
EXTERNAL_LICENSES.txt
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
|
||||||
|
==== For protozero from https://github.com/mapbox/protozero
|
||||||
|
|
||||||
|
protozero copyright (c) Mapbox.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
==== For protozero from https://github.com/mapbox/protozero
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
==== For utf8.h
|
||||||
|
|
||||||
|
Copyright 2006 Nemanja Trifunovic
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
23
LICENSE.txt
Normal file
23
LICENSE.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
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.
|
25
Makefile
Normal file
25
Makefile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
all:
|
||||||
|
mkdir -p build && cd build && cmake .. && $(MAKE)
|
||||||
|
|
||||||
|
doc:
|
||||||
|
mkdir -p build && cd build && cmake .. && $(MAKE) doc
|
||||||
|
|
||||||
|
clean:
|
||||||
|
if test -d build; then cd build && $(MAKE) clean; fi
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
rm -fr build
|
||||||
|
|
||||||
|
#deb:
|
||||||
|
# debuild -I -us -uc
|
||||||
|
#
|
||||||
|
#deb-clean:
|
||||||
|
# debuild clean
|
||||||
|
|
||||||
|
indent:
|
||||||
|
astyle --style=java --indent-namespaces --indent-switches --pad-header --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp
|
||||||
|
# astyle --style=java --indent-namespaces --indent-switches --pad-header --unpad-paren --align-pointer=type --lineend=linux --suffix=none --recursive include/\*.hpp examples/\*.cpp test/\*.cpp
|
||||||
|
|
||||||
|
.PHONY: clean distclean deb deb-clean doc indent
|
||||||
|
|
114
README.md
Normal file
114
README.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Libosmium
|
||||||
|
|
||||||
|
http://osmcode.org/libosmium
|
||||||
|
|
||||||
|
A fast and flexible C++ library for working with OpenStreetMap data.
|
||||||
|
|
||||||
|
[](https://travis-ci.org/osmcode/libosmium)
|
||||||
|
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||||
|
|
||||||
|
Libosmium is developed on Linux, but also works on OSX and Windows (with some
|
||||||
|
limitations).
|
||||||
|
|
||||||
|
There are a few applications that use the Osmium library in the examples
|
||||||
|
directory. See the [osmium-contrib](http://github.com/osmcode/osmium-contrib)
|
||||||
|
repository for more example code.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Because Libosmium uses many C++11 features you need a modern compiler and
|
||||||
|
standard C++ library. Osmium needs at least GCC 4.8 or clang (LLVM) 3.4.
|
||||||
|
(Some parts may work with older versions.)
|
||||||
|
|
||||||
|
Different parts of Libosmium (and the applications built on top of it) need
|
||||||
|
different libraries. You DO NOT NEED to install all of them, just install those
|
||||||
|
you need for your programs.
|
||||||
|
|
||||||
|
For details see the
|
||||||
|
[list of dependencies](https://github.com/osmcode/libosmium/wiki/Libosmium-dependencies).
|
||||||
|
|
||||||
|
The following external (header-only) libraries are included in the libosmium
|
||||||
|
repository:
|
||||||
|
* [gdalcpp](https://github.com/joto/gdalcpp)
|
||||||
|
* [protozero](https://github.com/mapbox/protozero)
|
||||||
|
* [utfcpp](http://utfcpp.sourceforge.net/)
|
||||||
|
|
||||||
|
If you want (some of) those libraries to be installed along with libosmium
|
||||||
|
itself when calling `make install`, you have to use the CMake options
|
||||||
|
`INSTALL_GDALCPP`, `INSTALL_PROTOZERO`, and/or `INSTALL_UTFCPP`.
|
||||||
|
|
||||||
|
|
||||||
|
## Directories
|
||||||
|
|
||||||
|
* benchmarks: Some benchmarks checking different parts of Libosmium.
|
||||||
|
|
||||||
|
* cmake: CMake configuration scripts.
|
||||||
|
|
||||||
|
* doc: Config for documentation.
|
||||||
|
|
||||||
|
* examples: Osmium example applications.
|
||||||
|
|
||||||
|
* include: C/C++ include files. All of Libosmium is in those header files
|
||||||
|
which are needed for building Osmium applications.
|
||||||
|
|
||||||
|
* test: Tests (see below).
|
||||||
|
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Osmium is a header-only library, so there is nothing to build for the
|
||||||
|
library itself.
|
||||||
|
|
||||||
|
But there are some tests and examples that can be build. Libosmium uses
|
||||||
|
cmake:
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
|
||||||
|
This will build the examples and tests. Call `ctest` to run the tests.
|
||||||
|
|
||||||
|
For more see the
|
||||||
|
[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Building-Libosmium).
|
||||||
|
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
See the
|
||||||
|
[Libosmium Wiki](https://github.com/osmcode/libosmium/wiki/Testing-Libosmium)
|
||||||
|
for instructions.
|
||||||
|
|
||||||
|
|
||||||
|
## Osmium on 32bit Machines
|
||||||
|
|
||||||
|
Osmium works well on 64 bit machines, but on 32 bit machines there are some
|
||||||
|
problems. Be aware that not everything will work on 32 bit architectures.
|
||||||
|
This is mostly due to the 64 bit needed for node IDs. Also Osmium hasn't been
|
||||||
|
tested well on 32 bit systems. Here are some issues you might run into:
|
||||||
|
|
||||||
|
* Google Sparsehash does not work on 32 bit machines in our use case.
|
||||||
|
* The `mmap` system call is called with a `size_t` argument, so it can't
|
||||||
|
give you more than 4GByte of memory on 32 bit systems. This might be a
|
||||||
|
problem.
|
||||||
|
|
||||||
|
Please report any issues you have and we might be able to solve them.
|
||||||
|
|
||||||
|
|
||||||
|
## Switching from the old Osmium
|
||||||
|
|
||||||
|
If you have been using the old version of Osmium at
|
||||||
|
https://github.com/joto/osmium you might want to read about the
|
||||||
|
[changes needed](https://github.com/osmcode/libosmium/wiki/Changes-from-old-versions-of-Osmium).
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Libosmium is available under the Boost Software License. See LICENSE.txt.
|
||||||
|
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
Libosmium was mainly written and is maintained by Jochen Topf
|
||||||
|
(jochen@topf.org). See the git commit log for other authors.
|
||||||
|
|
109
appveyor.yml
Normal file
109
appveyor.yml
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Configuration for continuous integration service at appveyor.com
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- config: Dev
|
||||||
|
- config: RelWithDebInfo
|
||||||
|
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
# Operating system (build VM template)
|
||||||
|
os: Visual Studio 2015
|
||||||
|
|
||||||
|
# scripts that are called at very beginning, before repo cloning
|
||||||
|
init:
|
||||||
|
|
||||||
|
# clone directory
|
||||||
|
clone_folder: c:\projects\libosmium
|
||||||
|
|
||||||
|
platform: x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
# show all available env vars
|
||||||
|
- set
|
||||||
|
- echo cmake on AppVeyor
|
||||||
|
- cmake -version
|
||||||
|
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||||
|
- set PATH=c:\projects\libosmium\cmake-3.1.0-win32-x86\bin;%PATH%
|
||||||
|
- set LODEPSDIR=c:\projects\libosmium\libosmium-deps
|
||||||
|
- set PROJ_LIB=%LODEPSDIR%\proj\share
|
||||||
|
- set GDAL_DATA=%LODEPSDIR%\gdal\data
|
||||||
|
#geos.dll
|
||||||
|
- set PATH=%LODEPSDIR%\geos\lib;%PATH%
|
||||||
|
#gdal.dll
|
||||||
|
- set PATH=%LODEPSDIR%\gdal\lib;%PATH%
|
||||||
|
#libexpat.dll
|
||||||
|
- set PATH=%LODEPSDIR%\expat\lib;%PATH%
|
||||||
|
#libtiff.dll
|
||||||
|
- set PATH=%LODEPSDIR%\libtiff\lib;%PATH%
|
||||||
|
#jpeg.dll
|
||||||
|
- set PATH=%LODEPSDIR%\jpeg\lib;%PATH%
|
||||||
|
#zlibwapi.dll
|
||||||
|
- set PATH=%LODEPSDIR%\zlib\lib;%PATH%
|
||||||
|
#convert backslashes in bzip2 path to forward slashes
|
||||||
|
#cmake cannot find it otherwise
|
||||||
|
- set LIBBZIP2=%LODEPSDIR%\bzip2\lib\libbz2.lib
|
||||||
|
- set LIBBZIP2=%LIBBZIP2:\=/%
|
||||||
|
- ps: Start-FileDownload https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/cmake-3.1.0-win32-x86.7z -FileName cm.7z
|
||||||
|
- ps: Start-FileDownload https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/libosmium-deps-win-14.0-x64.7z -FileName lodeps.7z
|
||||||
|
- 7z x cm.7z | %windir%\system32\find "ing archive"
|
||||||
|
- 7z x lodeps.7z | %windir%\system32\find "ing archive"
|
||||||
|
- echo %LODEPSDIR%
|
||||||
|
- dir %LODEPSDIR%
|
||||||
|
- echo our own cmake
|
||||||
|
- cmake -version
|
||||||
|
- cd c:\projects
|
||||||
|
- git clone --depth 1 https://github.com/osmcode/osm-testdata.git
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- cd c:\projects\libosmium
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- echo %config%
|
||||||
|
# This will produce lots of LNK4099 warnings which can be ignored.
|
||||||
|
# Unfortunately they can't be disabled, see
|
||||||
|
# http://stackoverflow.com/questions/661606/visual-c-how-to-disable-specific-linker-warnings
|
||||||
|
- cmake -LA -G "Visual Studio 14 Win64"
|
||||||
|
-DOsmium_DEBUG=TRUE
|
||||||
|
-DCMAKE_BUILD_TYPE=%config%
|
||||||
|
-DBUILD_HEADERS=OFF
|
||||||
|
-DBOOST_ROOT=%LODEPSDIR%\boost
|
||||||
|
-DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_58.lib
|
||||||
|
-DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib
|
||||||
|
-DBZIP2_LIBRARY_RELEASE=%LIBBZIP2%
|
||||||
|
-DCMAKE_PREFIX_PATH=%LODEPSDIR%\zlib;%LODEPSDIR%\expat;%LODEPSDIR%\bzip2;%LODEPSDIR%\geos;%LODEPSDIR%\gdal;%LODEPSDIR%\proj;%LODEPSDIR%\sparsehash;%LODEPSDIR%\wingetopt
|
||||||
|
..
|
||||||
|
- msbuild libosmium.sln /p:Configuration=%config% /toolsversion:14.0 /p:Platform=x64 /p:PlatformToolset=v140
|
||||||
|
#- cmake .. -LA -G "NMake Makefiles"
|
||||||
|
# -DOsmium_DEBUG=TRUE
|
||||||
|
# -DCMAKE_BUILD_TYPE=%config%
|
||||||
|
# -DBOOST_ROOT=%LODEPSDIR%\boost
|
||||||
|
# -DBoost_PROGRAM_OPTIONS_LIBRARY=%LODEPSDIR%\boost\lib\libboost_program_options-vc140-mt-1_57.lib
|
||||||
|
# -DZLIB_LIBRARY=%LODEPSDIR%\zlib\lib\zlibwapi.lib
|
||||||
|
# -DZLIB_INCLUDE_DIR=%LODEPSDIR%\zlib\include
|
||||||
|
# -DEXPAT_LIBRARY=%LODEPSDIR%\expat\lib\libexpat.lib
|
||||||
|
# -DEXPAT_INCLUDE_DIR=%LODEPSDIR%\expat\include
|
||||||
|
# -DBZIP2_LIBRARIES=%LIBBZIP2%
|
||||||
|
# -DBZIP2_INCLUDE_DIR=%LODEPSDIR%\bzip2\include
|
||||||
|
# -DGDAL_LIBRARY=%LODEPSDIR%\gdal\lib\gdal_i.lib
|
||||||
|
# -DGDAL_INCLUDE_DIR=%LODEPSDIR%\gdal\include
|
||||||
|
# -DGEOS_LIBRARY=%LODEPSDIR%\geos\lib\geos.lib
|
||||||
|
# -DGEOS_INCLUDE_DIR=%LODEPSDIR%\geos\include
|
||||||
|
# -DPROJ_LIBRARY=%LODEPSDIR%\proj\lib\proj.lib
|
||||||
|
# -DPROJ_INCLUDE_DIR=%LODEPSDIR%\proj\include
|
||||||
|
# -DSPARSEHASH_INCLUDE_DIR=%LODEPSDIR%\sparsehash\include
|
||||||
|
# -DGETOPT_LIBRARY=%LODEPSDIR%\wingetopt\lib\wingetopt.lib
|
||||||
|
# -DGETOPT_INCLUDE_DIR=%LODEPSDIR%\wingetopt\include
|
||||||
|
#- nmake
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
# "-E testdata-overview" exempts one test we know fails on Appveyor
|
||||||
|
# because we currently don't have spatialite support.
|
||||||
|
- ctest --output-on-failure
|
||||||
|
-C %config%
|
||||||
|
-E testdata-overview
|
||||||
|
|
49
benchmarks/CMakeLists.txt
Normal file
49
benchmarks/CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Libosmium benchmarks
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
message(STATUS "Configuring benchmarks")
|
||||||
|
|
||||||
|
set(BENCHMARKS
|
||||||
|
count
|
||||||
|
count_tag
|
||||||
|
index_map
|
||||||
|
static_vs_dynamic_index
|
||||||
|
write_pbf
|
||||||
|
CACHE STRING "Benchmark programs"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Configure benchmarks
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
message(STATUS "Configuring benchmarks - Building these benchmarks:")
|
||||||
|
foreach(benchmark ${BENCHMARKS})
|
||||||
|
message(STATUS " - osmium_benchmark_${benchmark}")
|
||||||
|
add_executable(osmium_benchmark_${benchmark}
|
||||||
|
"osmium_benchmark_${benchmark}.cpp")
|
||||||
|
target_link_libraries(osmium_benchmark_${benchmark}
|
||||||
|
${OSMIUM_IO_LIBRARIES}
|
||||||
|
${BENCHMARK_LIBS_${benchmark}})
|
||||||
|
configure_file(run_benchmark_${benchmark}.sh
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/run_benchmark_${benchmark}.sh
|
||||||
|
@ONLY)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(file setup run_benchmarks)
|
||||||
|
configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Configuring benchmarks - done")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
41
benchmarks/README.md
Normal file
41
benchmarks/README.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
# Benchmarks
|
||||||
|
|
||||||
|
Benchmarks check the performance of different parts of Libosmium.
|
||||||
|
|
||||||
|
## Preparations
|
||||||
|
|
||||||
|
To run the benchmarks first make a directory for the data files somewhere
|
||||||
|
(outside the repository) and set the `DATA_DIR` environment variable:
|
||||||
|
|
||||||
|
export DATA_DIR=benchmark_data
|
||||||
|
mkdir $DATA_DIR
|
||||||
|
|
||||||
|
Then copy the OSM files you want to do the benchmarks with into this directory.
|
||||||
|
You can use the `download_data.sh` script to download a selection of OSM files
|
||||||
|
in different sizes, but you can use a different selection, too. The benchmarks
|
||||||
|
will use whatever files you have in the `DATA_DIR` directory.
|
||||||
|
|
||||||
|
The download script will start the data files names with a number in order of
|
||||||
|
the size of the file from smallest to largest. You can use the same convention
|
||||||
|
or use a different one. Benchmarks will be run on the files in alphabetical
|
||||||
|
order.
|
||||||
|
|
||||||
|
The files don't have to be in that directory, you can add soft links from that
|
||||||
|
directory to the real file locations if that suits you.
|
||||||
|
|
||||||
|
## Compiling the benchmarks
|
||||||
|
|
||||||
|
To build the benchmarks set the `BUILD_BENCHMARKS` option when configuring with
|
||||||
|
CMake and run the compilation by calling `make` (or whatever build tool you
|
||||||
|
are using).
|
||||||
|
|
||||||
|
## Running the benchmarks
|
||||||
|
|
||||||
|
Go to the build directory and run `benchmarks/run_benchmarks.sh`. You can also
|
||||||
|
run each benchmark on its own by calling the respective script in the
|
||||||
|
`benchmarks` directory.
|
||||||
|
|
||||||
|
Results of the benchmarks will be printed to stdout, you might want to redirect
|
||||||
|
them into a file.
|
||||||
|
|
12
benchmarks/download_data.sh
Executable file
12
benchmarks/download_data.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# download_data.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
cd $DATA_DIR
|
||||||
|
curl --location --output 1_liechtenstein.osm.pbf http://download.geofabrik.de/europe/liechtenstein-latest.osm.pbf # about 1 MB
|
||||||
|
curl --location --output 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 13 MB
|
||||||
|
curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 120 MB
|
||||||
|
curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 2 GB
|
||||||
|
curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 26 GB
|
||||||
|
|
53
benchmarks/osmium_benchmark_count.cpp
Normal file
53
benchmarks/osmium_benchmark_count.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
struct CountHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
uint64_t nodes = 0;
|
||||||
|
uint64_t ways = 0;
|
||||||
|
uint64_t relations = 0;
|
||||||
|
|
||||||
|
void node(osmium::Node&) {
|
||||||
|
++nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(osmium::Way&) {
|
||||||
|
++ways;
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(osmium::Relation&) {
|
||||||
|
++relations;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename = argv[1];
|
||||||
|
|
||||||
|
osmium::io::Reader reader(input_filename);
|
||||||
|
|
||||||
|
CountHandler handler;
|
||||||
|
osmium::apply(reader, handler);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
std::cout << "Nodes: " << handler.nodes << "\n";
|
||||||
|
std::cout << "Ways: " << handler.ways << "\n";
|
||||||
|
std::cout << "Relations: " << handler.relations << "\n";
|
||||||
|
}
|
||||||
|
|
54
benchmarks/osmium_benchmark_count_tag.cpp
Normal file
54
benchmarks/osmium_benchmark_count_tag.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
struct CountHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
uint64_t counter = 0;
|
||||||
|
uint64_t all = 0;
|
||||||
|
|
||||||
|
void node(osmium::Node& node) {
|
||||||
|
++all;
|
||||||
|
const char* amenity = node.tags().get_value_by_key("amenity");
|
||||||
|
if (amenity && !strcmp(amenity, "post_box")) {
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(osmium::Way&) {
|
||||||
|
++all;
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(osmium::Relation&) {
|
||||||
|
++all;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename = argv[1];
|
||||||
|
|
||||||
|
osmium::io::Reader reader(input_filename);
|
||||||
|
|
||||||
|
CountHandler handler;
|
||||||
|
osmium::apply(reader, handler);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << "\n";
|
||||||
|
}
|
||||||
|
|
39
benchmarks/osmium_benchmark_index_map.cpp
Normal file
39
benchmarks/osmium_benchmark_index_map.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/index/map/all.hpp>
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
|
||||||
|
typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> index_type;
|
||||||
|
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<index_type> location_handler_type;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE FORMAT\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename = argv[1];
|
||||||
|
std::string location_store = argv[2];
|
||||||
|
|
||||||
|
osmium::io::Reader reader(input_filename);
|
||||||
|
|
||||||
|
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
|
||||||
|
std::unique_ptr<index_type> index = map_factory.create_map(location_store);
|
||||||
|
location_handler_type location_handler(*index);
|
||||||
|
location_handler.ignore_errors();
|
||||||
|
|
||||||
|
osmium::apply(reader, location_handler);
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
135
benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp
Normal file
135
benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This benchmarks compares the run time for statically vs. dynamically
|
||||||
|
configured index maps. You can configure index maps at compile-time using
|
||||||
|
typedefs or at run-time using polymorphism.
|
||||||
|
|
||||||
|
This will read the input file into a buffer and then run the
|
||||||
|
NodeLocationForWays handler multiple times over the complete data. The
|
||||||
|
number of runs depends on the size of the input, but is never smaller
|
||||||
|
than 10.
|
||||||
|
|
||||||
|
Do not run this with very large input files! It will need about 10 times
|
||||||
|
as much RAM as the file size of the input file.
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <osmium/index/map/all.hpp>
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
|
||||||
|
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> static_index_type;
|
||||||
|
const std::string location_store="sparse_mem_array";
|
||||||
|
|
||||||
|
typedef osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location> dynamic_index_type;
|
||||||
|
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<static_index_type> static_location_handler_type;
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<dynamic_index_type> dynamic_location_handler_type;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename = argv[1];
|
||||||
|
|
||||||
|
osmium::memory::Buffer buffer = osmium::io::read_file(input_filename);
|
||||||
|
|
||||||
|
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance();
|
||||||
|
|
||||||
|
const auto buffer_size = buffer.committed() / (1024*1024); // buffer size in MBytes
|
||||||
|
const int runs = std::max(10, static_cast<int>(5000ull / buffer_size));
|
||||||
|
|
||||||
|
std::cout << "input: filename=" << input_filename << " buffer_size=" << buffer_size << "MBytes\n";
|
||||||
|
std::cout << "runs: " << runs << "\n";
|
||||||
|
|
||||||
|
double static_min = std::numeric_limits<double>::max();
|
||||||
|
double static_sum = 0;
|
||||||
|
double static_max = 0;
|
||||||
|
|
||||||
|
double dynamic_min = std::numeric_limits<double>::max();
|
||||||
|
double dynamic_sum = 0;
|
||||||
|
double dynamic_max = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < runs; ++i) {
|
||||||
|
|
||||||
|
{
|
||||||
|
// static index
|
||||||
|
osmium::memory::Buffer tmp_buffer(buffer.committed());
|
||||||
|
for (const auto& item : buffer) {
|
||||||
|
tmp_buffer.add_item(item);
|
||||||
|
tmp_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
static_index_type static_index;
|
||||||
|
static_location_handler_type static_location_handler(static_index);
|
||||||
|
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
osmium::apply(tmp_buffer, static_location_handler);
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
double duration = std::chrono::duration<double, std::milli>(end-start).count();
|
||||||
|
|
||||||
|
if (duration < static_min) static_min = duration;
|
||||||
|
if (duration > static_max) static_max = duration;
|
||||||
|
static_sum += duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// dynamic index
|
||||||
|
osmium::memory::Buffer tmp_buffer(buffer.committed());
|
||||||
|
for (const auto& item : buffer) {
|
||||||
|
tmp_buffer.add_item(item);
|
||||||
|
tmp_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<dynamic_index_type> index = map_factory.create_map(location_store);
|
||||||
|
dynamic_location_handler_type dynamic_location_handler(*index);
|
||||||
|
dynamic_location_handler.ignore_errors();
|
||||||
|
|
||||||
|
auto start = std::chrono::steady_clock::now();
|
||||||
|
osmium::apply(tmp_buffer, dynamic_location_handler);
|
||||||
|
auto end = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
double duration = std::chrono::duration<double, std::milli>(end-start).count();
|
||||||
|
|
||||||
|
if (duration < dynamic_min) dynamic_min = duration;
|
||||||
|
if (duration > dynamic_max) dynamic_max = duration;
|
||||||
|
dynamic_sum += duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double static_avg = static_sum/runs;
|
||||||
|
double dynamic_avg = dynamic_sum/runs;
|
||||||
|
|
||||||
|
std::cout << "static min=" << static_min << "ms avg=" << static_avg << "ms max=" << static_max << "ms\n";
|
||||||
|
std::cout << "dynamic min=" << dynamic_min << "ms avg=" << dynamic_avg << "ms max=" << dynamic_max << "ms\n";
|
||||||
|
|
||||||
|
double rfactor = 100.0;
|
||||||
|
double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor;
|
||||||
|
double diff_avg = std::round((dynamic_avg - static_avg) * rfactor) / rfactor;
|
||||||
|
double diff_max = std::round((dynamic_max - static_max) * rfactor) / rfactor;
|
||||||
|
|
||||||
|
double prfactor = 10.0;
|
||||||
|
double percent_min = std::round((100.0 * diff_min / static_min) * prfactor) / prfactor;
|
||||||
|
double percent_avg = std::round((100.0 * diff_avg / static_avg) * prfactor) / prfactor;
|
||||||
|
double percent_max = std::round((100.0 * diff_max / static_max) * prfactor) / prfactor;
|
||||||
|
|
||||||
|
std::cout << "difference:";
|
||||||
|
std::cout << " min=" << diff_min << "ms (" << percent_min << "%)";
|
||||||
|
std::cout << " avg=" << diff_avg << "ms (" << percent_avg << "%)";
|
||||||
|
std::cout << " max=" << diff_max << "ms (" << percent_max << "%)\n";
|
||||||
|
}
|
||||||
|
|
34
benchmarks/osmium_benchmark_write_pbf.cpp
Normal file
34
benchmarks/osmium_benchmark_write_pbf.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The code in this file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/io/any_output.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " INPUT-FILE OUTPUT-FILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename = argv[1];
|
||||||
|
std::string output_filename = argv[2];
|
||||||
|
|
||||||
|
osmium::io::Reader reader(input_filename);
|
||||||
|
osmium::io::File output_file(output_filename, "pbf");
|
||||||
|
osmium::io::Header header;
|
||||||
|
osmium::io::Writer writer(output_file, header, osmium::io::overwrite::allow);
|
||||||
|
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
writer(std::move(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
22
benchmarks/run_benchmark_count.sh
Executable file
22
benchmarks/run_benchmark_count.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_count.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=count
|
||||||
|
|
||||||
|
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||||
|
|
||||||
|
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||||
|
|
||||||
|
echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options"
|
||||||
|
for data in $OB_DATA_FILES; do
|
||||||
|
filename=`basename $data`
|
||||||
|
filesize=`stat --format="%s" --dereference $data`
|
||||||
|
for n in $OB_SEQ; do
|
||||||
|
$OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
22
benchmarks/run_benchmark_count_tag.sh
Executable file
22
benchmarks/run_benchmark_count_tag.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_count_tag.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=count_tag
|
||||||
|
|
||||||
|
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||||
|
|
||||||
|
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||||
|
|
||||||
|
echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options"
|
||||||
|
for data in $OB_DATA_FILES; do
|
||||||
|
filename=`basename $data`
|
||||||
|
filesize=`stat --format="%s" --dereference $data`
|
||||||
|
for n in $OB_SEQ; do
|
||||||
|
$OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
27
benchmarks/run_benchmark_index_map.sh
Executable file
27
benchmarks/run_benchmark_index_map.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_index_map.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=index_map
|
||||||
|
|
||||||
|
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||||
|
|
||||||
|
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||||
|
|
||||||
|
#MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array dense_mem_array dense_mmap_array dense_file_array"
|
||||||
|
MAPS="sparse_mem_map sparse_mem_table sparse_mem_array sparse_mmap_array sparse_file_array"
|
||||||
|
|
||||||
|
echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options"
|
||||||
|
for data in $OB_DATA_FILES; do
|
||||||
|
filename=`basename $data`
|
||||||
|
filesize=`stat --format="%s" --dereference $data`
|
||||||
|
for map in $MAPS; do
|
||||||
|
for n in $OB_SEQ; do
|
||||||
|
$OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data $map 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
21
benchmarks/run_benchmark_static_vs_dynamic_index.sh
Executable file
21
benchmarks/run_benchmark_static_vs_dynamic_index.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_static_vs_dynamic_index.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=static_vs_dynamic_index
|
||||||
|
|
||||||
|
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||||
|
|
||||||
|
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||||
|
|
||||||
|
for data in $OB_DATA_FILES; do
|
||||||
|
filesize=`stat --format="%s" --dereference $data`
|
||||||
|
if [ $filesize -lt 500000000 ]; then
|
||||||
|
echo "========================"
|
||||||
|
$CMD $data
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
28
benchmarks/run_benchmark_write_pbf.sh
Executable file
28
benchmarks/run_benchmark_write_pbf.sh
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmark_write_pbf.sh
|
||||||
|
#
|
||||||
|
# Will read the input file and after reading it into memory completely,
|
||||||
|
# write it to /dev/null. Because this will need the time to read *and* write
|
||||||
|
# the file, it will report the times for reading and writing. You can
|
||||||
|
# subtract the times needed for the "count" benchmark to (roughly) get the
|
||||||
|
# write times.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BENCHMARK_NAME=write_pbf
|
||||||
|
|
||||||
|
. @CMAKE_BINARY_DIR@/benchmarks/setup.sh
|
||||||
|
|
||||||
|
CMD=$OB_DIR/osmium_benchmark_$BENCHMARK_NAME
|
||||||
|
|
||||||
|
echo "# file size num mem time cpu_kernel cpu_user cpu_percent cmd options"
|
||||||
|
for data in $OB_DATA_FILES; do
|
||||||
|
filename=`basename $data`
|
||||||
|
filesize=`stat --format="%s" --dereference $data`
|
||||||
|
for n in $OB_SEQ; do
|
||||||
|
$OB_TIME_CMD -f "$filename $filesize $n $OB_TIME_FORMAT" $CMD $data /dev/null 2>&1 >/dev/null | sed -e "s%$DATA_DIR/%%" | sed -e "s%$OB_DIR/%%"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
15
benchmarks/run_benchmarks.sh
Executable file
15
benchmarks/run_benchmarks.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# run_benchmarks.sh
|
||||||
|
#
|
||||||
|
# Run all benchmarks.
|
||||||
|
#
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
for benchmark in @CMAKE_BINARY_DIR@/benchmarks/run_benchmark_*.sh; do
|
||||||
|
name=`basename $benchmark`
|
||||||
|
echo "Running $name..."
|
||||||
|
$benchmark
|
||||||
|
done
|
||||||
|
|
34
benchmarks/setup.sh
Executable file
34
benchmarks/setup.sh
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# setup.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
if [ -z $DATA_DIR ]; then
|
||||||
|
echo "Please set DATA_DIR environment variable before running benchmark"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OB_DIR=@CMAKE_BINARY_DIR@/benchmarks
|
||||||
|
|
||||||
|
OB_RUNS=3
|
||||||
|
OB_SEQ=`seq -s' ' 1 $OB_RUNS`
|
||||||
|
|
||||||
|
OB_TIME_CMD=/usr/bin/time
|
||||||
|
OB_TIME_FORMAT="%M %e %S %U %P %C"
|
||||||
|
|
||||||
|
OB_DATA_FILES=`find -L $DATA_DIR -mindepth 1 -maxdepth 1 -type f | sort`
|
||||||
|
|
||||||
|
echo "BENCHMARK: $BENCHMARK_NAME"
|
||||||
|
echo "---------------------"
|
||||||
|
echo "CPU:"
|
||||||
|
grep '^model name' /proc/cpuinfo | tail -1
|
||||||
|
grep '^cpu MHz' /proc/cpuinfo | tail -1
|
||||||
|
grep '^cpu cores' /proc/cpuinfo | tail -1
|
||||||
|
grep '^siblings' /proc/cpuinfo | tail -1
|
||||||
|
|
||||||
|
echo "---------------------"
|
||||||
|
echo "MEMORY:"
|
||||||
|
free
|
||||||
|
echo "---------------------"
|
||||||
|
echo "RESULTS:"
|
||||||
|
|
153
cmake/FindGem.cmake
Normal file
153
cmake/FindGem.cmake
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
# Author thomas.roehr@dfki.de
|
||||||
|
#
|
||||||
|
# Version 0.3 2013-07-02
|
||||||
|
# - rely on `gem content` to find library and header
|
||||||
|
# - introduce GEM_OS_PKG to allow search via pkgconfig
|
||||||
|
# Version 0.2 2010-01-14
|
||||||
|
# - add support for searching for multiple gems
|
||||||
|
# Version 0.1 2010-12-15
|
||||||
|
# - support basic search functionality
|
||||||
|
# - tested to find rice
|
||||||
|
#
|
||||||
|
# OUTPUT:
|
||||||
|
#
|
||||||
|
# GEM_INCLUDE_DIRS After successful search contains the include directores
|
||||||
|
#
|
||||||
|
# GEM_LIBRARIES After successful search contains the full path of each found library
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# set(GEM_DEBUG TRUE)
|
||||||
|
# find_package(Gem COMPONENTS rice hoe)
|
||||||
|
# include_directories(${GEM_INCLUDE_DIRS})
|
||||||
|
# target_link_libraries(${GEM_LIBRARIES}
|
||||||
|
#
|
||||||
|
# in case pkg-config should be used to search for the os pkg, set GEM_OS_PKG, i.e.
|
||||||
|
# set(GEM_OS_PKG TRUE)
|
||||||
|
#
|
||||||
|
# Check for how 'gem' should be called
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_program(GEM_EXECUTABLE
|
||||||
|
NAMES "gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}"
|
||||||
|
"gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}"
|
||||||
|
"gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}"
|
||||||
|
"gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}"
|
||||||
|
"gem${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}"
|
||||||
|
"gem${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}"
|
||||||
|
"gem-${RUBY_VERSION_MAJOR}${RUBY_VERSION_MINOR}${RUBY_VERSION_PATCH}"
|
||||||
|
"gem-${RUBY_VERSION_MAJOR}.${RUBY_VERSION_MINOR}.${RUBY_VERSION_PATCH}"
|
||||||
|
"gem")
|
||||||
|
|
||||||
|
# Making backward compatible
|
||||||
|
if(Gem_DEBUG)
|
||||||
|
set(GEM_DEBUG TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT GEM_EXECUTABLE)
|
||||||
|
MESSAGE(FATAL_ERROR "Could not find the gem executable - install 'gem' first")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT Gem_FIND_COMPONENTS)
|
||||||
|
MESSAGE(FATAL_ERROR "If searching for a Gem you have to provide COMPONENTS with the name of the gem")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
foreach(Gem_NAME ${Gem_FIND_COMPONENTS})
|
||||||
|
set(GEM_${Gem_NAME}_FOUND TRUE)
|
||||||
|
list(APPEND components_found_vars GEM_${Gem_NAME}_FOUND)
|
||||||
|
# If the gem is installed as a gem
|
||||||
|
if(NOT GEM_OS_PKG)
|
||||||
|
set(GEM_HOME ENV{GEM_HOME})
|
||||||
|
|
||||||
|
# Use `gem content <gem-name>` to extract current information about installed gems
|
||||||
|
# Store the information into ${GEM_LOCAL_INFO}
|
||||||
|
EXECUTE_PROCESS(COMMAND ${GEM_EXECUTABLE} content ${Gem_NAME}
|
||||||
|
RESULT_VARIABLE GEM_RUN_RESULT
|
||||||
|
OUTPUT_VARIABLE GEM_LOCAL_INFO)
|
||||||
|
|
||||||
|
if(GEM_RUN_RESULT STREQUAL "0")
|
||||||
|
list(APPEND FOUND_GEMS ${Gem_NAME})
|
||||||
|
set(_library_NAME_PATTERN lib${Gem_NAME}.a
|
||||||
|
lib${Gem_NAME}.so
|
||||||
|
lib${Gem_NAME}.dylib
|
||||||
|
${Gem_NAME}.a
|
||||||
|
${Gem_NAME}.so
|
||||||
|
${Gem_NAME}.dylib
|
||||||
|
.*.a
|
||||||
|
.*.so
|
||||||
|
.*.dylib
|
||||||
|
)
|
||||||
|
|
||||||
|
set(_header_SUFFIX_PATTERN
|
||||||
|
.h
|
||||||
|
.hh
|
||||||
|
.hpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a list from the output results of the gem command
|
||||||
|
string(REPLACE "\n" ";" GEM_CONTENT_LIST "${GEM_LOCAL_INFO}")
|
||||||
|
foreach(_gem_CONTENT_PATH ${GEM_CONTENT_LIST})
|
||||||
|
|
||||||
|
# Convert so that only '/' Unix path separator are being using
|
||||||
|
# needed to do proper regex matching
|
||||||
|
FILE(TO_CMAKE_PATH ${_gem_CONTENT_PATH} gem_CONTENT_PATH)
|
||||||
|
|
||||||
|
# Identify library -- checking for a library in the gems 'lib' (sub)directory
|
||||||
|
# Search for an existing library, but only within the gems folder
|
||||||
|
foreach(_library_NAME ${_library_NAME_PATTERN})
|
||||||
|
STRING(REGEX MATCH ".*${Gem_NAME}.*/lib/.*${_library_NAME}$" GEM_PATH_INFO "${gem_CONTENT_PATH}")
|
||||||
|
if(NOT "${GEM_PATH_INFO}" STREQUAL "")
|
||||||
|
list(APPEND GEM_LIBRARIES ${GEM_PATH_INFO})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Identify headers
|
||||||
|
# Checking for available headers in an include directory
|
||||||
|
foreach(_header_PATTERN ${_header_SUFFIX_PATTERN})
|
||||||
|
STRING(REGEX MATCH ".*${Gem_NAME}.*/include/.*${_header_PATTERN}$" GEM_PATH_INFO "${gem_CONTENT_PATH}")
|
||||||
|
if(NOT "${GEM_PATH_INFO}" STREQUAL "")
|
||||||
|
STRING(REGEX REPLACE "(.*${Gem_NAME}.*/include/).*${_header_PATTERN}$" "\\1" GEM_PATH_INFO "${gem_CONTENT_PATH}")
|
||||||
|
list(APPEND GEM_INCLUDE_DIRS ${GEM_PATH_INFO})
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
else()
|
||||||
|
set(GEM_${Gem_NAME}_FOUND FALSE)
|
||||||
|
endif()
|
||||||
|
else(NOT GEM_OS_PKG)
|
||||||
|
pkg_check_modules(GEM_PKG ${Gem_NAME})
|
||||||
|
set(GEM_${GEM_NAME}_FOUND GEM_PKG_FOUND)
|
||||||
|
set(GEM_INCLUDE_DIRS ${GEM_PKG_INCLUDE_DIRS})
|
||||||
|
set(GEM_LIBRARIES ${GEM_PKG_LIBRARIES} ${GEM_PKG_STATIC_LIBRARIES})
|
||||||
|
list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS} ${GEM_PKG_STATIC_LDFLAGS})
|
||||||
|
list(APPEND GEM_LIBRARIES ${GEM_PKG_LDFLAGS_OTHER} ${GEM_PKG_STATIC_LDFLAGS_OTHER})
|
||||||
|
|
||||||
|
if(GEM_DEBUG)
|
||||||
|
message(STATUS "GEM_OS_PKG is defined")
|
||||||
|
message(STATUS "GEM_INCLUDE_DIRS ${GEM_INCLUDE_DIRS}")
|
||||||
|
message(STATUS "GEM_STATIC_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}")
|
||||||
|
message(STATUS "GEM_LIBRARY_DIRS ${GEM_PKG_STATIC_LIBRARY_DIRS}")
|
||||||
|
message(STATUS "GEM_STATIC_LIBRARIES ${GEM_PKG_STATIC_LIBRARIES}")
|
||||||
|
message(STATUS "GEM_LIBRARIES ${GEM_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(GEM_DEBUG)
|
||||||
|
message(STATUS "${Gem_NAME} library dir: ${GEM_LIBRARIES}")
|
||||||
|
message(STATUS "${Gem_NAME} include dir: ${GEM_INCLUDE_DIRS}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Compact the lists
|
||||||
|
if(DEFINED GEM_LIBRARIES)
|
||||||
|
LIST(REMOVE_DUPLICATES GEM_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
if(DEFINED GEM_INCLUDE_DIRS)
|
||||||
|
LIST(REMOVE_DUPLICATES GEM_INCLUDE_DIRS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(GEM
|
||||||
|
REQUIRED_VARS ${components_found_vars}
|
||||||
|
FAIL_MESSAGE "Could not find all required gems")
|
||||||
|
|
318
cmake/FindOsmium.cmake
Normal file
318
cmake/FindOsmium.cmake
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# FindOsmium.cmake
|
||||||
|
#
|
||||||
|
# Find the Libosmium headers and, optionally, several components needed for
|
||||||
|
# different Libosmium functions.
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
#
|
||||||
|
# Copy this file somewhere into your project directory, where cmake can
|
||||||
|
# find it. Usually this will be a directory called "cmake" which you can
|
||||||
|
# add to the CMake module search path with the following line in your
|
||||||
|
# CMakeLists.txt:
|
||||||
|
#
|
||||||
|
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
#
|
||||||
|
# Then add the following in your CMakeLists.txt:
|
||||||
|
#
|
||||||
|
# find_package(Osmium REQUIRED COMPONENTS <XXX>)
|
||||||
|
# include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||||
|
#
|
||||||
|
# For the <XXX> substitute a space separated list of one or more of the
|
||||||
|
# following components:
|
||||||
|
#
|
||||||
|
# pbf - include libraries needed for PBF input and output
|
||||||
|
# xml - include libraries needed for XML input and output
|
||||||
|
# io - include libraries needed for any type of input/output
|
||||||
|
# geos - include if you want to use any of the GEOS functions
|
||||||
|
# gdal - include if you want to use any of the OGR functions
|
||||||
|
# proj - include if you want to use any of the Proj.4 functions
|
||||||
|
# sparsehash - include if you use the sparsehash index
|
||||||
|
#
|
||||||
|
# You can check for success with something like this:
|
||||||
|
#
|
||||||
|
# if(NOT OSMIUM_FOUND)
|
||||||
|
# message(WARNING "Libosmium not found!\n")
|
||||||
|
# endif()
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Variables:
|
||||||
|
#
|
||||||
|
# OSMIUM_FOUND - True if Osmium found.
|
||||||
|
# OSMIUM_INCLUDE_DIRS - Where to find include files.
|
||||||
|
# OSMIUM_XML_LIBRARIES - Libraries needed for XML I/O.
|
||||||
|
# OSMIUM_PBF_LIBRARIES - Libraries needed for PBF I/O.
|
||||||
|
# OSMIUM_IO_LIBRARIES - Libraries needed for XML or PBF I/O.
|
||||||
|
# OSMIUM_LIBRARIES - All libraries Osmium uses somewhere.
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Look for the header file.
|
||||||
|
find_path(OSMIUM_INCLUDE_DIR osmium/osm.hpp
|
||||||
|
PATH_SUFFIXES include
|
||||||
|
PATHS
|
||||||
|
../libosmium
|
||||||
|
~/Library/Frameworks
|
||||||
|
/Library/Frameworks
|
||||||
|
/opt/local # DarwinPorts
|
||||||
|
/opt
|
||||||
|
)
|
||||||
|
|
||||||
|
set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Check for optional components
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
if(Osmium_FIND_COMPONENTS)
|
||||||
|
foreach(_component ${Osmium_FIND_COMPONENTS})
|
||||||
|
string(TOUPPER ${_component} _component_uppercase)
|
||||||
|
set(Osmium_USE_${_component_uppercase} TRUE)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'io' is an alias for 'pbf' and 'xml'
|
||||||
|
if(Osmium_USE_IO)
|
||||||
|
set(Osmium_USE_PBF TRUE)
|
||||||
|
set(Osmium_USE_XML TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'ogr' is an alias for 'gdal'
|
||||||
|
if(Osmium_USE_OGR)
|
||||||
|
set(Osmium_USE_GDAL TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'pbf'
|
||||||
|
if(Osmium_USE_PBF)
|
||||||
|
find_package(ZLIB)
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND)
|
||||||
|
if(ZLIB_FOUND AND Threads_FOUND)
|
||||||
|
list(APPEND OSMIUM_PBF_LIBRARIES
|
||||||
|
${ZLIB_LIBRARIES}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
)
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
|
||||||
|
endif()
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||||
|
${ZLIB_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'xml'
|
||||||
|
if(Osmium_USE_XML)
|
||||||
|
find_package(EXPAT)
|
||||||
|
find_package(BZip2)
|
||||||
|
find_package(ZLIB)
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS EXPAT_FOUND BZIP2_FOUND ZLIB_FOUND Threads_FOUND)
|
||||||
|
if(EXPAT_FOUND AND BZIP2_FOUND AND ZLIB_FOUND AND Threads_FOUND)
|
||||||
|
list(APPEND OSMIUM_XML_LIBRARIES
|
||||||
|
${EXPAT_LIBRARIES}
|
||||||
|
${BZIP2_LIBRARIES}
|
||||||
|
${ZLIB_LIBRARIES}
|
||||||
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
)
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||||
|
${EXPAT_INCLUDE_DIR}
|
||||||
|
${BZIP2_INCLUDE_DIR}
|
||||||
|
${ZLIB_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: Can not find some libraries for XML input/output, please install them or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
list(APPEND OSMIUM_IO_LIBRARIES
|
||||||
|
${OSMIUM_PBF_LIBRARIES}
|
||||||
|
${OSMIUM_XML_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_LIBRARIES
|
||||||
|
${OSMIUM_IO_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'geos'
|
||||||
|
if(Osmium_USE_GEOS)
|
||||||
|
find_path(GEOS_INCLUDE_DIR geos/geom.h)
|
||||||
|
find_library(GEOS_LIBRARY NAMES geos)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS GEOS_INCLUDE_DIR GEOS_LIBRARY)
|
||||||
|
if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY)
|
||||||
|
SET(GEOS_FOUND 1)
|
||||||
|
list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY})
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR})
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'gdal' (alias 'ogr')
|
||||||
|
if(Osmium_USE_GDAL)
|
||||||
|
find_package(GDAL)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS GDAL_FOUND)
|
||||||
|
if(GDAL_FOUND)
|
||||||
|
list(APPEND OSMIUM_LIBRARIES ${GDAL_LIBRARIES})
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS ${GDAL_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: GDAL library is required but not found, please install it or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'proj'
|
||||||
|
if(Osmium_USE_PROJ)
|
||||||
|
find_path(PROJ_INCLUDE_DIR proj_api.h)
|
||||||
|
find_library(PROJ_LIBRARY NAMES proj)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS PROJ_INCLUDE_DIR PROJ_LIBRARY)
|
||||||
|
if(PROJ_INCLUDE_DIR AND PROJ_LIBRARY)
|
||||||
|
set(PROJ_FOUND 1)
|
||||||
|
list(APPEND OSMIUM_LIBRARIES ${PROJ_LIBRARY})
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS ${PROJ_INCLUDE_DIR})
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: PROJ.4 library is required but not found, please install it or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# Component 'sparsehash'
|
||||||
|
if(Osmium_USE_SPARSEHASH)
|
||||||
|
find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable)
|
||||||
|
|
||||||
|
list(APPEND OSMIUM_EXTRA_FIND_VARS SPARSEHASH_INCLUDE_DIR)
|
||||||
|
if(SPARSEHASH_INCLUDE_DIR)
|
||||||
|
# Find size of sparsetable::size_type. This does not work on older
|
||||||
|
# CMake versions because they can do this check only in C, not in C++.
|
||||||
|
if (NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
|
||||||
|
set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
|
||||||
|
check_type_size("google::sparsetable<int>::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX)
|
||||||
|
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||||
|
set(CMAKE_REQUIRED_INCLUDES)
|
||||||
|
else()
|
||||||
|
set(SPARSETABLE_SIZE_TYPE ${CMAKE_SIZEOF_VOID_P})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Sparsetable::size_type must be at least 8 bytes (64bit), otherwise
|
||||||
|
# OSM object IDs will not fit.
|
||||||
|
if(SPARSETABLE_SIZE_TYPE GREATER 7)
|
||||||
|
set(SPARSEHASH_FOUND 1)
|
||||||
|
add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND})
|
||||||
|
list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR})
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
if(OSMIUM_XML_LIBRARIES)
|
||||||
|
list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OSMIUM_PBF_LIBRARIES)
|
||||||
|
list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OSMIUM_IO_LIBRARIES)
|
||||||
|
list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OSMIUM_LIBRARIES)
|
||||||
|
list(REMOVE_DUPLICATES OSMIUM_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Check that all required libraries are available
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
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)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Add compiler flags
|
||||||
|
#
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_definitions(-wd4996)
|
||||||
|
|
||||||
|
# Disable warning C4068: "unknown pragma" because we want it to ignore
|
||||||
|
# pragmas for other compilers.
|
||||||
|
add_definitions(-wd4068)
|
||||||
|
|
||||||
|
# Disable warning C4715: "not all control paths return a value" because
|
||||||
|
# it generates too many false positives.
|
||||||
|
add_definitions(-wd4715)
|
||||||
|
|
||||||
|
# Disable warning C4351: new behavior: elements of array '...' will be
|
||||||
|
# default initialized. The new behaviour is correct and we don't support
|
||||||
|
# old compilers anyway.
|
||||||
|
add_definitions(-wd4351)
|
||||||
|
|
||||||
|
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
# following only available from cmake 2.8.12:
|
||||||
|
# add_compile_options(-stdlib=libc++)
|
||||||
|
# so using this instead:
|
||||||
|
add_definitions(-stdlib=libc++)
|
||||||
|
set(LDFLAGS ${LDFLAGS} -stdlib=libc++)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
# This is a set of recommended warning options that can be added when compiling
|
||||||
|
# libosmium code.
|
||||||
|
if(MSVC)
|
||||||
|
set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium")
|
||||||
|
else()
|
||||||
|
set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast" CACHE STRING "Recommended warning options for libosmium")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal")
|
||||||
|
|
||||||
|
if(Osmium_DEBUG)
|
||||||
|
message(STATUS "OSMIUM_XML_LIBRARIES=" ${OSMIUM_XML_LIBRARIES})
|
||||||
|
message(STATUS "OSMIUM_PBF_LIBRARIES=" ${OSMIUM_PBF_LIBRARIES})
|
||||||
|
message(STATUS "OSMIUM_IO_LIBRARIES=" ${OSMIUM_IO_LIBRARIES})
|
||||||
|
message(STATUS "OSMIUM_LIBRARIES=" ${OSMIUM_LIBRARIES})
|
||||||
|
message(STATUS "OSMIUM_INCLUDE_DIRS=" ${OSMIUM_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
3
cmake/README
Normal file
3
cmake/README
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
FindGem.cmake from https://github.com/rock-core/base-cmake
|
||||||
|
|
15
cmake/build.bat
Normal file
15
cmake/build.bat
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
call "%VS120COMNTOOLS%\..\..\VC\vcvarsall.bat" x86_amd64
|
||||||
|
set CMAKE_PREFIX_PATH=C:\PROJ
|
||||||
|
set VERSION=Debug
|
||||||
|
set TESTS=ON
|
||||||
|
set ALLHPPS=ON
|
||||||
|
set PREFIX=d:\libs18d
|
||||||
|
set BOOST_ROOT=d:\boost
|
||||||
|
|
||||||
|
cmake .. -G "Visual Studio 12 Win64" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=%PREFIX% -DBOOST_ROOT=%BOOST_ROOT% -DBoost_USE_STATIC_LIBS=ON -DBUILD_TESTING=%TESTS% -DBUILD_TRY_HPPS=%ALLHPPS$ -T CTP_Nov2013
|
||||||
|
msbuild /clp:Verbosity=minimal /nologo libosmium.sln /flp1:logfile=build_errors.txt;errorsonly /flp2:logfile=build_warnings.txt;warningsonly
|
||||||
|
set PATH=%PATH%;%PREFIX%/bin
|
||||||
|
|
||||||
|
del test\osm-testdata\*.db
|
||||||
|
del test\osm-testdata\*.json
|
||||||
|
if "%TESTS%"=="ON" ctest -VV >build_tests.log
|
43
cmake/iwyu.sh
Executable file
43
cmake/iwyu.sh
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# This will run IWYU (Include What You Use) on includes files. The iwyu
|
||||||
|
# program isn't very reliable and crashes often, but is still useful.
|
||||||
|
#
|
||||||
|
# TODO: This script should be integrated with cmake in some way...
|
||||||
|
#
|
||||||
|
|
||||||
|
cmdline="iwyu -Xiwyu --mapping_file=osmium.imp -std=c++11 -I include"
|
||||||
|
|
||||||
|
log=build/iwyu.log
|
||||||
|
|
||||||
|
mkdir -p build/check_reports
|
||||||
|
|
||||||
|
echo "INCLUDE WHAT YOU USE REPORT:" >$log
|
||||||
|
|
||||||
|
allok=yes
|
||||||
|
|
||||||
|
for file in `find include/osmium -name \*.hpp | sort`; do
|
||||||
|
mkdir -p `dirname build/check_reports/$file`
|
||||||
|
ifile="build/check_reports/${file%.hpp}.iwyu"
|
||||||
|
$cmdline $file >$ifile 2>&1
|
||||||
|
if grep -q 'has correct #includes/fwd-decls' ${ifile}; then
|
||||||
|
echo "\n\033[1m\033[32m========\033[0m \033[1m${file}\033[0m" >>$log
|
||||||
|
echo "[OK] ${file}"
|
||||||
|
elif grep -q 'Assertion failed' ${ifile}; then
|
||||||
|
echo "\n\033[1m======== ${file}\033[0m" >>$log
|
||||||
|
echo "[--] ${file}"
|
||||||
|
allok=no
|
||||||
|
else
|
||||||
|
echo "\n\033[1m\033[31m========\033[0m \033[1m${file}\033[0m" >>$log
|
||||||
|
echo "[ ] ${file}"
|
||||||
|
allok=no
|
||||||
|
fi
|
||||||
|
cat $ifile >>$log
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$allok" = "yes" ]; then
|
||||||
|
echo "All files OK"
|
||||||
|
else
|
||||||
|
echo "There were errors"
|
||||||
|
fi
|
||||||
|
|
33
doc/CMakeLists.txt
Normal file
33
doc/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Libosmium documentation
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
message(STATUS "Configuring documentation")
|
||||||
|
|
||||||
|
message(STATUS "Looking for doxygen")
|
||||||
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
if(DOXYGEN_FOUND)
|
||||||
|
message(STATUS "Looking for doxygen - found")
|
||||||
|
configure_file(header.html ${CMAKE_CURRENT_BINARY_DIR}/header.html @ONLY)
|
||||||
|
configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
||||||
|
add_custom_target(doc
|
||||||
|
${DOXYGEN_EXECUTABLE}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
COMMENT "Generating API documentation with Doxygen" VERBATIM
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
message(STATUS "Looking for doxygen - not found")
|
||||||
|
message(STATUS " Disabled making of documentation.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Configuring documentation - done")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
2313
doc/Doxyfile.in
Normal file
2313
doc/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
8
doc/README.md
Normal file
8
doc/README.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
The `header.html` is created with:
|
||||||
|
|
||||||
|
`doxygen -w html header.html footer.html stylesheet.css`
|
||||||
|
|
||||||
|
This might have to be run again for newer Doxygen versions. After that add
|
||||||
|
changes back in.
|
||||||
|
|
26
doc/doc.txt
Normal file
26
doc/doc.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* @mainpage
|
||||||
|
*
|
||||||
|
* Osmium is a fast and flexible C++ library for working with OpenStreetMap
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* This is the API documentation that was automatically created from the
|
||||||
|
* source code. For more information about the Osmium Library see
|
||||||
|
* http://osmcode.org/libosmium .
|
||||||
|
*
|
||||||
|
* Osmium is free software and available under the Boost Software License.
|
||||||
|
* The source code is available at https://github.com/osmcode/libosmium .
|
||||||
|
*
|
||||||
|
* Osmium is a header-only library. You do not need to compile and link it,
|
||||||
|
* just include the headers you need.
|
||||||
|
*
|
||||||
|
* Everything in namespaces called "detail" is for internal Osmium use only,
|
||||||
|
* do not depend on it in your code. Do not include any include files in
|
||||||
|
* directories named "detail" directly. Include files in directories called
|
||||||
|
* "experimental" and everything in namespaces called "experimental" is
|
||||||
|
* unsupported and may change at any time regardless of the status of the rest
|
||||||
|
* of the library.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
56
doc/header.html
Normal file
56
doc/header.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<!-- HTML header for doxygen 1.8.8-->
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||||
|
<meta name="generator" content="Doxygen $doxygenversion"/>
|
||||||
|
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
|
||||||
|
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
|
||||||
|
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
|
||||||
|
<script type="text/javascript" src="$relpath^jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="$relpath^dynsections.js"></script>
|
||||||
|
$treeview
|
||||||
|
$search
|
||||||
|
$mathjax
|
||||||
|
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
|
||||||
|
$extrastylesheet
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||||||
|
|
||||||
|
<!--BEGIN TITLEAREA-->
|
||||||
|
<div id="titlearea">
|
||||||
|
<table cellspacing="0" cellpadding="0">
|
||||||
|
<tbody>
|
||||||
|
<tr style="height: 56px;">
|
||||||
|
<!--BEGIN PROJECT_LOGO-->
|
||||||
|
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
|
||||||
|
<!--END PROJECT_LOGO-->
|
||||||
|
<!--BEGIN PROJECT_NAME-->
|
||||||
|
<td style="padding-left: 0.5em;">
|
||||||
|
<div id="projectname">$projectname
|
||||||
|
<!--BEGIN PROJECT_NUMBER--> <span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
|
||||||
|
</div>
|
||||||
|
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
|
||||||
|
</td>
|
||||||
|
<!--END PROJECT_NAME-->
|
||||||
|
<!--BEGIN !PROJECT_NAME-->
|
||||||
|
<!--BEGIN PROJECT_BRIEF-->
|
||||||
|
<td style="padding-left: 0.5em;">
|
||||||
|
<div id="projectbrief">$projectbrief</div>
|
||||||
|
</td>
|
||||||
|
<!--END PROJECT_BRIEF-->
|
||||||
|
<!--END !PROJECT_NAME-->
|
||||||
|
<!--BEGIN DISABLE_INDEX-->
|
||||||
|
<!--BEGIN SEARCHENGINE-->
|
||||||
|
<td>$searchbox</td>
|
||||||
|
<!--END SEARCHENGINE-->
|
||||||
|
<!--END DISABLE_INDEX-->
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<!--END TITLEAREA-->
|
||||||
|
<!-- end header part -->
|
22
doc/osmium.css
Normal file
22
doc/osmium.css
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
body {
|
||||||
|
font-family: "Droid Sans",Helvetica,Arial,sans-serif;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #202060;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs, .tabs2, .tabs3, .navpath ul, .tablist li {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs, .tabs2, .tabs3 {
|
||||||
|
border-top: 1px solid #202060;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.contents {
|
||||||
|
margin: 0px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
92
examples/CMakeLists.txt
Normal file
92
examples/CMakeLists.txt
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# CMake Config
|
||||||
|
#
|
||||||
|
# Libosmium examples
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
message(STATUS "Configuring examples")
|
||||||
|
|
||||||
|
set(EXAMPLES
|
||||||
|
area_test
|
||||||
|
convert
|
||||||
|
count
|
||||||
|
create_node_cache
|
||||||
|
debug
|
||||||
|
filter_discussions
|
||||||
|
index
|
||||||
|
read
|
||||||
|
serdump
|
||||||
|
use_node_cache
|
||||||
|
CACHE STRING "Example programs"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Examples depending on wingetopt
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
set(GETOPT_EXAMPLES area_test convert serdump)
|
||||||
|
if(NOT GETOPT_MISSING)
|
||||||
|
foreach(example ${GETOPT_EXAMPLES})
|
||||||
|
list(APPEND EXAMPLE_LIBS_${example} ${GETOPT_LIBRARY})
|
||||||
|
endforeach()
|
||||||
|
else()
|
||||||
|
message(STATUS "Configuring examples - Skipping examples because on Visual Studio the wingetopt library is needed and was not found:")
|
||||||
|
foreach(example ${GETOPT_EXAMPLES})
|
||||||
|
message(STATUS " - osmium_${example}")
|
||||||
|
list(REMOVE_ITEM EXAMPLES ${example})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Examples depending on SparseHash
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
if(NOT SPARSEHASH_FOUND)
|
||||||
|
list(REMOVE_ITEM EXAMPLES area_test)
|
||||||
|
message(STATUS "Configuring examples - Skipping examples because Google SparseHash not found:")
|
||||||
|
message(STATUS " - osmium_area_test")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Examples depending on Boost Program Options
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
unset(Boost_LIBRARIES)
|
||||||
|
unset(Boost_FOUND)
|
||||||
|
find_package(Boost 1.38 COMPONENTS program_options)
|
||||||
|
|
||||||
|
if(Boost_PROGRAM_OPTIONS_FOUND)
|
||||||
|
list(APPEND EXAMPLE_LIBS_index ${Boost_PROGRAM_OPTIONS_LIBRARY})
|
||||||
|
else()
|
||||||
|
list(REMOVE_ITEM EXAMPLES index)
|
||||||
|
message(STATUS "Configuring examples - Skipping examples because Boost program_options not found:")
|
||||||
|
message(STATUS " - osmium_index")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Configure examples
|
||||||
|
#
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Configuring examples - Building these examples:")
|
||||||
|
foreach(example ${EXAMPLES})
|
||||||
|
message(STATUS " - osmium_${example}")
|
||||||
|
add_executable(osmium_${example} "osmium_${example}.cpp")
|
||||||
|
target_link_libraries(osmium_${example} ${OSMIUM_IO_LIBRARIES} ${EXAMPLE_LIBS_${example}})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
message(STATUS "Configuring examples - done")
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
136
examples/osmium_area_test.cpp
Normal file
136
examples/osmium_area_test.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is an example tool that creates multipolygons from OSM data
|
||||||
|
and dumps them to stdout.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <osmium/area/assembler.hpp>
|
||||||
|
#include <osmium/area/multipolygon_collector.hpp>
|
||||||
|
#include <osmium/dynamic_handler.hpp>
|
||||||
|
#include <osmium/geom/wkt.hpp>
|
||||||
|
#include <osmium/handler/dump.hpp>
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/index/map/dummy.hpp>
|
||||||
|
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
|
||||||
|
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
|
||||||
|
|
||||||
|
class WKTDump : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
osmium::geom::WKTFactory<> m_factory ;
|
||||||
|
|
||||||
|
std::ostream& m_out;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WKTDump(std::ostream& out) :
|
||||||
|
m_out(out) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(const osmium::Area& area) {
|
||||||
|
try {
|
||||||
|
m_out << m_factory.create_multipolygon(area) << "\n";
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
m_out << "GEOMETRY ERROR: " << e.what() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class WKTDump
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
std::cout << "osmium_area_test [OPTIONS] OSMFILE\n\n"
|
||||||
|
<< "Read OSMFILE and build multipolygons from it.\n"
|
||||||
|
<< "\nOptions:\n"
|
||||||
|
<< " -h, --help This help message\n"
|
||||||
|
<< " -w, --dump-wkt Dump area geometries as WKT\n"
|
||||||
|
<< " -o, --dump-objects Dump area objects\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"dump-wkt", no_argument, 0, 'w'},
|
||||||
|
{"dump-objects", no_argument, 0, 'o'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
osmium::handler::DynamicHandler handler;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int c = getopt_long(argc, argv, "hwo", long_options, 0);
|
||||||
|
if (c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
case 'w':
|
||||||
|
handler.set<WKTDump>(std::cout);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
handler.set<osmium::handler::Dump>(std::cout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining_args = argc - optind;
|
||||||
|
if (remaining_args != 1) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::File infile(argv[optind]);
|
||||||
|
|
||||||
|
osmium::area::Assembler::config_type assembler_config;
|
||||||
|
osmium::area::MultipolygonCollector<osmium::area::Assembler> collector(assembler_config);
|
||||||
|
|
||||||
|
std::cerr << "Pass 1...\n";
|
||||||
|
osmium::io::Reader reader1(infile, osmium::osm_entity_bits::relation);
|
||||||
|
collector.read_relations(reader1);
|
||||||
|
reader1.close();
|
||||||
|
std::cerr << "Pass 1 done\n";
|
||||||
|
|
||||||
|
std::cerr << "Memory:\n";
|
||||||
|
collector.used_memory();
|
||||||
|
|
||||||
|
index_pos_type index_pos;
|
||||||
|
index_neg_type index_neg;
|
||||||
|
location_handler_type location_handler(index_pos, index_neg);
|
||||||
|
location_handler.ignore_errors(); // XXX
|
||||||
|
|
||||||
|
std::cerr << "Pass 2...\n";
|
||||||
|
osmium::io::Reader reader2(infile);
|
||||||
|
osmium::apply(reader2, location_handler, collector.handler([&handler](osmium::memory::Buffer&& buffer) {
|
||||||
|
osmium::apply(buffer, handler);
|
||||||
|
}));
|
||||||
|
reader2.close();
|
||||||
|
std::cerr << "Pass 2 done\n";
|
||||||
|
|
||||||
|
std::cerr << "Memory:\n";
|
||||||
|
collector.used_memory();
|
||||||
|
|
||||||
|
std::vector<const osmium::Relation*> incomplete_relations = collector.get_incomplete_relations();
|
||||||
|
if (!incomplete_relations.empty()) {
|
||||||
|
std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
|
||||||
|
for (const auto* relation : incomplete_relations) {
|
||||||
|
std::cerr << " " << relation->id();
|
||||||
|
}
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
111
examples/osmium_convert.cpp
Normal file
111
examples/osmium_convert.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Convert OSM files from one format into another.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
#include <osmium/io/any_output.hpp>
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
std::cout << "osmium_convert [OPTIONS] [INFILE [OUTFILE]]\n\n" \
|
||||||
|
<< "If INFILE or OUTFILE is not given stdin/stdout is assumed.\n" \
|
||||||
|
<< "File format is autodetected from file name suffix.\n" \
|
||||||
|
<< "Use -f and -t options to force file format.\n" \
|
||||||
|
<< "\nFile types:\n" \
|
||||||
|
<< " osm normal OSM file\n" \
|
||||||
|
<< " osc OSM change file\n" \
|
||||||
|
<< " osh OSM file with history information\n" \
|
||||||
|
<< "\nFile format:\n" \
|
||||||
|
<< " (default) XML encoding\n" \
|
||||||
|
<< " pbf binary PBF encoding\n" \
|
||||||
|
<< " opl OPL encoding\n" \
|
||||||
|
<< "\nFile compression\n" \
|
||||||
|
<< " gz compressed with gzip\n" \
|
||||||
|
<< " bz2 compressed with bzip2\n" \
|
||||||
|
<< "\nOptions:\n" \
|
||||||
|
<< " -h, --help This help message\n" \
|
||||||
|
<< " -f, --from-format=FORMAT Input format\n" \
|
||||||
|
<< " -t, --to-format=FORMAT Output format\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"from-format", required_argument, 0, 'f'},
|
||||||
|
{"to-format", required_argument, 0, 't'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string input_format;
|
||||||
|
std::string output_format;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int c = getopt_long(argc, argv, "dhf:t:", long_options, 0);
|
||||||
|
if (c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
case 'f':
|
||||||
|
input_format = optarg;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
output_format = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input;
|
||||||
|
std::string output;
|
||||||
|
int remaining_args = argc - optind;
|
||||||
|
if (remaining_args > 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
} else if (remaining_args == 2) {
|
||||||
|
input = argv[optind];
|
||||||
|
output = argv[optind+1];
|
||||||
|
} else if (remaining_args == 1) {
|
||||||
|
input = argv[optind];
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::File infile(input, input_format);
|
||||||
|
|
||||||
|
osmium::io::File outfile(output, output_format);
|
||||||
|
|
||||||
|
if (infile.has_multiple_object_versions() && !outfile.has_multiple_object_versions()) {
|
||||||
|
std::cerr << "Warning! You are converting from an OSM file with (potentially) several versions of the same object to one that is not marked as such.\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int exit_code = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
osmium::io::Reader reader(infile);
|
||||||
|
osmium::io::Header header = reader.header();
|
||||||
|
header.set("generator", "osmium_convert");
|
||||||
|
|
||||||
|
osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
writer(std::move(buffer));
|
||||||
|
}
|
||||||
|
writer.close();
|
||||||
|
reader.close();
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
std::cerr << e.what() << "\n";
|
||||||
|
exit_code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
56
examples/osmium_count.cpp
Normal file
56
examples/osmium_count.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a small tool that counts the number of nodes, ways, and relations in
|
||||||
|
the input file.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
struct CountHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
uint64_t nodes = 0;
|
||||||
|
uint64_t ways = 0;
|
||||||
|
uint64_t relations = 0;
|
||||||
|
|
||||||
|
void node(osmium::Node&) {
|
||||||
|
++nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(osmium::Way&) {
|
||||||
|
++ways;
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(osmium::Relation&) {
|
||||||
|
++relations;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::File infile(argv[1]);
|
||||||
|
osmium::io::Reader reader(infile);
|
||||||
|
|
||||||
|
CountHandler handler;
|
||||||
|
osmium::apply(reader, handler);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
std::cout << "Nodes: " << handler.nodes << "\n";
|
||||||
|
std::cout << "Ways: " << handler.ways << "\n";
|
||||||
|
std::cout << "Relations: " << handler.relations << "\n";
|
||||||
|
}
|
||||||
|
|
55
examples/osmium_create_node_cache.cpp
Normal file
55
examples/osmium_create_node_cache.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This reads an OSM file and writes out the node locations to a cache
|
||||||
|
file.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
#include <osmium/index/map/dummy.hpp>
|
||||||
|
#include <osmium/index/map/dense_mmap_array.hpp>
|
||||||
|
#include <osmium/index/map/dense_file_array.hpp>
|
||||||
|
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
|
||||||
|
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
|
||||||
|
typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
|
||||||
|
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename(argv[1]);
|
||||||
|
osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::node);
|
||||||
|
|
||||||
|
int fd = open(argv[2], O_RDWR | O_CREAT, 0666);
|
||||||
|
if (fd == -1) {
|
||||||
|
std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_pos_type index_pos {fd};
|
||||||
|
index_neg_type index_neg;
|
||||||
|
location_handler_type location_handler(index_pos, index_neg);
|
||||||
|
location_handler.ignore_errors();
|
||||||
|
|
||||||
|
osmium::apply(reader, location_handler);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
50
examples/osmium_debug.cpp
Normal file
50
examples/osmium_debug.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a small tool to dump the contents of the input file.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/handler/dump.hpp>
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
std::ios_base::sync_with_stdio(false);
|
||||||
|
|
||||||
|
if (argc < 2 || argc > 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE [TYPES]\n";
|
||||||
|
std::cerr << "TYPES can be any combination of 'n', 'w', 'r', and 'c' to indicate what types of OSM entities you want (default: all).\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all;
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
read_types = osmium::osm_entity_bits::nothing;
|
||||||
|
std::string types = argv[2];
|
||||||
|
if (types.find('n') != std::string::npos) read_types |= osmium::osm_entity_bits::node;
|
||||||
|
if (types.find('w') != std::string::npos) read_types |= osmium::osm_entity_bits::way;
|
||||||
|
if (types.find('r') != std::string::npos) read_types |= osmium::osm_entity_bits::relation;
|
||||||
|
if (types.find('c') != std::string::npos) read_types |= osmium::osm_entity_bits::changeset;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::Reader reader(argv[1], read_types);
|
||||||
|
osmium::io::Header header = reader.header();
|
||||||
|
|
||||||
|
std::cout << "HEADER:\n generator=" << header.get("generator") << "\n";
|
||||||
|
|
||||||
|
for (auto& bbox : header.boxes()) {
|
||||||
|
std::cout << " bbox=" << bbox << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::handler::Dump dump(std::cout);
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
osmium::apply(buffer, dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
72
examples/osmium_filter_discussions.cpp
Normal file
72
examples/osmium_filter_discussions.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Read OSM changesets with discussions from a changeset dump like the one
|
||||||
|
you get from http://planet.osm.org/planet/discussions-latest.osm.bz2
|
||||||
|
and write out only those changesets which have discussions (ie comments).
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <algorithm> // for std::copy_if
|
||||||
|
#include <iostream> // for std::cout, std::cerr
|
||||||
|
|
||||||
|
// we want to read OSM files in XML format
|
||||||
|
// (other formats don't support full changesets, so only XML is needed here)
|
||||||
|
#include <osmium/io/xml_input.hpp>
|
||||||
|
#include <osmium/io/input_iterator.hpp>
|
||||||
|
|
||||||
|
// we want to write OSM files in XML format
|
||||||
|
#include <osmium/io/xml_output.hpp>
|
||||||
|
#include <osmium/io/output_iterator.hpp>
|
||||||
|
|
||||||
|
// we want to support any compressioon (.gz2 and .bz2)
|
||||||
|
#include <osmium/io/any_compression.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cout << "Usage: " << argv[0] << " INFILE OUTFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The input file, deduce file format from file suffix
|
||||||
|
osmium::io::File infile(argv[1]);
|
||||||
|
|
||||||
|
// The output file, force class XML OSM file format
|
||||||
|
osmium::io::File outfile(argv[2], "osm");
|
||||||
|
|
||||||
|
// Initialize Reader for the input file.
|
||||||
|
// Read only changesets (will ignore nodes, ways, and
|
||||||
|
// relations if there are any).
|
||||||
|
osmium::io::Reader reader(infile, osmium::osm_entity_bits::changeset);
|
||||||
|
|
||||||
|
// Get the header from the input file
|
||||||
|
osmium::io::Header header = reader.header();
|
||||||
|
|
||||||
|
// Initialize writer for the output file. Use the header from the input
|
||||||
|
// file for the output file. This will copy over some header information.
|
||||||
|
// The last parameter will tell the writer that it is allowed to overwrite
|
||||||
|
// an existing file. Without it, it will refuse to do so.
|
||||||
|
osmium::io::Writer writer(outfile, header, osmium::io::overwrite::allow);
|
||||||
|
|
||||||
|
// Create range of input iterators that will iterator over all changesets
|
||||||
|
// delivered from input file through the "reader".
|
||||||
|
auto input_range = osmium::io::make_input_iterator_range<osmium::Changeset>(reader);
|
||||||
|
|
||||||
|
// Create an output iterator writing through the "writer" object to the
|
||||||
|
// output file.
|
||||||
|
auto output_iterator = osmium::io::make_output_iterator(writer);
|
||||||
|
|
||||||
|
// Copy all changesets from input to output that have at least one comment.
|
||||||
|
std::copy_if(input_range.begin(), input_range.end(), output_iterator, [](const osmium::Changeset& changeset) {
|
||||||
|
return changeset.num_comments() > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Explicitly close the writer and reader. Will throw an exception if
|
||||||
|
// there is a problem. If you wait for the destructor to close the writer
|
||||||
|
// and reader, you will not notice the problem, because destructors must
|
||||||
|
// not throw.
|
||||||
|
writer.close();
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
237
examples/osmium_index.cpp
Normal file
237
examples/osmium_index.cpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Example program to look at Osmium indexes on disk.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
#include <osmium/index/map/dense_file_array.hpp>
|
||||||
|
#include <osmium/index/map/sparse_file_array.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
template <typename TKey, typename TValue>
|
||||||
|
class IndexSearch {
|
||||||
|
|
||||||
|
typedef typename osmium::index::map::DenseFileArray<TKey, TValue> dense_index_type;
|
||||||
|
typedef typename osmium::index::map::SparseFileArray<TKey, TValue> sparse_index_type;
|
||||||
|
|
||||||
|
int m_fd;
|
||||||
|
bool m_dense_format;
|
||||||
|
|
||||||
|
void dump_dense() {
|
||||||
|
dense_index_type index(m_fd);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < index.size(); ++i) {
|
||||||
|
if (index.get(i) != TValue()) {
|
||||||
|
std::cout << i << " " << index.get(i) << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_sparse() {
|
||||||
|
sparse_index_type index(m_fd);
|
||||||
|
|
||||||
|
for (auto& element : index) {
|
||||||
|
std::cout << element.first << " " << element.second << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search_dense(TKey key) {
|
||||||
|
dense_index_type index(m_fd);
|
||||||
|
|
||||||
|
try {
|
||||||
|
TValue value = index.get(key);
|
||||||
|
std::cout << key << " " << value << std::endl;
|
||||||
|
} catch (...) {
|
||||||
|
std::cout << key << " not found" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search_sparse(TKey key) {
|
||||||
|
typedef typename sparse_index_type::element_type element_type;
|
||||||
|
sparse_index_type index(m_fd);
|
||||||
|
|
||||||
|
element_type elem {key, TValue()};
|
||||||
|
auto positions = std::equal_range(index.begin(), index.end(), elem, [](const element_type& lhs, const element_type& rhs) {
|
||||||
|
return lhs.first < rhs.first;
|
||||||
|
});
|
||||||
|
if (positions.first == positions.second) {
|
||||||
|
std::cout << key << " not found" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& it = positions.first; it != positions.second; ++it) {
|
||||||
|
std::cout << it->first << " " << it->second << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
IndexSearch(int fd, bool dense_format) :
|
||||||
|
m_fd(fd),
|
||||||
|
m_dense_format(dense_format) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump() {
|
||||||
|
if (m_dense_format) {
|
||||||
|
dump_dense();
|
||||||
|
} else {
|
||||||
|
dump_sparse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(TKey key) {
|
||||||
|
if (m_dense_format) {
|
||||||
|
return search_dense(key);
|
||||||
|
} else {
|
||||||
|
return search_sparse(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(std::vector<TKey> keys) {
|
||||||
|
bool found_all = true;
|
||||||
|
|
||||||
|
for (const auto key : keys) {
|
||||||
|
if (!search(key)) {
|
||||||
|
found_all = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_all;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IndexSearch
|
||||||
|
|
||||||
|
enum return_code : int {
|
||||||
|
okay = 0,
|
||||||
|
not_found = 1,
|
||||||
|
error = 2,
|
||||||
|
fatal = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
class Options {
|
||||||
|
|
||||||
|
po::variables_map vm;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Options(int argc, char* argv[]) {
|
||||||
|
try {
|
||||||
|
po::options_description desc("Allowed options");
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "Print this help message")
|
||||||
|
("array,a", po::value<std::string>(), "Read given index file in array format")
|
||||||
|
("list,l", po::value<std::string>(), "Read given index file in list format")
|
||||||
|
("dump,d", "Dump contents of index file to STDOUT")
|
||||||
|
("search,s", po::value<std::vector<osmium::unsigned_object_id_type>>(), "Search for given id (Option can appear multiple times)")
|
||||||
|
("type,t", po::value<std::string>(), "Type of value ('location' or 'offset')")
|
||||||
|
;
|
||||||
|
|
||||||
|
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||||
|
po::notify(vm);
|
||||||
|
|
||||||
|
if (vm.count("help")) {
|
||||||
|
std::cout << desc << "\n";
|
||||||
|
exit(return_code::okay);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("array") && vm.count("list")) {
|
||||||
|
std::cerr << "Only option --array or --list allowed." << std::endl;
|
||||||
|
exit(return_code::fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vm.count("array") && !vm.count("list")) {
|
||||||
|
std::cerr << "Need one of option --array or --list." << std::endl;
|
||||||
|
exit(return_code::fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vm.count("type")) {
|
||||||
|
std::cerr << "Need --type argument." << std::endl;
|
||||||
|
exit(return_code::fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& type = vm["type"].as<std::string>();
|
||||||
|
if (type != "location" && type != "offset") {
|
||||||
|
std::cerr << "Unknown type '" << type << "'. Must be 'location' or 'offset'." << std::endl;
|
||||||
|
exit(return_code::fatal);
|
||||||
|
}
|
||||||
|
} catch (boost::program_options::error& e) {
|
||||||
|
std::cerr << "Error parsing command line: " << e.what() << std::endl;
|
||||||
|
exit(return_code::fatal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& filename() const {
|
||||||
|
if (vm.count("array")) {
|
||||||
|
return vm["array"].as<std::string>();
|
||||||
|
} else {
|
||||||
|
return vm["list"].as<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dense_format() const {
|
||||||
|
return vm.count("array") != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_dump() const {
|
||||||
|
return vm.count("dump") != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<osmium::unsigned_object_id_type> search_keys() const {
|
||||||
|
return vm["search"].as<std::vector<osmium::unsigned_object_id_type>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool type_is(const char* type) const {
|
||||||
|
return vm["type"].as<std::string>() == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Options
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
std::ios_base::sync_with_stdio(false);
|
||||||
|
|
||||||
|
Options options(argc, argv);
|
||||||
|
|
||||||
|
std::cout << std::fixed << std::setprecision(7);
|
||||||
|
int fd = open(options.filename().c_str(), O_RDWR);
|
||||||
|
|
||||||
|
bool result_okay = true;
|
||||||
|
|
||||||
|
if (options.type_is("location")) {
|
||||||
|
IndexSearch<osmium::unsigned_object_id_type, osmium::Location> is(fd, options.dense_format());
|
||||||
|
|
||||||
|
if (options.do_dump()) {
|
||||||
|
is.dump();
|
||||||
|
} else {
|
||||||
|
result_okay = is.search(options.search_keys());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IndexSearch<osmium::unsigned_object_id_type, size_t> is(fd, options.dense_format());
|
||||||
|
|
||||||
|
if (options.do_dump()) {
|
||||||
|
is.dump();
|
||||||
|
} else {
|
||||||
|
result_okay = is.search(options.search_keys());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(result_okay ? return_code::okay : return_code::not_found);
|
||||||
|
}
|
||||||
|
|
30
examples/osmium_read.cpp
Normal file
30
examples/osmium_read.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a small tool that reads and discards the contents of the input file.
|
||||||
|
(Used for timing.)
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::File infile(argv[1]);
|
||||||
|
osmium::io::Reader reader(infile);
|
||||||
|
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
|
206
examples/osmium_serdump.cpp
Normal file
206
examples/osmium_serdump.cpp
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This is a small tool to dump the contents of the input file
|
||||||
|
in serialized format to stdout.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstring>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# include <direct.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
#include <osmium/handler/disk_store.hpp>
|
||||||
|
#include <osmium/handler/object_relations.hpp>
|
||||||
|
|
||||||
|
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||||
|
#include <osmium/index/multimap/sparse_mem_multimap.hpp>
|
||||||
|
#include <osmium/index/multimap/sparse_mem_array.hpp>
|
||||||
|
#include <osmium/index/multimap/hybrid.hpp>
|
||||||
|
|
||||||
|
// ==============================================================================
|
||||||
|
// Choose the following depending on the size of the input OSM files:
|
||||||
|
// ==============================================================================
|
||||||
|
// for smaller OSM files (extracts)
|
||||||
|
typedef osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
||||||
|
//typedef osmium::index::map::SparseMapMmap<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
||||||
|
//typedef osmium::index::map::SparseMapFile<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
||||||
|
|
||||||
|
typedef osmium::index::multimap::SparseMemArray<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
||||||
|
//typedef osmium::index::multimap::SparseMemMultimap<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
||||||
|
//typedef osmium::index::multimap::Hybrid<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type> map_type;
|
||||||
|
|
||||||
|
// ==============================================================================
|
||||||
|
// for very large OSM files (planet)
|
||||||
|
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, size_t> offset_index_type;
|
||||||
|
// ==============================================================================
|
||||||
|
|
||||||
|
void print_help() {
|
||||||
|
std::cout << "osmium_serdump OSMFILE DIR\n" \
|
||||||
|
<< "Serialize content of OSMFILE into data file in DIR.\n" \
|
||||||
|
<< "\nOptions:\n" \
|
||||||
|
<< " -h, --help This help message\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
std::ios_base::sync_with_stdio(false);
|
||||||
|
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int c = getopt_long(argc, argv, "h", long_options, 0);
|
||||||
|
if (c == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
print_help();
|
||||||
|
exit(0);
|
||||||
|
default:
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int remaining_args = argc - optind;
|
||||||
|
|
||||||
|
if (remaining_args != 2) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dir(argv[optind+1]);
|
||||||
|
#ifndef _WIN32
|
||||||
|
int result = ::mkdir(dir.c_str(), 0777);
|
||||||
|
#else
|
||||||
|
int result = mkdir(dir.c_str());
|
||||||
|
#endif
|
||||||
|
if (result == -1 && errno != EEXIST) {
|
||||||
|
std::cerr << "Problem creating directory '" << dir << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string data_file(dir + "/data.osm.ser");
|
||||||
|
int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (data_fd < 0) {
|
||||||
|
std::cerr << "Can't open data file '" << data_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_index_type node_index;
|
||||||
|
offset_index_type way_index;
|
||||||
|
offset_index_type relation_index;
|
||||||
|
|
||||||
|
osmium::handler::DiskStore disk_store_handler(data_fd, node_index, way_index, relation_index);
|
||||||
|
|
||||||
|
map_type map_node2way;
|
||||||
|
map_type map_node2relation;
|
||||||
|
map_type map_way2relation;
|
||||||
|
map_type map_relation2relation;
|
||||||
|
|
||||||
|
osmium::handler::ObjectRelations object_relations_handler(map_node2way, map_node2relation, map_way2relation, map_relation2relation);
|
||||||
|
|
||||||
|
osmium::io::Reader reader(argv[1]);
|
||||||
|
|
||||||
|
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||||
|
disk_store_handler(buffer); // XXX
|
||||||
|
osmium::apply(buffer, object_relations_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string index_file(dir + "/nodes.idx");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open nodes index file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
node_index.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string index_file(dir + "/ways.idx");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open ways index file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
way_index.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string index_file(dir + "/relations.idx");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open relations index file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
relation_index.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
map_node2way.sort();
|
||||||
|
std::string index_file(dir + "/node2way.map");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open node->way map file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
map_node2way.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
map_node2relation.sort();
|
||||||
|
std::string index_file(dir + "/node2rel.map");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open node->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
map_node2relation.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
map_way2relation.sort();
|
||||||
|
std::string index_file(dir + "/way2rel.map");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open way->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
map_way2relation.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
map_relation2relation.sort();
|
||||||
|
std::string index_file(dir + "/rel2rel.map");
|
||||||
|
int fd = ::open(index_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||||
|
if (fd < 0) {
|
||||||
|
std::cerr << "Can't open rel->rel map file '" << index_file << "': " << strerror(errno) << "\n";
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
map_relation2relation.dump_as_list(fd);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
68
examples/osmium_use_node_cache.cpp
Normal file
68
examples/osmium_use_node_cache.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
This reads ways from an OSM file and writes out the node locations
|
||||||
|
it got from a node cache generated with osmium_create_node_cache.
|
||||||
|
|
||||||
|
The code in this example file is released into the Public Domain.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <osmium/io/any_input.hpp>
|
||||||
|
|
||||||
|
#include <osmium/index/map/dummy.hpp>
|
||||||
|
#include <osmium/index/map/dense_file_array.hpp>
|
||||||
|
#include <osmium/index/map/dense_mmap_array.hpp>
|
||||||
|
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> index_neg_type;
|
||||||
|
//typedef osmium::index::map::DenseMmapArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
|
||||||
|
typedef osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location> index_pos_type;
|
||||||
|
|
||||||
|
typedef osmium::handler::NodeLocationsForWays<index_pos_type, index_neg_type> location_handler_type;
|
||||||
|
|
||||||
|
class MyHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void way(osmium::Way& way) {
|
||||||
|
for (auto& nr : way.nodes()) {
|
||||||
|
std::cout << nr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class MyHandler
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 3) {
|
||||||
|
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string input_filename(argv[1]);
|
||||||
|
osmium::io::Reader reader(input_filename, osmium::osm_entity_bits::way);
|
||||||
|
|
||||||
|
int fd = open(argv[2], O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
std::cerr << "Can not open node cache file '" << argv[2] << "': " << strerror(errno) << "\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_pos_type index_pos {fd};
|
||||||
|
index_neg_type index_neg;
|
||||||
|
location_handler_type location_handler(index_pos, index_neg);
|
||||||
|
location_handler.ignore_errors();
|
||||||
|
|
||||||
|
MyHandler handler;
|
||||||
|
osmium::apply(reader, location_handler, handler);
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
406
include/gdalcpp.hpp
Normal file
406
include/gdalcpp.hpp
Normal file
@ -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@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
|
787
include/osmium/area/assembler.hpp
Normal file
787
include/osmium/area/assembler.hpp
Normal file
@ -0,0 +1,787 @@
|
|||||||
|
#ifndef OSMIUM_AREA_ASSEMBLER_HPP
|
||||||
|
#define OSMIUM_AREA_ASSEMBLER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/area.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/tags/filter.hpp>
|
||||||
|
|
||||||
|
#include <osmium/area/detail/proto_ring.hpp>
|
||||||
|
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||||
|
#include <osmium/area/detail/segment_list.hpp>
|
||||||
|
#include <osmium/area/problem_reporter.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
using osmium::area::detail::ProtoRing;
|
||||||
|
|
||||||
|
struct AssemblerConfig {
|
||||||
|
|
||||||
|
osmium::area::ProblemReporter* problem_reporter;
|
||||||
|
|
||||||
|
// Enables debug output to stderr
|
||||||
|
bool debug;
|
||||||
|
|
||||||
|
explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d = false) :
|
||||||
|
problem_reporter(pr),
|
||||||
|
debug(d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable debug output to stderr. This is for Osmium
|
||||||
|
* developers only.
|
||||||
|
*/
|
||||||
|
void enable_debug_output(bool d = true) {
|
||||||
|
debug = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct AssemblerConfig
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles area objects from multipolygon relations and their
|
||||||
|
* members. This is called by the MultipolygonCollector object
|
||||||
|
* after all members have been collected.
|
||||||
|
*/
|
||||||
|
class Assembler {
|
||||||
|
|
||||||
|
const AssemblerConfig m_config;
|
||||||
|
|
||||||
|
// The way segments
|
||||||
|
osmium::area::detail::SegmentList m_segment_list;
|
||||||
|
|
||||||
|
// The rings we are building from the way segments
|
||||||
|
std::list<ProtoRing> m_rings;
|
||||||
|
|
||||||
|
std::vector<ProtoRing*> m_outer_rings;
|
||||||
|
std::vector<ProtoRing*> m_inner_rings;
|
||||||
|
|
||||||
|
int m_inner_outer_mismatches { 0 };
|
||||||
|
|
||||||
|
bool debug() const {
|
||||||
|
return m_config.debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given NodeRefs have the same location.
|
||||||
|
* Uses the actual location for the test, not the id. If both
|
||||||
|
* have the same location, but not the same id, a problem
|
||||||
|
* point will be added to the list of problem points.
|
||||||
|
*/
|
||||||
|
bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||||
|
if (nr1.location() != nr2.location()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (nr1.ref() != nr2.ref()) {
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
||||||
|
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||||
|
for (const osmium::Tag& tag : way.tags()) {
|
||||||
|
tl_builder.add_tag(tag.key(), tag.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
||||||
|
std::map<std::string, size_t> counter;
|
||||||
|
for (const osmium::Way* way : ways) {
|
||||||
|
for (const auto& tag : way->tags()) {
|
||||||
|
std::string kv {tag.key()};
|
||||||
|
kv.append(1, '\0');
|
||||||
|
kv.append(tag.value());
|
||||||
|
++counter[kv];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_ways = ways.size();
|
||||||
|
for (const auto& t_c : counter) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n";
|
||||||
|
}
|
||||||
|
if (t_c.second == num_ways) {
|
||||||
|
size_t len = std::strlen(t_c.first.c_str());
|
||||||
|
tl_builder.add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MPFilter : public osmium::tags::KeyFilter {
|
||||||
|
|
||||||
|
MPFilter() : osmium::tags::KeyFilter(true) {
|
||||||
|
add(false, "type");
|
||||||
|
add(false, "created_by");
|
||||||
|
add(false, "source");
|
||||||
|
add(false, "note");
|
||||||
|
add(false, "test:id");
|
||||||
|
add(false, "test:section");
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct MPFilter
|
||||||
|
|
||||||
|
static MPFilter& filter() {
|
||||||
|
static MPFilter filter;
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const {
|
||||||
|
const auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " use tags from relation\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// write out all tags except type=*
|
||||||
|
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||||
|
for (const osmium::Tag& tag : relation.tags()) {
|
||||||
|
if (strcmp(tag.key(), "type")) {
|
||||||
|
tl_builder.add_tag(tag.key(), tag.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " use tags from outer ways\n";
|
||||||
|
}
|
||||||
|
std::set<const osmium::Way*> ways;
|
||||||
|
for (const auto& ring : m_outer_rings) {
|
||||||
|
ring->get_ways(ways);
|
||||||
|
}
|
||||||
|
if (ways.size() == 1) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " only one outer way\n";
|
||||||
|
}
|
||||||
|
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||||
|
for (const osmium::Tag& tag : (*ways.begin())->tags()) {
|
||||||
|
tl_builder.add_tag(tag.key(), tag.value());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " multiple outer ways, get common tags\n";
|
||||||
|
}
|
||||||
|
osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
|
||||||
|
add_common_tags(tl_builder, ways);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go through all the rings and find rings that are not closed.
|
||||||
|
* Problems are reported through the problem reporter.
|
||||||
|
*
|
||||||
|
* @returns true if any rings were not closed, false otherwise
|
||||||
|
*/
|
||||||
|
bool check_for_open_rings() {
|
||||||
|
bool open_rings = false;
|
||||||
|
|
||||||
|
for (const auto& ring : m_rings) {
|
||||||
|
if (!ring.closed()) {
|
||||||
|
open_rings = true;
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->report_ring_not_closed(ring.get_node_ref_front().location(), ring.get_node_ref_back().location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return open_rings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether there are any rings that can be combined with the
|
||||||
|
* given ring to one larger ring by appending the other ring to
|
||||||
|
* the end of this ring.
|
||||||
|
* If the rings can be combined they are and the function returns
|
||||||
|
* true.
|
||||||
|
*/
|
||||||
|
bool possibly_combine_rings_back(ProtoRing& ring) {
|
||||||
|
const osmium::NodeRef& nr = ring.get_node_ref_back();
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " possibly_combine_rings_back()\n";
|
||||||
|
}
|
||||||
|
for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
|
||||||
|
if (&*it != &ring && !it->closed()) {
|
||||||
|
if (has_same_location(nr, it->get_node_ref_front())) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " ring.last=it->first\n";
|
||||||
|
}
|
||||||
|
ring.merge_ring(*it, debug());
|
||||||
|
m_rings.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (has_same_location(nr, it->get_node_ref_back())) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " ring.last=it->last\n";
|
||||||
|
}
|
||||||
|
ring.merge_ring_reverse(*it, debug());
|
||||||
|
m_rings.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether there are any rings that can be combined with the
|
||||||
|
* given ring to one larger ring by prepending the other ring to
|
||||||
|
* the start of this ring.
|
||||||
|
* If the rings can be combined they are and the function returns
|
||||||
|
* true.
|
||||||
|
*/
|
||||||
|
bool possibly_combine_rings_front(ProtoRing& ring) {
|
||||||
|
const osmium::NodeRef& nr = ring.get_node_ref_front();
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " possibly_combine_rings_front()\n";
|
||||||
|
}
|
||||||
|
for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
|
||||||
|
if (&*it != &ring && !it->closed()) {
|
||||||
|
if (has_same_location(nr, it->get_node_ref_back())) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " ring.first=it->last\n";
|
||||||
|
}
|
||||||
|
ring.swap_segments(*it);
|
||||||
|
ring.merge_ring(*it, debug());
|
||||||
|
m_rings.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (has_same_location(nr, it->get_node_ref_front())) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " ring.first=it->first\n";
|
||||||
|
}
|
||||||
|
ring.reverse();
|
||||||
|
ring.merge_ring(*it, debug());
|
||||||
|
m_rings.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void split_off_subring(osmium::area::detail::ProtoRing& ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " subring found at: " << *it << "\n";
|
||||||
|
}
|
||||||
|
ProtoRing new_ring(it_begin, it_end);
|
||||||
|
ring.remove_segments(it_begin, it_end);
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " split into two rings:\n";
|
||||||
|
std::cerr << " " << new_ring << "\n";
|
||||||
|
std::cerr << " " << ring << "\n";
|
||||||
|
}
|
||||||
|
m_rings.push_back(std::move(new_ring));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) {
|
||||||
|
if (ring.segments().size() < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " has_closed_subring_back()\n";
|
||||||
|
}
|
||||||
|
const auto end = ring.segments().end();
|
||||||
|
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||||
|
if (has_same_location(nr, it->first())) {
|
||||||
|
split_off_subring(ring, it, it, end);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) {
|
||||||
|
if (ring.segments().size() < 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " has_closed_subring_front()\n";
|
||||||
|
}
|
||||||
|
const auto end = ring.segments().end();
|
||||||
|
for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
|
||||||
|
if (has_same_location(nr, it->second())) {
|
||||||
|
split_off_subring(ring, it, ring.segments().begin(), it+1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_for_closed_subring(ProtoRing& ring) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " check_for_closed_subring()\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size());
|
||||||
|
std::copy(ring.segments().cbegin(), ring.segments().cend(), segments.begin());
|
||||||
|
std::sort(segments.begin(), segments.end());
|
||||||
|
const auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) {
|
||||||
|
return has_same_location(s1.first(), s2.first());
|
||||||
|
});
|
||||||
|
if (it == segments.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
|
||||||
|
assert(r1 != ring.segments().end());
|
||||||
|
const auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
|
||||||
|
assert(r2 != ring.segments().end());
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto m = std::minmax(r1, r2);
|
||||||
|
|
||||||
|
ProtoRing new_ring(m.first, m.second);
|
||||||
|
ring.remove_segments(m.first, m.second);
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " split ring1=" << new_ring << "\n";
|
||||||
|
std::cerr << " split ring2=" << ring << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rings.emplace_back(new_ring);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " => match at front of ring\n";
|
||||||
|
}
|
||||||
|
ring.add_segment_front(segment);
|
||||||
|
has_closed_subring_front(ring, segment.first());
|
||||||
|
if (possibly_combine_rings_front(ring)) {
|
||||||
|
check_for_closed_subring(ring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " => match at back of ring\n";
|
||||||
|
}
|
||||||
|
ring.add_segment_back(segment);
|
||||||
|
has_closed_subring_back(ring, segment.second());
|
||||||
|
if (possibly_combine_rings_back(ring)) {
|
||||||
|
check_for_closed_subring(ring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append each outer ring together with its inner rings to the
|
||||||
|
* area in the buffer.
|
||||||
|
*/
|
||||||
|
void add_rings_to_area(osmium::builder::AreaBuilder& builder) const {
|
||||||
|
for (const ProtoRing* ring : m_outer_rings) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " ring " << *ring << " is outer\n";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder);
|
||||||
|
ring_builder.add_node_ref(ring->get_node_ref_front());
|
||||||
|
for (const auto& segment : ring->segments()) {
|
||||||
|
ring_builder.add_node_ref(segment.second());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (ProtoRing* inner : ring->inner_rings()) {
|
||||||
|
osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder);
|
||||||
|
ring_builder.add_node_ref(inner->get_node_ref_front());
|
||||||
|
for (const auto& segment : inner->segments()) {
|
||||||
|
ring_builder.add_node_ref(segment.second());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) {
|
||||||
|
int n = 0;
|
||||||
|
for (auto& ring : m_rings) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " check against ring " << n << " " << ring;
|
||||||
|
}
|
||||||
|
if (ring.closed()) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " => ring CLOSED\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (has_same_location(ring.get_node_ref_back(), segment.first())) {
|
||||||
|
combine_rings_back(segment, ring);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (has_same_location(ring.get_node_ref_back(), segment.second())) {
|
||||||
|
segment.swap_locations();
|
||||||
|
combine_rings_back(segment, ring);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (has_same_location(ring.get_node_ref_front(), segment.first())) {
|
||||||
|
segment.swap_locations();
|
||||||
|
combine_rings_front(segment, ring);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (has_same_location(ring.get_node_ref_front(), segment.second())) {
|
||||||
|
combine_rings_front(segment, ring);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " => no match\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_inner_outer(ProtoRing& ring) {
|
||||||
|
const osmium::NodeRef& min_node = ring.min_node();
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " check_inner_outer min_node=" << min_node << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
int above = 0;
|
||||||
|
|
||||||
|
for (auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.location().x(); ++it) {
|
||||||
|
if (!ring.contains(*it)) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " segments for count: " << *it;
|
||||||
|
}
|
||||||
|
if (it->to_left_of(min_node.location())) {
|
||||||
|
++count;
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " counted\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " not counted\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (it->first().location() == min_node.location()) {
|
||||||
|
if (it->second().location().y() > min_node.location().y()) {
|
||||||
|
++above;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (it->second().location() == min_node.location()) {
|
||||||
|
if (it->first().location().y() > min_node.location().y()) {
|
||||||
|
++above;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " count=" << count << " above=" << above << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
count += above % 2;
|
||||||
|
|
||||||
|
if (count % 2) {
|
||||||
|
ring.set_inner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_inner_outer_roles() {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " check_inner_outer_roles\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto ringptr : m_outer_rings) {
|
||||||
|
for (const auto& segment : ringptr->segments()) {
|
||||||
|
if (!segment.role_outer()) {
|
||||||
|
++m_inner_outer_mismatches;
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n";
|
||||||
|
}
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto ringptr : m_inner_rings) {
|
||||||
|
for (const auto& segment : ringptr->segments()) {
|
||||||
|
if (!segment.role_inner()) {
|
||||||
|
++m_inner_outer_mismatches;
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n";
|
||||||
|
}
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create rings from segments.
|
||||||
|
*/
|
||||||
|
bool create_rings() {
|
||||||
|
m_segment_list.sort();
|
||||||
|
m_segment_list.erase_duplicate_segments();
|
||||||
|
|
||||||
|
// Now we look for segments crossing each other. If there are
|
||||||
|
// any, the multipolygon is invalid.
|
||||||
|
// In the future this could be improved by trying to fix those
|
||||||
|
// cases.
|
||||||
|
if (m_segment_list.find_intersections(m_config.problem_reporter)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now iterator over all segments and add them to rings. Each segment
|
||||||
|
// is tacked on to either end of an existing ring if possible, or a
|
||||||
|
// new ring is started with it.
|
||||||
|
for (const auto& segment : m_segment_list) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " checking segment " << segment << "\n";
|
||||||
|
}
|
||||||
|
if (!add_to_existing_ring(segment)) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " new ring for segment " << segment << "\n";
|
||||||
|
}
|
||||||
|
m_rings.emplace_back(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " Rings:\n";
|
||||||
|
for (const auto& ring : m_rings) {
|
||||||
|
std::cerr << " " << ring;
|
||||||
|
if (ring.closed()) {
|
||||||
|
std::cerr << " (closed)";
|
||||||
|
}
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_for_open_rings()) {
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " not all rings are closed\n";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << " Find inner/outer...\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_rings.size() == 1) {
|
||||||
|
m_outer_rings.push_back(&m_rings.front());
|
||||||
|
} else {
|
||||||
|
for (auto& ring : m_rings) {
|
||||||
|
check_inner_outer(ring);
|
||||||
|
if (ring.outer()) {
|
||||||
|
if (!ring.is_cw()) {
|
||||||
|
ring.reverse();
|
||||||
|
}
|
||||||
|
m_outer_rings.push_back(&ring);
|
||||||
|
} else {
|
||||||
|
if (ring.is_cw()) {
|
||||||
|
ring.reverse();
|
||||||
|
}
|
||||||
|
m_inner_rings.push_back(&ring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_outer_rings.size() == 1) {
|
||||||
|
for (auto inner : m_inner_rings) {
|
||||||
|
m_outer_rings.front()->add_inner_ring(inner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// sort outer rings by size, smallest first
|
||||||
|
std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
|
||||||
|
return a->area() < b->area();
|
||||||
|
});
|
||||||
|
for (auto inner : m_inner_rings) {
|
||||||
|
for (auto outer : m_outer_rings) {
|
||||||
|
if (inner->is_in(outer)) {
|
||||||
|
outer->add_inner_ring(inner);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_inner_outer_roles();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef osmium::area::AssemblerConfig config_type;
|
||||||
|
|
||||||
|
explicit Assembler(const config_type& config) :
|
||||||
|
m_config(config),
|
||||||
|
m_segment_list(config.debug) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~Assembler() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble an area from the given way.
|
||||||
|
* The resulting area is put into the out_buffer.
|
||||||
|
*/
|
||||||
|
void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->set_object(osmium::item_type::way, way.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!way.ends_have_same_id()) {
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_segment_list.extract_segments_from_way(way, "outer");
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now create the Area object and add the attributes and tags
|
||||||
|
// from the way.
|
||||||
|
{
|
||||||
|
osmium::builder::AreaBuilder builder(out_buffer);
|
||||||
|
builder.initialize_from_object(way);
|
||||||
|
|
||||||
|
if (create_rings()) {
|
||||||
|
add_tags_to_area(builder, way);
|
||||||
|
add_rings_to_area(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble an area from the given relation and its members.
|
||||||
|
* All members are to be found in the in_buffer at the offsets
|
||||||
|
* given by the members parameter.
|
||||||
|
* The resulting area is put into the out_buffer.
|
||||||
|
*/
|
||||||
|
void operator()(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) {
|
||||||
|
if (m_config.problem_reporter) {
|
||||||
|
m_config.problem_reporter->set_object(osmium::item_type::relation, relation.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
|
||||||
|
|
||||||
|
if (debug()) {
|
||||||
|
std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t area_offset = out_buffer.committed();
|
||||||
|
|
||||||
|
// Now create the Area object and add the attributes and tags
|
||||||
|
// from the relation.
|
||||||
|
{
|
||||||
|
osmium::builder::AreaBuilder builder(out_buffer);
|
||||||
|
builder.initialize_from_object(relation);
|
||||||
|
|
||||||
|
if (create_rings()) {
|
||||||
|
add_tags_to_area(builder, relation);
|
||||||
|
add_rings_to_area(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out_buffer.commit();
|
||||||
|
|
||||||
|
const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
|
||||||
|
|
||||||
|
// Find all closed ways that are inner rings and check their
|
||||||
|
// tags. If they are not the same as the tags of the area we
|
||||||
|
// just built, add them to a list and later build areas for
|
||||||
|
// them, too.
|
||||||
|
std::vector<const osmium::Way*> ways_that_should_be_areas;
|
||||||
|
if (m_inner_outer_mismatches == 0) {
|
||||||
|
auto memit = relation.members().begin();
|
||||||
|
for (size_t offset : members) {
|
||||||
|
if (!std::strcmp(memit->role(), "inner")) {
|
||||||
|
const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
|
||||||
|
if (!way.nodes().empty() && way.is_closed() && way.tags().size() > 0) {
|
||||||
|
auto d = std::count_if(way.tags().begin(), way.tags().end(), filter());
|
||||||
|
if (d > 0) {
|
||||||
|
osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end());
|
||||||
|
osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end());
|
||||||
|
osmium::tags::KeyFilter::iterator area_fi_begin(filter(), area_tags.begin(), area_tags.end());
|
||||||
|
osmium::tags::KeyFilter::iterator area_fi_end(filter(), area_tags.end(), area_tags.end());
|
||||||
|
|
||||||
|
if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d != std::distance(area_fi_begin, area_fi_end)) {
|
||||||
|
ways_that_should_be_areas.push_back(&way);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++memit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now build areas for all ways found in the last step.
|
||||||
|
for (const osmium::Way* way : ways_that_should_be_areas) {
|
||||||
|
Assembler assembler(m_config);
|
||||||
|
assembler(*way, out_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Assembler
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_ASSEMBLER_HPP
|
274
include/osmium/area/detail/node_ref_segment.hpp
Normal file
274
include/osmium/area/detail/node_ref_segment.hpp
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
#ifndef OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
||||||
|
#define OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iosfwd>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
class Way;
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Namespace for Osmium internal use
|
||||||
|
*/
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This helper class for the Assembler class models a segment.
|
||||||
|
* Segments are the connection between
|
||||||
|
* two nodes and they all have their smaller coordinate at the
|
||||||
|
* beginning of the segment. Smaller, in this case, means smaller x
|
||||||
|
* coordinate, and if they are the same smaller y coordinate.
|
||||||
|
*/
|
||||||
|
class NodeRefSegment {
|
||||||
|
|
||||||
|
osmium::NodeRef m_first;
|
||||||
|
osmium::NodeRef m_second;
|
||||||
|
|
||||||
|
/// Role of the member this segment was from.
|
||||||
|
const char* m_role;
|
||||||
|
|
||||||
|
/// Way this segment was from.
|
||||||
|
const osmium::Way* m_way;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void swap_locations() {
|
||||||
|
using std::swap;
|
||||||
|
swap(m_first, m_second);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit NodeRefSegment() noexcept :
|
||||||
|
m_first(),
|
||||||
|
m_second(),
|
||||||
|
m_role(nullptr),
|
||||||
|
m_way(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, const char* role, const osmium::Way* way) :
|
||||||
|
m_first(nr1),
|
||||||
|
m_second(nr2),
|
||||||
|
m_role(role),
|
||||||
|
m_way(way) {
|
||||||
|
if (nr2.location() < nr1.location()) {
|
||||||
|
swap_locations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRefSegment(const NodeRefSegment&) = default;
|
||||||
|
NodeRefSegment(NodeRefSegment&&) = default;
|
||||||
|
|
||||||
|
NodeRefSegment& operator=(const NodeRefSegment&) = default;
|
||||||
|
NodeRefSegment& operator=(NodeRefSegment&&) = default;
|
||||||
|
|
||||||
|
~NodeRefSegment() = default;
|
||||||
|
|
||||||
|
/// Return first NodeRef of Segment according to sorting order (bottom left to top right).
|
||||||
|
const osmium::NodeRef& first() const noexcept {
|
||||||
|
return m_first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return second NodeRef of Segment according to sorting order (bottom left to top right).
|
||||||
|
const osmium::NodeRef& second() const noexcept {
|
||||||
|
return m_second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool to_left_of(const osmium::Location& location) const {
|
||||||
|
// std::cerr << "segment " << first() << "--" << second() << " to_left_of(" << location << "\n";
|
||||||
|
|
||||||
|
if (first().location() == location || second().location() == location) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::pair<osmium::Location, osmium::Location> mm = std::minmax(first().location(), second().location(), [](const osmium::Location a, const osmium::Location b) {
|
||||||
|
return a.y() < b.y();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mm.first.y() >= location.y() || mm.second.y() < location.y() || first().location().x() > location.x()) {
|
||||||
|
// std::cerr << " false\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ax = mm.first.x();
|
||||||
|
int64_t bx = mm.second.x();
|
||||||
|
int64_t lx = location.x();
|
||||||
|
int64_t ay = mm.first.y();
|
||||||
|
int64_t by = mm.second.y();
|
||||||
|
int64_t ly = location.y();
|
||||||
|
return ((bx - ax)*(ly - ay) - (by - ay)*(lx - ax)) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool role_outer() const noexcept {
|
||||||
|
return !strcmp(m_role, "outer");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool role_inner() const noexcept {
|
||||||
|
return !strcmp(m_role, "inner");
|
||||||
|
}
|
||||||
|
|
||||||
|
const osmium::Way* way() const noexcept {
|
||||||
|
return m_way;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class NodeRefSegment
|
||||||
|
|
||||||
|
/// NodeRefSegments are equal if both their locations are equal
|
||||||
|
inline bool operator==(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return lhs.first().location() == rhs.first().location() && lhs.second().location() == rhs.second().location();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return ! (lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NodeRefSegments are "smaller" if they are to the left and down of another
|
||||||
|
* segment. The first() location is checked first() and only if they have the
|
||||||
|
* same first() location the second() location is taken into account.
|
||||||
|
*/
|
||||||
|
inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return (lhs.first().location() == rhs.first().location() && lhs.second().location() < rhs.second().location()) || lhs.first().location() < rhs.first().location();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator<=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return ! (rhs < lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator>=(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||||
|
return ! (lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TChar, typename TTraits>
|
||||||
|
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const NodeRefSegment& segment) {
|
||||||
|
return out << segment.first() << "--" << segment.second();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||||
|
if (s1.first().location().x() > s2.second().location().x()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) {
|
||||||
|
const std::pair<int32_t, int32_t> m1 = std::minmax(s1.first().location().y(), s1.second().location().y());
|
||||||
|
const std::pair<int32_t, int32_t> m2 = std::minmax(s2.first().location().y(), s2.second().location().y());
|
||||||
|
if (m1.first > m2.second || m2.first > m1.second) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the intersection between two NodeRefSegments. The
|
||||||
|
* result is returned as a Location. Note that because the Location
|
||||||
|
* uses integers with limited precision internally, the result
|
||||||
|
* might be slightly different than the numerically correct
|
||||||
|
* location.
|
||||||
|
*
|
||||||
|
* This function uses integer arithmentic as much as possible and
|
||||||
|
* will not work if the segments are longer than about half the
|
||||||
|
* planet. This shouldn't happen with real data, so it isn't a big
|
||||||
|
* problem.
|
||||||
|
*
|
||||||
|
* If the segments touch in one of their endpoints, it doesn't
|
||||||
|
* count as an intersection.
|
||||||
|
*
|
||||||
|
* If the segments intersect not in a single point but in multiple
|
||||||
|
* points, ie if they overlap, this is NOT detected.
|
||||||
|
*
|
||||||
|
* @returns Undefined osmium::Location if there is no intersection
|
||||||
|
* or a defined Location if the segments intersect.
|
||||||
|
*/
|
||||||
|
inline osmium::Location calculate_intersection(const NodeRefSegment& s1, const NodeRefSegment& s2) {
|
||||||
|
if (s1.first().location() == s2.first().location() ||
|
||||||
|
s1.first().location() == s2.second().location() ||
|
||||||
|
s1.second().location() == s2.first().location() ||
|
||||||
|
s1.second().location() == s2.second().location()) {
|
||||||
|
return osmium::Location();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t s1ax = s1.first().x();
|
||||||
|
int64_t s1ay = s1.first().y();
|
||||||
|
int64_t s1bx = s1.second().x();
|
||||||
|
int64_t s1by = s1.second().y();
|
||||||
|
int64_t s2ax = s2.first().x();
|
||||||
|
int64_t s2ay = s2.first().y();
|
||||||
|
int64_t s2bx = s2.second().x();
|
||||||
|
int64_t s2by = s2.second().y();
|
||||||
|
|
||||||
|
int64_t d = (s2by - s2ay) * (s1bx - s1ax) -
|
||||||
|
(s2bx - s2ax) * (s1by - s1ay);
|
||||||
|
|
||||||
|
if (d != 0) {
|
||||||
|
int64_t na = (s2bx - s2ax) * (s1ay - s2ay) -
|
||||||
|
(s2by - s2ay) * (s1ax - s2ax);
|
||||||
|
|
||||||
|
int64_t nb = (s1bx - s1ax) * (s1ay - s2ay) -
|
||||||
|
(s1by - s1ay) * (s1ax - s2ax);
|
||||||
|
|
||||||
|
if ((d > 0 && na >= 0 && na <= d && nb >= 0 && nb <= d) ||
|
||||||
|
(d < 0 && na <= 0 && na >= d && nb <= 0 && nb >= d)) {
|
||||||
|
|
||||||
|
double ua = double(na) / d;
|
||||||
|
int32_t ix = int32_t(s1ax + ua*(s1bx - s1ax));
|
||||||
|
int32_t iy = int32_t(s1ay + ua*(s1by - s1ay));
|
||||||
|
|
||||||
|
return osmium::Location(ix, iy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return osmium::Location();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
285
include/osmium/area/detail/proto_ring.hpp
Normal file
285
include/osmium/area/detail/proto_ring.hpp
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
#ifndef OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
||||||
|
#define OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ring in the process of being built by the Assembler object.
|
||||||
|
*/
|
||||||
|
class ProtoRing {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::vector<NodeRefSegment> segments_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// segments in this ring
|
||||||
|
segments_type m_segments;
|
||||||
|
|
||||||
|
bool m_outer {true};
|
||||||
|
|
||||||
|
// if this is an outer ring, these point to it's inner rings (if any)
|
||||||
|
std::vector<ProtoRing*> m_inner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ProtoRing(const NodeRefSegment& segment) noexcept :
|
||||||
|
m_segments() {
|
||||||
|
add_segment_back(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit ProtoRing(segments_type::const_iterator sbegin, segments_type::const_iterator send) :
|
||||||
|
m_segments(static_cast<size_t>(std::distance(sbegin, send))) {
|
||||||
|
std::copy(sbegin, send, m_segments.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool outer() const noexcept {
|
||||||
|
return m_outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_inner() noexcept {
|
||||||
|
m_outer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
segments_type& segments() noexcept {
|
||||||
|
return m_segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
const segments_type& segments() const noexcept {
|
||||||
|
return m_segments;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_segments(segments_type::iterator sbegin, segments_type::iterator send) {
|
||||||
|
m_segments.erase(sbegin, send);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_segment_front(const NodeRefSegment& segment) {
|
||||||
|
m_segments.insert(m_segments.begin(), segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_segment_back(const NodeRefSegment& segment) {
|
||||||
|
m_segments.push_back(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeRefSegment& get_segment_front() const {
|
||||||
|
return m_segments.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRefSegment& get_segment_front() {
|
||||||
|
return m_segments.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeRef& get_node_ref_front() const {
|
||||||
|
return get_segment_front().first();
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeRefSegment& get_segment_back() const {
|
||||||
|
return m_segments.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeRefSegment& get_segment_back() {
|
||||||
|
return m_segments.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeRef& get_node_ref_back() const {
|
||||||
|
return get_segment_back().second();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool closed() const {
|
||||||
|
return m_segments.front().first().location() == m_segments.back().second().location();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t sum() const {
|
||||||
|
int64_t sum = 0;
|
||||||
|
|
||||||
|
for (const auto& segment : m_segments) {
|
||||||
|
sum += static_cast<int64_t>(segment.first().location().x()) * static_cast<int64_t>(segment.second().location().y()) -
|
||||||
|
static_cast<int64_t>(segment.second().location().x()) * static_cast<int64_t>(segment.first().location().y());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_cw() const {
|
||||||
|
return sum() <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t area() const {
|
||||||
|
return std::abs(sum()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap_segments(ProtoRing& other) {
|
||||||
|
using std::swap;
|
||||||
|
swap(m_segments, other.m_segments);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_inner_ring(ProtoRing* ring) {
|
||||||
|
m_inner.push_back(ring);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<ProtoRing*>& inner_rings() const {
|
||||||
|
return m_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(std::ostream& out) const {
|
||||||
|
out << "[";
|
||||||
|
bool first = true;
|
||||||
|
for (const auto& segment : m_segments) {
|
||||||
|
if (first) {
|
||||||
|
out << segment.first().ref();
|
||||||
|
}
|
||||||
|
out << ',' << segment.second().ref();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
out << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse() {
|
||||||
|
std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment& segment) {
|
||||||
|
segment.swap_locations();
|
||||||
|
});
|
||||||
|
std::reverse(m_segments.begin(), m_segments.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge other ring to end of this ring.
|
||||||
|
*/
|
||||||
|
void merge_ring(const ProtoRing& other, bool debug) {
|
||||||
|
if (debug) {
|
||||||
|
std::cerr << " MERGE rings ";
|
||||||
|
print(std::cerr);
|
||||||
|
std::cerr << " to ";
|
||||||
|
other.print(std::cerr);
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
m_segments.insert(m_segments.end(), other.m_segments.begin(), other.m_segments.end());
|
||||||
|
if (debug) {
|
||||||
|
std::cerr << " result ring: ";
|
||||||
|
print(std::cerr);
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void merge_ring_reverse(const ProtoRing& other, bool debug) {
|
||||||
|
if (debug) {
|
||||||
|
std::cerr << " MERGE rings (reverse) ";
|
||||||
|
print(std::cerr);
|
||||||
|
std::cerr << " to ";
|
||||||
|
other.print(std::cerr);
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
size_t n = m_segments.size();
|
||||||
|
m_segments.resize(n + other.m_segments.size());
|
||||||
|
std::transform(other.m_segments.rbegin(), other.m_segments.rend(), m_segments.begin() + static_cast<segments_type::difference_type>(n), [](NodeRefSegment segment) {
|
||||||
|
segment.swap_locations();
|
||||||
|
return segment;
|
||||||
|
});
|
||||||
|
if (debug) {
|
||||||
|
std::cerr << " result ring: ";
|
||||||
|
print(std::cerr);
|
||||||
|
std::cerr << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const NodeRef& min_node() const {
|
||||||
|
auto it = std::min_element(m_segments.begin(), m_segments.end());
|
||||||
|
if (location_less()(it->first(), it->second())) {
|
||||||
|
return it->first();
|
||||||
|
} else {
|
||||||
|
return it->second();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_in(ProtoRing* outer) {
|
||||||
|
osmium::Location testpoint = segments().front().first().location();
|
||||||
|
bool is_in = false;
|
||||||
|
|
||||||
|
for (size_t i = 0, j = outer->segments().size()-1; i < outer->segments().size(); j = i++) {
|
||||||
|
if (((outer->segments()[i].first().location().y() > testpoint.y()) != (outer->segments()[j].first().location().y() > testpoint.y())) &&
|
||||||
|
(testpoint.x() < (outer->segments()[j].first().location().x() - outer->segments()[i].first().location().x()) * (testpoint.y() - outer->segments()[i].first().location().y()) / (outer->segments()[j].first().location().y() - outer->segments()[i].first().location().y()) + outer->segments()[i].first().location().x()) ) {
|
||||||
|
is_in = !is_in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return is_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_ways(std::set<const osmium::Way*>& ways) {
|
||||||
|
for (const auto& segment : m_segments) {
|
||||||
|
ways.insert(segment.way());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const NodeRefSegment& segment) const {
|
||||||
|
for (const auto& s : m_segments) {
|
||||||
|
if (s == segment || (s.first() == segment.second() && s.second() == segment.first())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ProtoRing
|
||||||
|
|
||||||
|
template <typename TChar, typename TTraits>
|
||||||
|
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const ProtoRing& ring) {
|
||||||
|
ring.print(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_DETAIL_PROTO_RING_HPP
|
229
include/osmium/area/detail/segment_list.hpp
Normal file
229
include/osmium/area/detail/segment_list.hpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#ifndef OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
||||||
|
#define OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/area/problem_reporter.hpp>
|
||||||
|
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper class for the area assembler. It models
|
||||||
|
* a list of segments.
|
||||||
|
*/
|
||||||
|
class SegmentList {
|
||||||
|
|
||||||
|
using slist_type = std::vector<NodeRefSegment>;
|
||||||
|
|
||||||
|
slist_type m_segments;
|
||||||
|
|
||||||
|
bool m_debug;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit SegmentList(bool debug) noexcept :
|
||||||
|
m_segments(),
|
||||||
|
m_debug(debug) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~SegmentList() noexcept = default;
|
||||||
|
|
||||||
|
SegmentList(const SegmentList&) = delete;
|
||||||
|
SegmentList(SegmentList&&) = delete;
|
||||||
|
|
||||||
|
SegmentList& operator=(const SegmentList&) = delete;
|
||||||
|
SegmentList& operator=(SegmentList&&) = delete;
|
||||||
|
|
||||||
|
/// The number of segments in the list.
|
||||||
|
size_t size() const noexcept {
|
||||||
|
return m_segments.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const noexcept {
|
||||||
|
return m_segments.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef slist_type::const_iterator const_iterator;
|
||||||
|
typedef slist_type::iterator iterator;
|
||||||
|
|
||||||
|
iterator begin() noexcept {
|
||||||
|
return m_segments.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() noexcept {
|
||||||
|
return m_segments.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {
|
||||||
|
return m_segments.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const noexcept {
|
||||||
|
return m_segments.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable or disable debug output to stderr. This is used
|
||||||
|
* for debugging libosmium itself.
|
||||||
|
*/
|
||||||
|
void enable_debug_output(bool debug = true) noexcept {
|
||||||
|
m_debug = debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear the list of segments. All segments are removed.
|
||||||
|
void clear() {
|
||||||
|
m_segments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sort the list of segments.
|
||||||
|
void sort() {
|
||||||
|
std::sort(m_segments.begin(), m_segments.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract segments from given way and add them to the list.
|
||||||
|
*
|
||||||
|
* Segments connecting two nodes with the same location (ie same
|
||||||
|
* node or different node with same location) are removed.
|
||||||
|
*
|
||||||
|
* XXX should two nodes with same location be reported?
|
||||||
|
*/
|
||||||
|
void extract_segments_from_way(const osmium::Way& way, const char* role) {
|
||||||
|
osmium::NodeRef last_nr;
|
||||||
|
for (const osmium::NodeRef& nr : way.nodes()) {
|
||||||
|
if (last_nr.location() && last_nr.location() != nr.location()) {
|
||||||
|
m_segments.emplace_back(last_nr, nr, role, &way);
|
||||||
|
}
|
||||||
|
last_nr = nr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract all segments from all ways that make up this
|
||||||
|
* multipolygon relation and add them to the list.
|
||||||
|
*/
|
||||||
|
void extract_segments_from_ways(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer) {
|
||||||
|
auto member_it = relation.members().begin();
|
||||||
|
for (size_t offset : members) {
|
||||||
|
const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
|
||||||
|
extract_segments_from_way(way, member_it->role());
|
||||||
|
++member_it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find duplicate segments (ie same start and end point) in the
|
||||||
|
* list and remove them. This will always remove pairs of the
|
||||||
|
* same segment. So if there are three, for instance, two will
|
||||||
|
* be removed and one will be left.
|
||||||
|
*/
|
||||||
|
void erase_duplicate_segments() {
|
||||||
|
while (true) {
|
||||||
|
auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
|
||||||
|
if (it == m_segments.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_debug) {
|
||||||
|
std::cerr << " erase duplicate segment: " << *it << "\n";
|
||||||
|
}
|
||||||
|
m_segments.erase(it, it+2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find intersection between segments.
|
||||||
|
*
|
||||||
|
* @param problem_reporter Any intersections found are
|
||||||
|
* reported to this object.
|
||||||
|
* @returns true if there are intersections.
|
||||||
|
*/
|
||||||
|
bool find_intersections(osmium::area::ProblemReporter* problem_reporter) const {
|
||||||
|
if (m_segments.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found_intersections = false;
|
||||||
|
|
||||||
|
for (auto it1 = m_segments.begin(); it1 != m_segments.end()-1; ++it1) {
|
||||||
|
const NodeRefSegment& s1 = *it1;
|
||||||
|
for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) {
|
||||||
|
const NodeRefSegment& s2 = *it2;
|
||||||
|
|
||||||
|
assert(s1 != s2); // erase_duplicate_segments() should have made sure of that
|
||||||
|
|
||||||
|
if (outside_x_range(s2, s1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y_range_overlap(s1, s2)) {
|
||||||
|
osmium::Location intersection = calculate_intersection(s1, s2);
|
||||||
|
if (intersection) {
|
||||||
|
found_intersections = true;
|
||||||
|
if (m_debug) {
|
||||||
|
std::cerr << " segments " << s1 << " and " << s2 << " intersecting at " << intersection << "\n";
|
||||||
|
}
|
||||||
|
if (problem_reporter) {
|
||||||
|
problem_reporter->report_intersection(s1.way()->id(), s1.first().location(), s1.second().location(), s2.way()->id(), s2.first().location(), s2.second().location(), intersection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found_intersections;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class SegmentList
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_DETAIL_SEGMENT_LIST_HPP
|
201
include/osmium/area/multipolygon_collector.hpp
Normal file
201
include/osmium/area/multipolygon_collector.hpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||||
|
#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/tag.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
#include <osmium/relations/collector.hpp>
|
||||||
|
#include <osmium/relations/detail/member_meta.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace relations {
|
||||||
|
class RelationMeta;
|
||||||
|
} // namespace relations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Code related to the building of areas (multipolygons) from relations.
|
||||||
|
*/
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class collects all data needed for creating areas from
|
||||||
|
* relations tagged with type=multipolygon or type=boundary.
|
||||||
|
* Most of its functionality is derived from the parent class
|
||||||
|
* osmium::relations::Collector.
|
||||||
|
*
|
||||||
|
* The actual assembling of the areas is done by the assembler
|
||||||
|
* class given as template argument.
|
||||||
|
*
|
||||||
|
* @tparam TAssembler Multipolygon Assembler class.
|
||||||
|
*/
|
||||||
|
template <typename TAssembler>
|
||||||
|
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
|
||||||
|
|
||||||
|
typedef typename osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> collector_type;
|
||||||
|
|
||||||
|
typedef typename TAssembler::config_type assembler_config_type;
|
||||||
|
const assembler_config_type m_assembler_config;
|
||||||
|
|
||||||
|
osmium::memory::Buffer m_output_buffer;
|
||||||
|
|
||||||
|
static constexpr size_t initial_output_buffer_size = 1024 * 1024;
|
||||||
|
static constexpr size_t max_buffer_size_for_flush = 100 * 1024;
|
||||||
|
|
||||||
|
void flush_output_buffer() {
|
||||||
|
if (this->callback()) {
|
||||||
|
osmium::memory::Buffer buffer(initial_output_buffer_size);
|
||||||
|
using std::swap;
|
||||||
|
swap(buffer, m_output_buffer);
|
||||||
|
this->callback()(std::move(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void possibly_flush_output_buffer() {
|
||||||
|
if (m_output_buffer.committed() > max_buffer_size_for_flush) {
|
||||||
|
flush_output_buffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit MultipolygonCollector(const assembler_config_type& assembler_config) :
|
||||||
|
collector_type(),
|
||||||
|
m_assembler_config(assembler_config),
|
||||||
|
m_output_buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We are interested in all relations tagged with type=multipolygon
|
||||||
|
* or type=boundary.
|
||||||
|
*
|
||||||
|
* Overwritten from the base class.
|
||||||
|
*/
|
||||||
|
bool keep_relation(const osmium::Relation& relation) const {
|
||||||
|
const char* type = relation.tags().get_value_by_key("type");
|
||||||
|
|
||||||
|
// ignore relations without "type" tag
|
||||||
|
if (!type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!strcmp(type, "multipolygon")) || (!strcmp(type, "boundary"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwritten from the base class.
|
||||||
|
*/
|
||||||
|
bool keep_member(const osmium::relations::RelationMeta& /*relation_meta*/, const osmium::RelationMember& member) const {
|
||||||
|
// We are only interested in members of type way.
|
||||||
|
return member.type() == osmium::item_type::way;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is called when a way is not in any multipolygon
|
||||||
|
* relation.
|
||||||
|
*
|
||||||
|
* Overwritten from the base class.
|
||||||
|
*/
|
||||||
|
void way_not_in_any_relation(const osmium::Way& way) {
|
||||||
|
// you need at least 4 nodes to make up a polygon
|
||||||
|
if (way.nodes().size() <= 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (!way.nodes().front().location() || !way.nodes().back().location()) {
|
||||||
|
throw osmium::invalid_location("invalid location");
|
||||||
|
}
|
||||||
|
if (way.ends_have_same_location()) {
|
||||||
|
// way is closed and has enough nodes, build simple multipolygon
|
||||||
|
TAssembler assembler(m_assembler_config);
|
||||||
|
assembler(way, m_output_buffer);
|
||||||
|
possibly_flush_output_buffer();
|
||||||
|
}
|
||||||
|
} catch (osmium::invalid_location&) {
|
||||||
|
// XXX ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void complete_relation(osmium::relations::RelationMeta& relation_meta) {
|
||||||
|
const osmium::Relation& relation = this->get_relation(relation_meta);
|
||||||
|
std::vector<size_t> offsets;
|
||||||
|
for (const auto& member : relation.members()) {
|
||||||
|
if (member.ref() != 0) {
|
||||||
|
offsets.push_back(this->get_offset(member.type(), member.ref()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
TAssembler assembler(m_assembler_config);
|
||||||
|
assembler(relation, offsets, this->members_buffer(), m_output_buffer);
|
||||||
|
possibly_flush_output_buffer();
|
||||||
|
} catch (osmium::invalid_location&) {
|
||||||
|
// XXX ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
flush_output_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::memory::Buffer read() {
|
||||||
|
osmium::memory::Buffer buffer(initial_output_buffer_size, osmium::memory::Buffer::auto_grow::yes);
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(buffer, m_output_buffer);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class MultipolygonCollector
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
149
include/osmium/area/problem_reporter.hpp
Normal file
149
include/osmium/area/problem_reporter.hpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||||
|
#define OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When assembling a multipolygon/area from a multipolygon relation
|
||||||
|
* or a closed way several problems can be detected. This includes
|
||||||
|
* intersections between lines, wrong role attributes on relation
|
||||||
|
* members etc. These problems are reported by the area::Assembler
|
||||||
|
* class to the ProblemReporter class or one of its child classes.
|
||||||
|
*
|
||||||
|
* This is the parent class which does nothing with the reports.
|
||||||
|
* Child classes are expected to implement different ways of
|
||||||
|
* reporting the problems.
|
||||||
|
*/
|
||||||
|
class ProblemReporter {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Type of object we are currently working on
|
||||||
|
osmium::item_type m_object_type;
|
||||||
|
|
||||||
|
// ID of the relation/way we are currently working on
|
||||||
|
osmium::object_id_type m_object_id;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProblemReporter() = default;
|
||||||
|
|
||||||
|
virtual ~ProblemReporter() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the object the next problem reports will be on.
|
||||||
|
*
|
||||||
|
* @param object_type The type of the object.
|
||||||
|
* @param object_id The ID of the object.
|
||||||
|
*/
|
||||||
|
void set_object(osmium::item_type object_type, osmium::object_id_type object_id) noexcept {
|
||||||
|
m_object_type = object_type;
|
||||||
|
m_object_id = object_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable "unused-parameter" warning, so that the compiler will not complain.
|
||||||
|
// We can't remove the parameter names, because then doxygen will complain.
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a duplicate node, ie. two nodes with the same location.
|
||||||
|
*
|
||||||
|
* @param node_id1 ID of the first node.
|
||||||
|
* @param node_id2 ID of the second node.
|
||||||
|
* @param location Location of both nodes.
|
||||||
|
*/
|
||||||
|
virtual void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report an intersection between two segments.
|
||||||
|
*
|
||||||
|
* @param way1_id ID of the first involved way.
|
||||||
|
* @param way1_seg_start Location where the segment of the first way with the intersection starts
|
||||||
|
* @param way1_seg_end Location where the segment of the first way with the intersection ends
|
||||||
|
* @param way2_id ID of the second involved way.
|
||||||
|
* @param way2_seg_start Location where the segment of the second way with the intersection starts
|
||||||
|
* @param way2_seg_end Location where the segment of the second way with the intersection ends
|
||||||
|
* @param intersection Location of the intersection. This might be slightly off the correct location due to rounding.
|
||||||
|
*/
|
||||||
|
virtual void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||||
|
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report an open ring.
|
||||||
|
*
|
||||||
|
* @param end1 Location of the first open end.
|
||||||
|
* @param end2 Location of the second open end.
|
||||||
|
*/
|
||||||
|
virtual void report_ring_not_closed(osmium::Location end1, osmium::Location end2) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a segment that should have role "outer", but has a different role.
|
||||||
|
*
|
||||||
|
* @param way_id ID of the way this segment is in.
|
||||||
|
* @param seg_start Start of the segment with the wrong role.
|
||||||
|
* @param seg_end End of the segment with the wrong role.
|
||||||
|
*/
|
||||||
|
virtual void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report a segment that should have role "inner", but has a different role.
|
||||||
|
*
|
||||||
|
* @param way_id ID of the way this segment is in.
|
||||||
|
* @param seg_start Start of the segment with the wrong role.
|
||||||
|
* @param seg_end End of the segment with the wrong role.
|
||||||
|
*/
|
||||||
|
virtual void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
}; // class ProblemReporter
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
96
include/osmium/area/problem_reporter_exception.hpp
Normal file
96
include/osmium/area/problem_reporter_exception.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
||||||
|
#define OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <osmium/area/problem_reporter_stream.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
class ProblemReporterException : public ProblemReporterStream {
|
||||||
|
|
||||||
|
std::stringstream m_sstream;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ProblemReporterException() :
|
||||||
|
ProblemReporterStream(m_sstream) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProblemReporterException() override = default;
|
||||||
|
|
||||||
|
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||||
|
m_sstream.str();
|
||||||
|
ProblemReporterStream::report_duplicate_node(node_id1, node_id2, location);
|
||||||
|
throw std::runtime_error(m_sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||||
|
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||||
|
m_sstream.str();
|
||||||
|
ProblemReporterStream::report_intersection(way1_id, way1_seg_start, way1_seg_end, way2_id, way2_seg_start, way2_seg_end, intersection);
|
||||||
|
throw std::runtime_error(m_sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||||
|
m_sstream.str();
|
||||||
|
ProblemReporterStream::report_ring_not_closed(end1, end2);
|
||||||
|
throw std::runtime_error(m_sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
m_sstream.str();
|
||||||
|
ProblemReporterStream::report_role_should_be_outer(way_id, seg_start, seg_end);
|
||||||
|
throw std::runtime_error(m_sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
m_sstream.str();
|
||||||
|
ProblemReporterStream::report_role_should_be_inner(way_id, seg_start, seg_end);
|
||||||
|
throw std::runtime_error(m_sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ProblemReporterException
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
139
include/osmium/area/problem_reporter_ogr.hpp
Normal file
139
include/osmium/area/problem_reporter_ogr.hpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
||||||
|
#define OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* This file contains code for reporting problems through OGR when
|
||||||
|
* assembling multipolygons.
|
||||||
|
*
|
||||||
|
* @attention If you include this file, you'll need to link with `libgdal`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <gdalcpp.hpp>
|
||||||
|
|
||||||
|
#include <osmium/area/problem_reporter.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
#include <osmium/geom/ogr.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report problems when assembling areas by adding them to
|
||||||
|
* layers in an OGR datasource.
|
||||||
|
*/
|
||||||
|
class ProblemReporterOGR : public ProblemReporter {
|
||||||
|
|
||||||
|
osmium::geom::OGRFactory<> m_ogr_factory;
|
||||||
|
|
||||||
|
gdalcpp::Layer m_layer_perror;
|
||||||
|
gdalcpp::Layer m_layer_lerror;
|
||||||
|
|
||||||
|
void write_point(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location location) {
|
||||||
|
gdalcpp::Feature feature(m_layer_perror, m_ogr_factory.create_point(location));
|
||||||
|
feature.set_field("id1", static_cast<double>(id1));
|
||||||
|
feature.set_field("id2", static_cast<double>(id2));
|
||||||
|
feature.set_field("problem_type", problem_type);
|
||||||
|
feature.add_to_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_line(const char* problem_type, osmium::object_id_type id1, osmium::object_id_type id2, osmium::Location loc1, osmium::Location loc2) {
|
||||||
|
std::unique_ptr<OGRPoint> ogr_point1 = m_ogr_factory.create_point(loc1);
|
||||||
|
std::unique_ptr<OGRPoint> ogr_point2 = m_ogr_factory.create_point(loc2);
|
||||||
|
std::unique_ptr<OGRLineString> ogr_linestring = std::unique_ptr<OGRLineString>(new OGRLineString());
|
||||||
|
ogr_linestring->addPoint(ogr_point1.get());
|
||||||
|
ogr_linestring->addPoint(ogr_point2.get());
|
||||||
|
|
||||||
|
gdalcpp::Feature feature(m_layer_lerror, std::move(ogr_linestring));
|
||||||
|
feature.set_field("id1", static_cast<double>(id1));
|
||||||
|
feature.set_field("id2", static_cast<double>(id2));
|
||||||
|
feature.set_field("problem_type", problem_type);
|
||||||
|
feature.add_to_layer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ProblemReporterOGR(gdalcpp::Dataset& dataset) :
|
||||||
|
m_layer_perror(dataset, "perrors", wkbPoint),
|
||||||
|
m_layer_lerror(dataset, "lerrors", wkbLineString) {
|
||||||
|
|
||||||
|
m_layer_perror.add_field("id1", OFTReal, 10);
|
||||||
|
m_layer_perror.add_field("id2", OFTReal, 10);
|
||||||
|
m_layer_perror.add_field("problem_type", OFTString, 30);
|
||||||
|
|
||||||
|
m_layer_lerror.add_field("id1", OFTReal, 10);
|
||||||
|
m_layer_lerror.add_field("id2", OFTReal, 10);
|
||||||
|
m_layer_lerror.add_field("problem_type", OFTString, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProblemReporterOGR() override = default;
|
||||||
|
|
||||||
|
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||||
|
write_point("duplicate_node", node_id1, node_id2, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||||
|
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||||
|
write_point("intersection", m_object_id, 0, intersection);
|
||||||
|
write_line("intersection", m_object_id, way1_id, way1_seg_start, way1_seg_end);
|
||||||
|
write_line("intersection", m_object_id, way2_id, way2_seg_start, way2_seg_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||||
|
write_point("ring_not_closed", m_object_id, 0, end1);
|
||||||
|
write_point("ring_not_closed", m_object_id, 0, end2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
write_line("role_should_be_outer", m_object_id, way_id, seg_start, seg_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
write_line("role_should_be_inner", m_object_id, way_id, seg_start, seg_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ProblemReporterOGR
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
96
include/osmium/area/problem_reporter_stream.hpp
Normal file
96
include/osmium/area/problem_reporter_stream.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
||||||
|
#define OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <ostream>
|
||||||
|
|
||||||
|
#include <osmium/area/problem_reporter.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace area {
|
||||||
|
|
||||||
|
class ProblemReporterStream : public ProblemReporter {
|
||||||
|
|
||||||
|
std::ostream* m_out;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ProblemReporterStream(std::ostream& out) :
|
||||||
|
m_out(&out) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~ProblemReporterStream() override = default;
|
||||||
|
|
||||||
|
void header(const char* msg) {
|
||||||
|
*m_out << "DATA PROBLEM: " << msg << " on " << item_type_to_char(m_object_type) << m_object_id << ": ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location) override {
|
||||||
|
header("duplicate node");
|
||||||
|
*m_out << "node_id1=" << node_id1 << " node_id2=" << node_id2 << " location=" << location << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_intersection(osmium::object_id_type way1_id, osmium::Location way1_seg_start, osmium::Location way1_seg_end,
|
||||||
|
osmium::object_id_type way2_id, osmium::Location way2_seg_start, osmium::Location way2_seg_end, osmium::Location intersection) override {
|
||||||
|
header("intersection");
|
||||||
|
*m_out << "way1_id=" << way1_id << " way1_seg_start=" << way1_seg_start << " way1_seg_end=" << way1_seg_end
|
||||||
|
<< " way2_id=" << way2_id << " way2_seg_start=" << way2_seg_start << " way2_seg_end=" << way2_seg_end << " intersection=" << intersection << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_ring_not_closed(osmium::Location end1, osmium::Location end2) override {
|
||||||
|
header("ring not closed");
|
||||||
|
*m_out << "end1=" << end1 << " end2=" << end2 << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
header("role should be outer");
|
||||||
|
*m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end) override {
|
||||||
|
header("role should be inner");
|
||||||
|
*m_out << "way_id=" << way_id << " seg_start=" << seg_start << " seg_end=" << seg_end << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ProblemReporterStream
|
||||||
|
|
||||||
|
} // namespace area
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
877
include/osmium/builder/attr.hpp
Normal file
877
include/osmium/builder/attr.hpp
Normal file
@ -0,0 +1,877 @@
|
|||||||
|
#ifndef OSMIUM_BUILDER_ATTR_HPP
|
||||||
|
#define OSMIUM_BUILDER_ATTR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ctime>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <iterator>
|
||||||
|
#include <string>
|
||||||
|
#include <tuple>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/builder/builder.hpp>
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/osm.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace builder {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// workaround for bug in MSVC
|
||||||
|
|
||||||
|
template <typename THandler, typename... TTypes>
|
||||||
|
struct is_handled_by;
|
||||||
|
|
||||||
|
template <typename THandler>
|
||||||
|
struct is_handled_by<THandler> {
|
||||||
|
static constexpr bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename THandler, typename T, typename... TRest>
|
||||||
|
struct is_handled_by<THandler, T, TRest...> {
|
||||||
|
static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value ||
|
||||||
|
is_handled_by<THandler, TRest...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename THandler, typename... TTypes>
|
||||||
|
struct are_all_handled_by;
|
||||||
|
|
||||||
|
template <typename THandler, typename T>
|
||||||
|
struct are_all_handled_by<THandler, T> {
|
||||||
|
static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename THandler, typename T, typename... TRest>
|
||||||
|
struct are_all_handled_by<THandler, T, TRest...> {
|
||||||
|
static constexpr bool value = std::is_base_of<typename T::handler, THandler>::value &&
|
||||||
|
are_all_handled_by<THandler, TRest...>::value;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
// True if Predicate matches for none of the types Ts
|
||||||
|
template <template<typename> class Predicate, typename... Ts>
|
||||||
|
struct static_none_of : std::is_same<std::tuple<std::false_type, typename Predicate<Ts>::type...>,
|
||||||
|
std::tuple<typename Predicate<Ts>::type..., std::false_type>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// True if Predicate matches for all of the types Ts
|
||||||
|
template <template<typename> class Predicate, typename... Ts>
|
||||||
|
struct static_all_of : std::is_same<std::tuple<std::true_type, typename Predicate<Ts>::type...>,
|
||||||
|
std::tuple<typename Predicate<Ts>::type..., std::true_type>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
// True if THandler is derived from the handler for at least one of the types in TTypes
|
||||||
|
template <typename THandler, typename... TTypes>
|
||||||
|
struct is_handled_by {
|
||||||
|
template <typename T>
|
||||||
|
using HasHandler = std::is_base_of<typename T::handler, THandler>;
|
||||||
|
|
||||||
|
static constexpr bool value = !static_none_of<HasHandler, TTypes...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// True if THandler is derived from the handlers of all the types in TTypes
|
||||||
|
template <typename THandler, typename... TTypes>
|
||||||
|
struct are_all_handled_by {
|
||||||
|
template <typename T>
|
||||||
|
using HasHandler = std::is_base_of<typename T::handler, THandler>;
|
||||||
|
|
||||||
|
static constexpr bool value = static_all_of<HasHandler, TTypes...>::value;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Wraps any type, so that we can derive from it
|
||||||
|
template <typename TType>
|
||||||
|
struct type_wrapper {
|
||||||
|
|
||||||
|
using type = TType;
|
||||||
|
|
||||||
|
TType value;
|
||||||
|
|
||||||
|
constexpr explicit type_wrapper(const TType& v) :
|
||||||
|
value(v) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct type_wrapper
|
||||||
|
|
||||||
|
// Small wrapper for begin/end iterator
|
||||||
|
template <typename TType>
|
||||||
|
struct iterator_wrapper {
|
||||||
|
|
||||||
|
using type = TType;
|
||||||
|
|
||||||
|
TType first;
|
||||||
|
TType last;
|
||||||
|
|
||||||
|
constexpr iterator_wrapper(TType begin, TType end) :
|
||||||
|
first(begin),
|
||||||
|
last(end) {}
|
||||||
|
|
||||||
|
constexpr TType begin() const {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr TType end() const {
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct iterator_wrapper
|
||||||
|
|
||||||
|
|
||||||
|
struct entity_handler {};
|
||||||
|
struct object_handler;
|
||||||
|
struct node_handler;
|
||||||
|
struct tags_handler;
|
||||||
|
struct nodes_handler;
|
||||||
|
struct members_handler;
|
||||||
|
struct changeset_handler;
|
||||||
|
struct discussion_handler;
|
||||||
|
struct ring_handler;
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
#define OSMIUM_ATTRIBUTE(_handler, _name, _type) \
|
||||||
|
struct _name : public osmium::builder::detail::type_wrapper<_type> { \
|
||||||
|
using handler = osmium::builder::detail::_handler;
|
||||||
|
|
||||||
|
#define OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(_handler, _name, _type) \
|
||||||
|
OSMIUM_ATTRIBUTE(_handler, _name, _type) \
|
||||||
|
constexpr explicit _name(std::add_const<_type>::type& value) : \
|
||||||
|
type_wrapper(value) {} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OSMIUM_ATTRIBUTE_ITER(_handler, _name) \
|
||||||
|
template <typename TIterator> \
|
||||||
|
struct _name : public osmium::builder::detail::iterator_wrapper<TIterator> { \
|
||||||
|
using handler = osmium::builder::detail::_handler; \
|
||||||
|
constexpr _name(TIterator first, TIterator last) : \
|
||||||
|
osmium::builder::detail::iterator_wrapper<TIterator>(first, last) {} \
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace attr {
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(object_handler, _id, osmium::object_id_type);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(object_handler, _version, osmium::object_version_type);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(entity_handler, _uid, osmium::user_id_type);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(entity_handler, _cid, osmium::changeset_id_type);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(object_handler, _deleted, bool)
|
||||||
|
constexpr explicit _deleted(bool value = true) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(object_handler, _visible, bool)
|
||||||
|
constexpr explicit _visible(bool value = true) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(object_handler, _timestamp, osmium::Timestamp)
|
||||||
|
constexpr explicit _timestamp(const osmium::Timestamp& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
constexpr explicit _timestamp(time_t value) noexcept :
|
||||||
|
type_wrapper(osmium::Timestamp{value}) {}
|
||||||
|
constexpr explicit _timestamp(uint32_t value) noexcept :
|
||||||
|
type_wrapper(osmium::Timestamp{value}) {}
|
||||||
|
explicit _timestamp(const char* value) :
|
||||||
|
type_wrapper(osmium::Timestamp{value}) {}
|
||||||
|
explicit _timestamp(const std::string& value) :
|
||||||
|
type_wrapper(osmium::Timestamp{value}) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(node_handler, _location, osmium::Location)
|
||||||
|
constexpr explicit _location(const osmium::Location& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
explicit _location(double lat, double lon) :
|
||||||
|
type_wrapper(osmium::Location{lat, lon}) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(entity_handler, _user, const char*)
|
||||||
|
constexpr explicit _user(const char* val) noexcept :
|
||||||
|
type_wrapper(val) {}
|
||||||
|
explicit _user(const std::string& val) noexcept :
|
||||||
|
type_wrapper(val.c_str()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair_of_cstrings = std::pair<const char* const, const char* const>;
|
||||||
|
using pair_of_strings = std::pair<const std::string&, const std::string&>;
|
||||||
|
|
||||||
|
class member_type {
|
||||||
|
|
||||||
|
osmium::item_type m_type;
|
||||||
|
osmium::object_id_type m_ref;
|
||||||
|
const char* m_role;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
constexpr member_type(osmium::item_type type, osmium::object_id_type ref, const char* role = "") noexcept :
|
||||||
|
m_type(type),
|
||||||
|
m_ref(ref),
|
||||||
|
m_role(role) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr osmium::item_type type() const noexcept {
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr osmium::object_id_type ref() const noexcept {
|
||||||
|
return m_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* role() const noexcept {
|
||||||
|
return m_role;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class member_type
|
||||||
|
|
||||||
|
class comment_type {
|
||||||
|
|
||||||
|
osmium::Timestamp m_date;
|
||||||
|
osmium::user_id_type m_uid;
|
||||||
|
const char* m_user;
|
||||||
|
const char* m_text;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
constexpr comment_type(osmium::Timestamp date, osmium::user_id_type uid, const char* user, const char* text) noexcept :
|
||||||
|
m_date(date),
|
||||||
|
m_uid(uid),
|
||||||
|
m_user(user),
|
||||||
|
m_text(text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr osmium::Timestamp date() const noexcept {
|
||||||
|
return m_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr osmium::user_id_type uid() const noexcept {
|
||||||
|
return m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* user() const noexcept {
|
||||||
|
return m_user;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* text() const noexcept {
|
||||||
|
return m_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class comment_type
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(tags_handler, tags_from_iterator_pair);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(nodes_handler, nodes_from_iterator_pair);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(members_handler, members_from_iterator_pair);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(discussion_handler, comments_from_iterator_pair);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(ring_handler, outer_ring_from_iterator_pair);
|
||||||
|
OSMIUM_ATTRIBUTE_ITER(ring_handler, inner_ring_from_iterator_pair);
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(tags_handler, _tag, pair_of_cstrings)
|
||||||
|
explicit _tag(const pair_of_cstrings& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
explicit _tag(const std::pair<const char* const, const char*>& value) :
|
||||||
|
type_wrapper(pair_of_cstrings{value.first, value.second}) {}
|
||||||
|
explicit _tag(const std::pair<const char*, const char* const>& value) :
|
||||||
|
type_wrapper(pair_of_cstrings{value.first, value.second}) {}
|
||||||
|
explicit _tag(const std::pair<const char*, const char*>& value) :
|
||||||
|
type_wrapper(pair_of_cstrings{value.first, value.second}) {}
|
||||||
|
explicit _tag(const pair_of_strings& value) :
|
||||||
|
type_wrapper(std::make_pair(value.first.c_str(), value.second.c_str())) {}
|
||||||
|
explicit _tag(const char* key, const char* val) :
|
||||||
|
type_wrapper(std::make_pair(key, val)) {}
|
||||||
|
explicit _tag(const std::string& key, const std::string& val) :
|
||||||
|
type_wrapper(std::make_pair(key.c_str(), val.c_str())) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TTagIterator>
|
||||||
|
inline constexpr detail::tags_from_iterator_pair<TTagIterator> _tags(TTagIterator first, TTagIterator last) {
|
||||||
|
return detail::tags_from_iterator_pair<TTagIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::tags_from_iterator_pair<typename TContainer::const_iterator> _tags(const TContainer& container) {
|
||||||
|
return detail::tags_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using tag_ilist = std::initializer_list<std::pair<const char*, const char*>>;
|
||||||
|
inline detail::tags_from_iterator_pair<tag_ilist::const_iterator> _tags(const tag_ilist& container) {
|
||||||
|
return detail::tags_from_iterator_pair<tag_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(nodes_handler, _node, osmium::NodeRef)
|
||||||
|
constexpr explicit _node(osmium::object_id_type value) noexcept :
|
||||||
|
type_wrapper(NodeRef{value}) {}
|
||||||
|
constexpr explicit _node(const NodeRef& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TIdIterator>
|
||||||
|
inline constexpr detail::nodes_from_iterator_pair<TIdIterator> _nodes(TIdIterator first, TIdIterator last) {
|
||||||
|
return detail::nodes_from_iterator_pair<TIdIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::nodes_from_iterator_pair<typename TContainer::const_iterator> _nodes(const TContainer& container) {
|
||||||
|
return detail::nodes_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using object_id_ilist = std::initializer_list<osmium::object_id_type>;
|
||||||
|
inline detail::nodes_from_iterator_pair<object_id_ilist::const_iterator> _nodes(const object_id_ilist& container) {
|
||||||
|
return detail::nodes_from_iterator_pair<object_id_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
|
||||||
|
inline detail::nodes_from_iterator_pair<node_ref_ilist::const_iterator> _nodes(const node_ref_ilist& container) {
|
||||||
|
return detail::nodes_from_iterator_pair<node_ref_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(members_handler, _member, member_type)
|
||||||
|
constexpr explicit _member(const member_type& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
constexpr explicit _member(osmium::item_type type, osmium::object_id_type id) noexcept :
|
||||||
|
type_wrapper({type, id}) {}
|
||||||
|
constexpr explicit _member(osmium::item_type type, osmium::object_id_type id, const char* role) noexcept :
|
||||||
|
type_wrapper({type, id, role}) {}
|
||||||
|
explicit _member(osmium::item_type type, osmium::object_id_type id, const std::string& role) noexcept :
|
||||||
|
type_wrapper({type, id, role.c_str()}) {}
|
||||||
|
explicit _member(const osmium::RelationMember& member) noexcept :
|
||||||
|
type_wrapper({member.type(), member.ref(), member.role()}) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TMemberIterator>
|
||||||
|
inline constexpr detail::members_from_iterator_pair<TMemberIterator> _members(TMemberIterator first, TMemberIterator last) {
|
||||||
|
return detail::members_from_iterator_pair<TMemberIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::members_from_iterator_pair<typename TContainer::const_iterator> _members(const TContainer& container) {
|
||||||
|
return detail::members_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using member_ilist = std::initializer_list<member_type>;
|
||||||
|
inline detail::members_from_iterator_pair<member_ilist::const_iterator> _members(const member_ilist& container) {
|
||||||
|
return detail::members_from_iterator_pair<member_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _num_changes, osmium::num_changes_type);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _num_comments, osmium::num_comments_type);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _created_at, osmium::Timestamp);
|
||||||
|
OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR(changeset_handler, _closed_at, osmium::Timestamp);
|
||||||
|
|
||||||
|
OSMIUM_ATTRIBUTE(discussion_handler, _comment, comment_type)
|
||||||
|
constexpr explicit _comment(const comment_type& value) noexcept :
|
||||||
|
type_wrapper(value) {}
|
||||||
|
explicit _comment(const osmium::ChangesetComment& comment) noexcept :
|
||||||
|
type_wrapper({comment.date(), comment.uid(), comment.user(), comment.text()}) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename TCommentIterator>
|
||||||
|
inline constexpr detail::comments_from_iterator_pair<TCommentIterator> _comments(TCommentIterator first, TCommentIterator last) {
|
||||||
|
return detail::comments_from_iterator_pair<TCommentIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::comments_from_iterator_pair<typename TContainer::const_iterator> _comments(const TContainer& container) {
|
||||||
|
return detail::comments_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using comment_ilist = std::initializer_list<comment_type>;
|
||||||
|
inline detail::comments_from_iterator_pair<comment_ilist::const_iterator> _comments(const comment_ilist& container) {
|
||||||
|
return detail::comments_from_iterator_pair<comment_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename TIdIterator>
|
||||||
|
inline constexpr detail::outer_ring_from_iterator_pair<TIdIterator> _outer_ring(TIdIterator first, TIdIterator last) {
|
||||||
|
return detail::outer_ring_from_iterator_pair<TIdIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::outer_ring_from_iterator_pair<typename TContainer::const_iterator> _outer_ring(const TContainer& container) {
|
||||||
|
return detail::outer_ring_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using object_id_ilist = std::initializer_list<osmium::object_id_type>;
|
||||||
|
inline detail::outer_ring_from_iterator_pair<object_id_ilist::const_iterator> _outer_ring(const object_id_ilist& container) {
|
||||||
|
return detail::outer_ring_from_iterator_pair<object_id_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
|
||||||
|
inline detail::outer_ring_from_iterator_pair<node_ref_ilist::const_iterator> _outer_ring(const node_ref_ilist& container) {
|
||||||
|
return detail::outer_ring_from_iterator_pair<node_ref_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIdIterator>
|
||||||
|
inline constexpr detail::inner_ring_from_iterator_pair<TIdIterator> _inner_ring(TIdIterator first, TIdIterator last) {
|
||||||
|
return detail::inner_ring_from_iterator_pair<TIdIterator>(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TContainer>
|
||||||
|
inline detail::inner_ring_from_iterator_pair<typename TContainer::const_iterator> _inner_ring(const TContainer& container) {
|
||||||
|
return detail::inner_ring_from_iterator_pair<typename TContainer::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using object_id_ilist = std::initializer_list<osmium::object_id_type>;
|
||||||
|
inline detail::inner_ring_from_iterator_pair<object_id_ilist::const_iterator> _inner_ring(const object_id_ilist& container) {
|
||||||
|
return detail::inner_ring_from_iterator_pair<object_id_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
using node_ref_ilist = std::initializer_list<osmium::NodeRef>;
|
||||||
|
inline detail::inner_ring_from_iterator_pair<node_ref_ilist::const_iterator> _inner_ring(const node_ref_ilist& container) {
|
||||||
|
return detail::inner_ring_from_iterator_pair<node_ref_ilist::const_iterator>(std::begin(container), std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace attr
|
||||||
|
|
||||||
|
#undef OSMIUM_ATTRIBUTE_ITER
|
||||||
|
#undef OSMIUM_ATTRIBUTE_WITH_CONSTRUCTOR
|
||||||
|
#undef OSMIUM_ATTRIBUTE
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
struct changeset_handler : public entity_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(osmium::Changeset&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_cid id) noexcept {
|
||||||
|
changeset.set_id(id.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_num_changes num_changes) noexcept {
|
||||||
|
changeset.set_num_changes(num_changes.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_num_comments num_comments) noexcept {
|
||||||
|
changeset.set_num_comments(num_comments.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_created_at created_at) noexcept {
|
||||||
|
changeset.set_created_at(created_at.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_closed_at closed_at) noexcept {
|
||||||
|
changeset.set_closed_at(closed_at.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::Changeset& changeset, attr::_uid uid) noexcept {
|
||||||
|
changeset.set_uid(uid.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct object_handler : public entity_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(osmium::OSMObject&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_id id) noexcept {
|
||||||
|
object.set_id(id.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_version version) noexcept {
|
||||||
|
object.set_version(version.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_visible visible) noexcept {
|
||||||
|
object.set_visible(visible.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_deleted deleted) noexcept {
|
||||||
|
object.set_deleted(deleted.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_timestamp timestamp) noexcept {
|
||||||
|
object.set_timestamp(timestamp.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_cid changeset) noexcept {
|
||||||
|
object.set_changeset(changeset.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(osmium::OSMObject& object, attr::_uid uid) noexcept {
|
||||||
|
object.set_uid(uid.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // object_handler
|
||||||
|
|
||||||
|
struct node_handler : public object_handler {
|
||||||
|
|
||||||
|
using object_handler::set_value;
|
||||||
|
|
||||||
|
static void set_value(osmium::Node& node, attr::_location location) noexcept {
|
||||||
|
node.set_location(location.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // node_handler
|
||||||
|
|
||||||
|
template <typename THandler, typename TBuilder, typename... TArgs>
|
||||||
|
inline void add_basic(TBuilder& builder, const TArgs&... args) noexcept {
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(THandler::set_value(builder.object(), args), 0)...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline constexpr const char* get_user(const attr::_user& user, const TArgs&...) noexcept {
|
||||||
|
return user.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr const char* get_user() noexcept {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TFirst, typename... TRest>
|
||||||
|
inline constexpr typename std::enable_if<!std::is_same<attr::_user, TFirst>::value, const char*>::type
|
||||||
|
get_user(const TFirst&, const TRest&... args) noexcept {
|
||||||
|
return get_user(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TBuilder, typename... TArgs>
|
||||||
|
inline void add_user(TBuilder& builder, const TArgs&... args) {
|
||||||
|
builder.add_user(get_user(args...));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
|
struct tags_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(TagListBuilder&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(TagListBuilder& builder, const attr::_tag& tag) {
|
||||||
|
builder.add_tag(tag.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(TagListBuilder& builder, const attr::detail::tags_from_iterator_pair<TIterator>& tags) {
|
||||||
|
for (const auto& tag : tags) {
|
||||||
|
builder.add_tag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct tags_handler
|
||||||
|
|
||||||
|
struct nodes_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(WayNodeListBuilder&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(WayNodeListBuilder& builder, const attr::_node& node_ref) {
|
||||||
|
builder.add_node_ref(node_ref.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(WayNodeListBuilder& builder, const attr::detail::nodes_from_iterator_pair<TIterator>& nodes) {
|
||||||
|
for (const auto& ref : nodes) {
|
||||||
|
builder.add_node_ref(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct nodes_handler
|
||||||
|
|
||||||
|
struct members_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(RelationMemberListBuilder&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(RelationMemberListBuilder& builder, const attr::_member& member) {
|
||||||
|
builder.add_member(member.value.type(), member.value.ref(), member.value.role());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(RelationMemberListBuilder& builder, const attr::detail::members_from_iterator_pair<TIterator>& members) {
|
||||||
|
for (const auto& member : members) {
|
||||||
|
builder.add_member(member.type(), member.ref(), member.role());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct members_handler
|
||||||
|
|
||||||
|
struct discussion_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(ChangesetDiscussionBuilder&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(ChangesetDiscussionBuilder& builder, const attr::_comment& comment) {
|
||||||
|
builder.add_comment(comment.value.date(), comment.value.uid(), comment.value.user());
|
||||||
|
builder.add_comment_text(comment.value.text());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(ChangesetDiscussionBuilder& builder, const attr::detail::comments_from_iterator_pair<TIterator>& comments) {
|
||||||
|
for (const auto& comment : comments) {
|
||||||
|
builder.add_comment(comment.date(), comment.uid(), comment.user());
|
||||||
|
builder.add_comment_text(comment.text());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct discussion_handler
|
||||||
|
|
||||||
|
struct ring_handler {
|
||||||
|
|
||||||
|
template <typename TDummy>
|
||||||
|
static void set_value(AreaBuilder&, const TDummy&) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(AreaBuilder& parent, const attr::detail::outer_ring_from_iterator_pair<TIterator>& nodes) {
|
||||||
|
OuterRingBuilder builder(parent.buffer(), &parent);
|
||||||
|
for (const auto& ref : nodes) {
|
||||||
|
builder.add_node_ref(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIterator>
|
||||||
|
static void set_value(AreaBuilder& parent, const attr::detail::inner_ring_from_iterator_pair<TIterator>& nodes) {
|
||||||
|
InnerRingBuilder builder(parent.buffer(), &parent);
|
||||||
|
for (const auto& ref : nodes) {
|
||||||
|
builder.add_node_ref(ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct ring_handler
|
||||||
|
|
||||||
|
// ==============================================================
|
||||||
|
|
||||||
|
template <typename TBuilder, typename THandler, typename... TArgs>
|
||||||
|
inline typename std::enable_if<!is_handled_by<THandler, TArgs...>::value>::type
|
||||||
|
add_list(osmium::builder::Builder&, const TArgs&...) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TBuilder, typename THandler, typename... TArgs>
|
||||||
|
inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>::type
|
||||||
|
add_list(osmium::builder::Builder& parent, const TArgs&... args) {
|
||||||
|
TBuilder builder(parent.buffer(), &parent);
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(THandler::set_value(builder, args), 0)...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct any_node_handlers : public node_handler, public tags_handler {};
|
||||||
|
struct any_way_handlers : public object_handler, public tags_handler, public nodes_handler {};
|
||||||
|
struct any_relation_handlers : public object_handler, public tags_handler, public members_handler {};
|
||||||
|
struct any_area_handlers : public object_handler, public tags_handler, public ring_handler {};
|
||||||
|
struct any_changeset_handlers : public changeset_handler, public tags_handler, public discussion_handler {};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a node using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the node will be added.
|
||||||
|
* @param args The attributes of the node.
|
||||||
|
* @returns The position in the buffer where this node was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_node(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_node() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()");
|
||||||
|
|
||||||
|
NodeBuilder builder(buffer);
|
||||||
|
|
||||||
|
detail::add_basic<detail::node_handler>(builder, args...);
|
||||||
|
detail::add_user(builder, args...);
|
||||||
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a way using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the way will be added.
|
||||||
|
* @param args The attributes of the way.
|
||||||
|
* @returns The position in the buffer where this way was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_way(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_way() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()");
|
||||||
|
|
||||||
|
WayBuilder builder(buffer);
|
||||||
|
|
||||||
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
|
detail::add_user(builder, args...);
|
||||||
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
detail::add_list<WayNodeListBuilder, detail::nodes_handler>(builder, args...);
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a relation using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the relation will be added.
|
||||||
|
* @param args The attributes of the relation.
|
||||||
|
* @returns The position in the buffer where this relation was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_relation(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_relation() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()");
|
||||||
|
|
||||||
|
RelationBuilder builder(buffer);
|
||||||
|
|
||||||
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
|
detail::add_user(builder, args...);
|
||||||
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
detail::add_list<RelationMemberListBuilder, detail::members_handler>(builder, args...);
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a changeset using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the changeset will be added.
|
||||||
|
* @param args The attributes of the changeset.
|
||||||
|
* @returns The position in the buffer where this changeset was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_changeset(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_changeset() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()");
|
||||||
|
|
||||||
|
ChangesetBuilder builder(buffer);
|
||||||
|
|
||||||
|
detail::add_basic<detail::changeset_handler>(builder, args...);
|
||||||
|
detail::add_user(builder, args...);
|
||||||
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
detail::add_list<ChangesetDiscussionBuilder, detail::discussion_handler>(builder, args...);
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a area using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the area will be added.
|
||||||
|
* @param args The attributes of the area.
|
||||||
|
* @returns The position in the buffer where this area was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_area(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_area() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()");
|
||||||
|
|
||||||
|
AreaBuilder builder(buffer);
|
||||||
|
|
||||||
|
detail::add_basic<detail::object_handler>(builder, args...);
|
||||||
|
detail::add_user(builder, args...);
|
||||||
|
detail::add_list<TagListBuilder, detail::tags_handler>(builder, args...);
|
||||||
|
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(detail::ring_handler::set_value(builder, args), 0)...
|
||||||
|
};
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a WayNodeList using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the list will be added.
|
||||||
|
* @param args The contents of the list.
|
||||||
|
* @returns The position in the buffer where this list was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_way_node_list(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_way_node_list() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::nodes_handler, TArgs...>::value, "Attribute not allowed in add_way_node_list()");
|
||||||
|
|
||||||
|
{
|
||||||
|
WayNodeListBuilder builder(buffer);
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(detail::nodes_handler::set_value(builder, args), 0)...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TagList using the given arguments and add it to the given buffer.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer to which the list will be added.
|
||||||
|
* @param args The contents of the list.
|
||||||
|
* @returns The position in the buffer where this list was added.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
inline size_t add_tag_list(osmium::memory::Buffer& buffer, const TArgs&... args) {
|
||||||
|
static_assert(sizeof...(args) > 0, "add_tag_list() must have buffer and at least one additional argument");
|
||||||
|
static_assert(detail::are_all_handled_by<detail::tags_handler, TArgs...>::value, "Attribute not allowed in add_tag_list()");
|
||||||
|
|
||||||
|
{
|
||||||
|
TagListBuilder builder(buffer);
|
||||||
|
(void)std::initializer_list<int>{
|
||||||
|
(detail::tags_handler::set_value(builder, args), 0)...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace builder
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_BUILDER_ATTR_HPP
|
237
include/osmium/builder/builder.hpp
Normal file
237
include/osmium/builder/builder.hpp
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
#ifndef OSMIUM_BUILDER_BUILDER_HPP
|
||||||
|
#define OSMIUM_BUILDER_BUILDER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/memory/item.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/util/cast.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Classes for building OSM objects and other items in buffers
|
||||||
|
*/
|
||||||
|
namespace builder {
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
|
||||||
|
osmium::memory::Buffer& m_buffer;
|
||||||
|
Builder* m_parent;
|
||||||
|
size_t m_item_offset;
|
||||||
|
|
||||||
|
Builder(const Builder&) = delete;
|
||||||
|
Builder(Builder&&) = delete;
|
||||||
|
|
||||||
|
Builder& operator=(const Builder&) = delete;
|
||||||
|
Builder& operator=(Builder&&) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, osmium::memory::item_size_type size) :
|
||||||
|
m_buffer(buffer),
|
||||||
|
m_parent(parent),
|
||||||
|
m_item_offset(buffer.written()) {
|
||||||
|
m_buffer.reserve_space(size);
|
||||||
|
assert(buffer.is_aligned());
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->add_size(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Builder() = default;
|
||||||
|
|
||||||
|
osmium::memory::Item& item() const {
|
||||||
|
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add padding to buffer (if needed) to align data properly.
|
||||||
|
*
|
||||||
|
* This calculates how many padding bytes are needed and adds
|
||||||
|
* as many zero bytes to the buffer. It also adds this number
|
||||||
|
* to the size of the current item (if the "self" param is
|
||||||
|
* true) and recursively to all the parent items.
|
||||||
|
*
|
||||||
|
* @param self If true add number of padding bytes to size
|
||||||
|
* of current item. Size is always added to
|
||||||
|
* parent item (if any).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void add_padding(bool self = false) {
|
||||||
|
auto padding = osmium::memory::align_bytes - (size() % osmium::memory::align_bytes);
|
||||||
|
if (padding != osmium::memory::align_bytes) {
|
||||||
|
std::fill_n(m_buffer.reserve_space(padding), padding, 0);
|
||||||
|
if (self) {
|
||||||
|
add_size(padding);
|
||||||
|
} else if (m_parent) {
|
||||||
|
m_parent->add_size(padding);
|
||||||
|
assert(m_parent->size() % osmium::memory::align_bytes == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_size(uint32_t size) {
|
||||||
|
item().add_size(size);
|
||||||
|
if (m_parent) {
|
||||||
|
m_parent->add_size(size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t size() const noexcept {
|
||||||
|
return item().byte_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_item(const osmium::memory::Item* item) {
|
||||||
|
unsigned char* target = m_buffer.reserve_space(item->padded_size());
|
||||||
|
std::copy_n(reinterpret_cast<const unsigned char*>(item), item->padded_size(), target);
|
||||||
|
add_size(item->padded_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reserve space for an object of class T in buffer and return
|
||||||
|
* pointer to it.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T* reserve_space_for() {
|
||||||
|
assert(m_buffer.is_aligned());
|
||||||
|
return reinterpret_cast<T*>(m_buffer.reserve_space(sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append data to buffer.
|
||||||
|
*
|
||||||
|
* @param data Pointer to data.
|
||||||
|
* @param length Length of data in bytes. If data is a
|
||||||
|
* \0-terminated string, length must contain the
|
||||||
|
* \0 byte.
|
||||||
|
* @returns The number of bytes appended (length).
|
||||||
|
*/
|
||||||
|
osmium::memory::item_size_type append(const char* data, const osmium::memory::item_size_type length) {
|
||||||
|
unsigned char* target = m_buffer.reserve_space(length);
|
||||||
|
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append \0-terminated string to buffer.
|
||||||
|
*
|
||||||
|
* @param str \0-terminated string.
|
||||||
|
* @returns The number of bytes appended (strlen(str) + 1).
|
||||||
|
*/
|
||||||
|
osmium::memory::item_size_type append(const char* str) {
|
||||||
|
return append(str, static_cast<osmium::memory::item_size_type>(std::strlen(str) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append '\0' to the buffer.
|
||||||
|
*
|
||||||
|
* @returns The number of bytes appended (always 1).
|
||||||
|
*/
|
||||||
|
osmium::memory::item_size_type append_zero() {
|
||||||
|
*m_buffer.reserve_space(1) = '\0';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the buffer this builder is using.
|
||||||
|
osmium::memory::Buffer& buffer() noexcept {
|
||||||
|
return m_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Builder
|
||||||
|
|
||||||
|
template <typename TItem>
|
||||||
|
class ObjectBuilder : public Builder {
|
||||||
|
|
||||||
|
static_assert(std::is_base_of<osmium::memory::Item, TItem>::value, "ObjectBuilder can only build objects derived from osmium::memory::Item");
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
Builder(buffer, parent, sizeof(TItem)) {
|
||||||
|
new (&item()) TItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
TItem& object() noexcept {
|
||||||
|
return static_cast<TItem&>(item());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add user name to buffer.
|
||||||
|
*
|
||||||
|
* @param user Pointer to user name.
|
||||||
|
* @param length Length of user name (without \0 termination).
|
||||||
|
*/
|
||||||
|
void add_user(const char* user, const string_size_type length) {
|
||||||
|
object().set_user_size(length + 1);
|
||||||
|
add_size(append(user, length) + append_zero());
|
||||||
|
add_padding(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add user name to buffer.
|
||||||
|
*
|
||||||
|
* @param user Pointer to \0-terminated user name.
|
||||||
|
*/
|
||||||
|
void add_user(const char* user) {
|
||||||
|
add_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add user name to buffer.
|
||||||
|
*
|
||||||
|
* @param user User name.
|
||||||
|
*/
|
||||||
|
void add_user(const std::string& user) {
|
||||||
|
add_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ObjectBuilder
|
||||||
|
|
||||||
|
} // namespace builder
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_BUILDER_BUILDER_HPP
|
120
include/osmium/builder/builder_helper.hpp
Normal file
120
include/osmium/builder/builder_helper.hpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#ifndef OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
||||||
|
#define OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/builder/osm_object_builder.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
class NodeRef;
|
||||||
|
class TagList;
|
||||||
|
class WayNodeList;
|
||||||
|
|
||||||
|
namespace builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use osmium::builder::add_way_node_list() instead.
|
||||||
|
*/
|
||||||
|
OSMIUM_DEPRECATED inline const osmium::WayNodeList& build_way_node_list(osmium::memory::Buffer& buffer, const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||||
|
size_t pos = buffer.committed();
|
||||||
|
{
|
||||||
|
osmium::builder::WayNodeListBuilder wnl_builder(buffer);
|
||||||
|
for (const auto& node_ref : nodes) {
|
||||||
|
wnl_builder.add_node_ref(node_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.commit();
|
||||||
|
return buffer.get<const osmium::WayNodeList>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use osmium::builder::add_tag_list() instead.
|
||||||
|
*/
|
||||||
|
inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||||
|
size_t pos = buffer.committed();
|
||||||
|
{
|
||||||
|
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||||
|
for (const auto& p : tags) {
|
||||||
|
tl_builder.add_tag(p.first, p.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.commit();
|
||||||
|
return buffer.get<const osmium::TagList>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use osmium::builder::add_tag_list() instead.
|
||||||
|
*/
|
||||||
|
inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& tags) {
|
||||||
|
size_t pos = buffer.committed();
|
||||||
|
{
|
||||||
|
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||||
|
for (const auto& p : tags) {
|
||||||
|
tl_builder.add_tag(p.first, p.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buffer.commit();
|
||||||
|
return buffer.get<const osmium::TagList>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use osmium::builder::add_tag_list() instead.
|
||||||
|
*/
|
||||||
|
inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
|
||||||
|
size_t pos = buffer.committed();
|
||||||
|
{
|
||||||
|
osmium::builder::TagListBuilder tl_builder(buffer);
|
||||||
|
func(tl_builder);
|
||||||
|
}
|
||||||
|
buffer.commit();
|
||||||
|
return buffer.get<const osmium::TagList>(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace builder
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_BUILDER_BUILDER_HELPER_HPP
|
407
include/osmium/builder/osm_object_builder.hpp
Normal file
407
include/osmium/builder/osm_object_builder.hpp
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
#ifndef OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
||||||
|
#define OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <limits>
|
||||||
|
#include <new>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/builder/builder.hpp>
|
||||||
|
#include <osmium/osm.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/object.hpp>
|
||||||
|
#include <osmium/osm/tag.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace memory {
|
||||||
|
class Buffer;
|
||||||
|
} // namespace memory
|
||||||
|
|
||||||
|
namespace builder {
|
||||||
|
|
||||||
|
class TagListBuilder : public ObjectBuilder<TagList> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
ObjectBuilder<TagList>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~TagListBuilder() {
|
||||||
|
add_padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param key Tag key (0-terminated string).
|
||||||
|
* @param value Tag value (0-terminated string).
|
||||||
|
*/
|
||||||
|
void add_tag(const char* key, const char* value) {
|
||||||
|
if (std::strlen(key) > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag key is too long");
|
||||||
|
}
|
||||||
|
if (std::strlen(value) > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag value is too long");
|
||||||
|
}
|
||||||
|
add_size(append(key) + append(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param key Pointer to tag key.
|
||||||
|
* @param key_length Length of key (not including the \0 byte).
|
||||||
|
* @param value Pointer to tag value.
|
||||||
|
* @param value_length Length of value (not including the \0 byte).
|
||||||
|
*/
|
||||||
|
void add_tag(const char* key, const size_t key_length, const char* value, const size_t value_length) {
|
||||||
|
if (key_length > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag key is too long");
|
||||||
|
}
|
||||||
|
if (value_length > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag value is too long");
|
||||||
|
}
|
||||||
|
add_size(append(key, osmium::memory::item_size_type(key_length)) + append_zero() +
|
||||||
|
append(value, osmium::memory::item_size_type(value_length)) + append_zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param key Tag key.
|
||||||
|
* @param value Tag value.
|
||||||
|
*/
|
||||||
|
void add_tag(const std::string& key, const std::string& value) {
|
||||||
|
if (key.size() > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag key is too long");
|
||||||
|
}
|
||||||
|
if (value.size() > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM tag value is too long");
|
||||||
|
}
|
||||||
|
add_size(append(key.data(), osmium::memory::item_size_type(key.size()) + 1) +
|
||||||
|
append(value.data(), osmium::memory::item_size_type(value.size()) + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param tag Tag.
|
||||||
|
*/
|
||||||
|
void add_tag(const osmium::Tag& tag) {
|
||||||
|
add_size(append(tag.key()) + append(tag.value()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param tag Pair of key/value 0-terminated strings.
|
||||||
|
*/
|
||||||
|
void add_tag(const std::pair<const char* const, const char* const>& tag) {
|
||||||
|
add_tag(tag.first, tag.second);
|
||||||
|
}
|
||||||
|
void add_tag(const std::pair<const char* const, const char*>& tag) {
|
||||||
|
add_tag(tag.first, tag.second);
|
||||||
|
}
|
||||||
|
void add_tag(const std::pair<const char*, const char* const>& tag) {
|
||||||
|
add_tag(tag.first, tag.second);
|
||||||
|
}
|
||||||
|
void add_tag(const std::pair<const char*, const char*>& tag) {
|
||||||
|
add_tag(tag.first, tag.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add tag to buffer.
|
||||||
|
*
|
||||||
|
* @param tag Pair of std::string references.
|
||||||
|
*/
|
||||||
|
void add_tag(const std::pair<const std::string&, const std::string&>& tag) {
|
||||||
|
add_tag(tag.first, tag.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class TagListBuilder
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class NodeRefListBuilder : public ObjectBuilder<T> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
ObjectBuilder<T>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~NodeRefListBuilder() {
|
||||||
|
static_cast<Builder*>(this)->add_padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_node_ref(const NodeRef& node_ref) {
|
||||||
|
new (static_cast<Builder*>(this)->reserve_space_for<osmium::NodeRef>()) osmium::NodeRef(node_ref);
|
||||||
|
static_cast<Builder*>(this)->add_size(sizeof(osmium::NodeRef));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_node_ref(const object_id_type ref, const osmium::Location& location = Location{}) {
|
||||||
|
add_node_ref(NodeRef(ref, location));
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class NodeRefListBuilder
|
||||||
|
|
||||||
|
typedef NodeRefListBuilder<WayNodeList> WayNodeListBuilder;
|
||||||
|
typedef NodeRefListBuilder<OuterRing> OuterRingBuilder;
|
||||||
|
typedef NodeRefListBuilder<InnerRing> InnerRingBuilder;
|
||||||
|
|
||||||
|
class RelationMemberListBuilder : public ObjectBuilder<RelationMemberList> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add role to buffer.
|
||||||
|
*
|
||||||
|
* @param member Relation member object where the length of the role
|
||||||
|
* will be set.
|
||||||
|
* @param role The role.
|
||||||
|
* @param length Length of role (without \0 termination).
|
||||||
|
* @throws std:length_error If role is longer than osmium::max_osm_string_length
|
||||||
|
*/
|
||||||
|
void add_role(osmium::RelationMember& member, const char* role, const size_t length) {
|
||||||
|
if (length > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM relation member role is too long");
|
||||||
|
}
|
||||||
|
member.set_role_size(osmium::string_size_type(length) + 1);
|
||||||
|
add_size(append(role, osmium::memory::item_size_type(length)) + append_zero());
|
||||||
|
add_padding(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
ObjectBuilder<RelationMemberList>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~RelationMemberListBuilder() {
|
||||||
|
add_padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a member to the relation.
|
||||||
|
*
|
||||||
|
* @param type The type (node, way, or relation).
|
||||||
|
* @param ref The ID of the member.
|
||||||
|
* @param role The role of the member.
|
||||||
|
* @param role_length Length of the role (without \0 termination).
|
||||||
|
* @param full_member Optional pointer to the member object. If it
|
||||||
|
* is available a copy will be added to the
|
||||||
|
* relation.
|
||||||
|
* @throws std:length_error If role_length is greater than
|
||||||
|
* osmium::max_osm_string_length
|
||||||
|
*/
|
||||||
|
void add_member(osmium::item_type type, object_id_type ref, const char* role, const size_t role_length, const osmium::OSMObject* full_member = nullptr) {
|
||||||
|
osmium::RelationMember* member = reserve_space_for<osmium::RelationMember>();
|
||||||
|
new (member) osmium::RelationMember(ref, type, full_member != nullptr);
|
||||||
|
add_size(sizeof(RelationMember));
|
||||||
|
add_role(*member, role, role_length);
|
||||||
|
if (full_member) {
|
||||||
|
add_item(full_member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a member to the relation.
|
||||||
|
*
|
||||||
|
* @param type The type (node, way, or relation).
|
||||||
|
* @param ref The ID of the member.
|
||||||
|
* @param role The role of the member (\0 terminated string).
|
||||||
|
* @param full_member Optional pointer to the member object. If it
|
||||||
|
* is available a copy will be added to the
|
||||||
|
* relation.
|
||||||
|
* @throws std:length_error If role is longer than osmium::max_osm_string_length
|
||||||
|
*/
|
||||||
|
void add_member(osmium::item_type type, object_id_type ref, const char* role, const osmium::OSMObject* full_member = nullptr) {
|
||||||
|
add_member(type, ref, role, std::strlen(role), full_member);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a member to the relation.
|
||||||
|
*
|
||||||
|
* @param type The type (node, way, or relation).
|
||||||
|
* @param ref The ID of the member.
|
||||||
|
* @param role The role of the member.
|
||||||
|
* @param full_member Optional pointer to the member object. If it
|
||||||
|
* is available a copy will be added to the
|
||||||
|
* relation.
|
||||||
|
* @throws std:length_error If role is longer than osmium::max_osm_string_length
|
||||||
|
*/
|
||||||
|
void add_member(osmium::item_type type, object_id_type ref, const std::string& role, const osmium::OSMObject* full_member = nullptr) {
|
||||||
|
add_member(type, ref, role.data(), role.size(), full_member);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class RelationMemberListBuilder
|
||||||
|
|
||||||
|
class ChangesetDiscussionBuilder : public ObjectBuilder<ChangesetDiscussion> {
|
||||||
|
|
||||||
|
osmium::ChangesetComment* m_comment = nullptr;
|
||||||
|
|
||||||
|
void add_user(osmium::ChangesetComment& comment, const char* user, const size_t length) {
|
||||||
|
if (length > osmium::max_osm_string_length) {
|
||||||
|
throw std::length_error("OSM user name is too long");
|
||||||
|
}
|
||||||
|
comment.set_user_size(osmium::string_size_type(length) + 1);
|
||||||
|
add_size(append(user, osmium::memory::item_size_type(length)) + append_zero());
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_text(osmium::ChangesetComment& comment, const char* text, const size_t length) {
|
||||||
|
// XXX There is no limit on the length of a comment text. We
|
||||||
|
// limit it here to 2^16-2 characters, because that's all that
|
||||||
|
// will fit into our internal data structure. This is not ideal,
|
||||||
|
// and will have to be discussed and cleared up.
|
||||||
|
if (length > std::numeric_limits<osmium::string_size_type>::max() - 1) {
|
||||||
|
throw std::length_error("OSM changeset comment is too long");
|
||||||
|
}
|
||||||
|
comment.set_text_size(osmium::string_size_type(length) + 1);
|
||||||
|
add_size(append(text, osmium::memory::item_size_type(length)) + append_zero());
|
||||||
|
add_padding(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
ObjectBuilder<ChangesetDiscussion>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~ChangesetDiscussionBuilder() {
|
||||||
|
assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||||
|
add_padding();
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_comment(osmium::Timestamp date, osmium::user_id_type uid, const char* user) {
|
||||||
|
assert(!m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||||
|
m_comment = reserve_space_for<osmium::ChangesetComment>();
|
||||||
|
new (m_comment) osmium::ChangesetComment(date, uid);
|
||||||
|
add_size(sizeof(ChangesetComment));
|
||||||
|
add_user(*m_comment, user, std::strlen(user));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_comment_text(const char* text) {
|
||||||
|
assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||||
|
add_text(*m_comment, text, std::strlen(text));
|
||||||
|
m_comment = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_comment_text(const std::string& text) {
|
||||||
|
assert(m_comment && "You have to always call both add_comment() and then add_comment_text() in that order for each comment!");
|
||||||
|
add_text(*m_comment, text.c_str(), text.size());
|
||||||
|
m_comment = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ChangesetDiscussionBuilder
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class OSMObjectBuilder : public ObjectBuilder<T> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
ObjectBuilder<T>(buffer, parent) {
|
||||||
|
static_cast<Builder*>(this)->reserve_space_for<string_size_type>();
|
||||||
|
static_cast<Builder*>(this)->add_size(sizeof(string_size_type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||||
|
osmium::builder::TagListBuilder tl_builder(static_cast<Builder*>(this)->buffer(), this);
|
||||||
|
for (const auto& p : tags) {
|
||||||
|
tl_builder.add_tag(p.first, p.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class OSMObjectBuilder
|
||||||
|
|
||||||
|
typedef OSMObjectBuilder<osmium::Node> NodeBuilder;
|
||||||
|
typedef OSMObjectBuilder<osmium::Relation> RelationBuilder;
|
||||||
|
|
||||||
|
class WayBuilder : public OSMObjectBuilder<osmium::Way> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
OSMObjectBuilder<osmium::Way>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_node_refs(const std::initializer_list<osmium::NodeRef>& nodes) {
|
||||||
|
osmium::builder::WayNodeListBuilder builder(buffer(), this);
|
||||||
|
for (const auto& node_ref : nodes) {
|
||||||
|
builder.add_node_ref(node_ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class WayBuilder
|
||||||
|
|
||||||
|
class AreaBuilder : public OSMObjectBuilder<osmium::Area> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||||
|
OSMObjectBuilder<osmium::Area>(buffer, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize area attributes from the attributes of the given object.
|
||||||
|
*/
|
||||||
|
void initialize_from_object(const osmium::OSMObject& source) {
|
||||||
|
osmium::Area& area = object();
|
||||||
|
area.set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
||||||
|
area.set_version(source.version());
|
||||||
|
area.set_changeset(source.changeset());
|
||||||
|
area.set_timestamp(source.timestamp());
|
||||||
|
area.set_visible(source.visible());
|
||||||
|
area.set_uid(source.uid());
|
||||||
|
|
||||||
|
add_user(source.user());
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class AreaBuilder
|
||||||
|
|
||||||
|
typedef ObjectBuilder<osmium::Changeset> ChangesetBuilder;
|
||||||
|
|
||||||
|
} // namespace builder
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
66
include/osmium/diff_handler.hpp
Normal file
66
include/osmium/diff_handler.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef OSMIUM_DIFF_HANDLER_HPP
|
||||||
|
#define OSMIUM_DIFF_HANDLER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/osm/diff_object.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Osmium diff handlers provide access to differences between OSM object versions
|
||||||
|
*/
|
||||||
|
namespace diff_handler {
|
||||||
|
|
||||||
|
class DiffHandler {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DiffHandler() = default;
|
||||||
|
|
||||||
|
void node(const osmium::DiffNode&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::DiffWay&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::DiffRelation&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class DiffHandler
|
||||||
|
|
||||||
|
} // namespace diff_handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_DIFF_HANDLER_HPP
|
135
include/osmium/diff_iterator.hpp
Normal file
135
include/osmium/diff_iterator.hpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#ifndef OSMIUM_DIFF_ITERATOR_HPP
|
||||||
|
#define OSMIUM_DIFF_ITERATOR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <osmium/osm/diff_object.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
class OSMObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An input iterator wrapping any iterator over OSMObjects. When
|
||||||
|
* dereferenced it will yield DiffObject objects pointing to the
|
||||||
|
* underlying OSMObjects.
|
||||||
|
*/
|
||||||
|
template <typename TBasicIterator>
|
||||||
|
class DiffIterator : public std::iterator<std::input_iterator_tag, const osmium::DiffObject> {
|
||||||
|
|
||||||
|
static_assert(std::is_base_of<osmium::OSMObject, typename TBasicIterator::value_type>::value, "TBasicIterator::value_type must derive from osmium::OSMObject");
|
||||||
|
|
||||||
|
TBasicIterator m_prev;
|
||||||
|
TBasicIterator m_curr;
|
||||||
|
TBasicIterator m_next;
|
||||||
|
|
||||||
|
const TBasicIterator m_end;
|
||||||
|
|
||||||
|
mutable osmium::DiffObject m_diff;
|
||||||
|
|
||||||
|
void set_diff() const noexcept {
|
||||||
|
assert(m_curr != m_end);
|
||||||
|
|
||||||
|
bool use_curr_for_prev = m_prev->type() != m_curr->type() || m_prev->id() != m_curr->id();
|
||||||
|
bool use_curr_for_next = m_next == m_end || m_next->type() != m_curr->type() || m_next->id() != m_curr->id();
|
||||||
|
|
||||||
|
m_diff = std::move(osmium::DiffObject{
|
||||||
|
*(use_curr_for_prev ? m_curr : m_prev),
|
||||||
|
*m_curr,
|
||||||
|
*(use_curr_for_next ? m_curr : m_next)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DiffIterator(TBasicIterator begin, TBasicIterator end) :
|
||||||
|
m_prev(begin),
|
||||||
|
m_curr(begin),
|
||||||
|
m_next(begin == end ? begin : ++begin),
|
||||||
|
m_end(std::move(end)),
|
||||||
|
m_diff() {
|
||||||
|
}
|
||||||
|
|
||||||
|
DiffIterator& operator++() {
|
||||||
|
m_prev = std::move(m_curr);
|
||||||
|
m_curr = m_next;
|
||||||
|
|
||||||
|
if (m_next != m_end) {
|
||||||
|
++m_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
DiffIterator operator++(int) {
|
||||||
|
DiffIterator tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const DiffIterator& rhs) const noexcept {
|
||||||
|
return m_curr == rhs.m_curr && m_end == rhs.m_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const DiffIterator& rhs) const noexcept {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
reference operator*() const noexcept {
|
||||||
|
set_diff();
|
||||||
|
return m_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer operator->() const noexcept {
|
||||||
|
set_diff();
|
||||||
|
return &m_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class DiffIterator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a DiffIterator based on the given iterators.
|
||||||
|
*/
|
||||||
|
template <typename TBasicIterator>
|
||||||
|
inline DiffIterator<TBasicIterator> make_diff_iterator(TBasicIterator begin,
|
||||||
|
TBasicIterator end) {
|
||||||
|
return DiffIterator<TBasicIterator>{begin, end};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_DIFF_ITERATOR_HPP
|
104
include/osmium/diff_visitor.hpp
Normal file
104
include/osmium/diff_visitor.hpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#ifndef OSMIUM_DIFF_VISITOR_HPP
|
||||||
|
#define OSMIUM_DIFF_VISITOR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/diff_iterator.hpp>
|
||||||
|
#include <osmium/io/input_iterator.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/diff_object.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename THandler>
|
||||||
|
inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler) {
|
||||||
|
switch (diff.type()) {
|
||||||
|
case osmium::item_type::node:
|
||||||
|
handler.node(static_cast<const osmium::DiffNode&>(diff));
|
||||||
|
break;
|
||||||
|
case osmium::item_type::way:
|
||||||
|
handler.way(static_cast<const osmium::DiffWay&>(diff));
|
||||||
|
break;
|
||||||
|
case osmium::item_type::relation:
|
||||||
|
handler.relation(static_cast<const osmium::DiffRelation&>(diff));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw osmium::unknown_type();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename THandler, typename... TRest>
|
||||||
|
inline void apply_diff_iterator_recurse(const osmium::DiffObject& diff, THandler& handler, TRest&... more) {
|
||||||
|
apply_diff_iterator_recurse(diff, handler);
|
||||||
|
apply_diff_iterator_recurse(diff, more...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TIterator, typename... THandlers>
|
||||||
|
inline void apply_diff(TIterator it, TIterator end, THandlers&... handlers) {
|
||||||
|
using diff_iterator = osmium::DiffIterator<TIterator>;
|
||||||
|
|
||||||
|
diff_iterator dit(it, end);
|
||||||
|
diff_iterator dend(end, end);
|
||||||
|
|
||||||
|
for (; dit != dend; ++dit) {
|
||||||
|
detail::apply_diff_iterator_recurse(*dit, handlers...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class OSMObject;
|
||||||
|
|
||||||
|
template <typename TSource, typename... THandlers>
|
||||||
|
inline void apply_diff(TSource& source, THandlers&... handlers) {
|
||||||
|
apply_diff(osmium::io::InputIterator<TSource, osmium::OSMObject> {source},
|
||||||
|
osmium::io::InputIterator<TSource, osmium::OSMObject> {},
|
||||||
|
handlers...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... THandlers>
|
||||||
|
inline void apply_diff(osmium::memory::Buffer& buffer, THandlers&... handlers) {
|
||||||
|
apply_diff(buffer.begin(), buffer.end(), handlers...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... THandlers>
|
||||||
|
inline void apply_diff(const osmium::memory::Buffer& buffer, THandlers&... handlers) {
|
||||||
|
apply_diff(buffer.cbegin(), buffer.cend(), handlers...);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_DIFF_VISITOR_HPP
|
190
include/osmium/dynamic_handler.hpp
Normal file
190
include/osmium/dynamic_handler.hpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#ifndef OSMIUM_DYNAMIC_HANDLER_HPP
|
||||||
|
#define OSMIUM_DYNAMIC_HANDLER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/fwd.hpp>
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class HandlerWrapperBase {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~HandlerWrapperBase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void node(const osmium::Node&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void way(const osmium::Way&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void relation(const osmium::Relation&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void area(const osmium::Area&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void changeset(const osmium::Changeset&) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void flush() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class HandlerWrapperBase
|
||||||
|
|
||||||
|
|
||||||
|
// The following uses trick from
|
||||||
|
// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
|
||||||
|
// to either call handler style functions or visitor style operator().
|
||||||
|
|
||||||
|
#define OSMIUM_DYNAMIC_HANDLER_DISPATCH(_name_, _type_) \
|
||||||
|
template <typename THandler> \
|
||||||
|
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, int) -> decltype(handler._name_(object), void()) { \
|
||||||
|
handler._name_(object); \
|
||||||
|
} \
|
||||||
|
template <typename THandler> \
|
||||||
|
auto _name_##_dispatch(THandler& handler, const osmium::_type_& object, long) -> decltype(handler(object), void()) { \
|
||||||
|
handler(object); \
|
||||||
|
}
|
||||||
|
|
||||||
|
OSMIUM_DYNAMIC_HANDLER_DISPATCH(node, Node)
|
||||||
|
OSMIUM_DYNAMIC_HANDLER_DISPATCH(way, Way)
|
||||||
|
OSMIUM_DYNAMIC_HANDLER_DISPATCH(relation, Relation)
|
||||||
|
OSMIUM_DYNAMIC_HANDLER_DISPATCH(changeset, Changeset)
|
||||||
|
OSMIUM_DYNAMIC_HANDLER_DISPATCH(area, Area)
|
||||||
|
|
||||||
|
template <typename THandler>
|
||||||
|
auto flush_dispatch(THandler& handler, int) -> decltype(handler.flush(), void()) {
|
||||||
|
handler.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename THandler>
|
||||||
|
void flush_dispatch(THandler&, long) {}
|
||||||
|
|
||||||
|
template <typename THandler>
|
||||||
|
class HandlerWrapper : public HandlerWrapperBase {
|
||||||
|
|
||||||
|
THandler m_handler;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
template <typename... TArgs>
|
||||||
|
HandlerWrapper(TArgs&&... args) :
|
||||||
|
m_handler(std::forward<TArgs>(args)...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) final {
|
||||||
|
node_dispatch(m_handler, node, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) final {
|
||||||
|
way_dispatch(m_handler, way, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) final {
|
||||||
|
relation_dispatch(m_handler, relation, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(const osmium::Area& area) final {
|
||||||
|
area_dispatch(m_handler, area, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset(const osmium::Changeset& changeset) final {
|
||||||
|
changeset_dispatch(m_handler, changeset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() final {
|
||||||
|
flush_dispatch(m_handler, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class HandlerWrapper
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
class DynamicHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
typedef std::unique_ptr<osmium::handler::detail::HandlerWrapperBase> impl_ptr;
|
||||||
|
impl_ptr m_impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DynamicHandler() :
|
||||||
|
m_impl(impl_ptr(new osmium::handler::detail::HandlerWrapperBase)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename THandler, typename... TArgs>
|
||||||
|
void set(TArgs&&... args) {
|
||||||
|
m_impl = impl_ptr(new osmium::handler::detail::HandlerWrapper<THandler>(std::forward<TArgs>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
m_impl->node(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
m_impl->way(way);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
m_impl->relation(relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(const osmium::Area& area) {
|
||||||
|
m_impl->area(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset(const osmium::Changeset& changeset) {
|
||||||
|
m_impl->changeset(changeset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
m_impl->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class DynamicHandler
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_DYNAMIC_HANDLER_HPP
|
137
include/osmium/experimental/flex_reader.hpp
Normal file
137
include/osmium/experimental/flex_reader.hpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#ifndef OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
|
||||||
|
#define OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/area/assembler.hpp>
|
||||||
|
#include <osmium/area/multipolygon_collector.hpp>
|
||||||
|
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||||
|
#include <osmium/io/file.hpp>
|
||||||
|
#include <osmium/io/header.hpp>
|
||||||
|
#include <osmium/io/reader.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/osm/entity_bits.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Experimental code that is not "officially" supported.
|
||||||
|
*/
|
||||||
|
namespace experimental {
|
||||||
|
|
||||||
|
template <typename TLocationHandler>
|
||||||
|
class FlexReader {
|
||||||
|
|
||||||
|
bool m_with_areas;
|
||||||
|
osmium::osm_entity_bits::type m_entities;
|
||||||
|
|
||||||
|
TLocationHandler& m_location_handler;
|
||||||
|
|
||||||
|
osmium::io::Reader m_reader;
|
||||||
|
osmium::area::Assembler::config_type m_assembler_config;
|
||||||
|
osmium::area::MultipolygonCollector<osmium::area::Assembler> m_collector;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit FlexReader(const osmium::io::File& file, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) :
|
||||||
|
m_with_areas((entities & osmium::osm_entity_bits::area) != 0),
|
||||||
|
m_entities((entities & ~osmium::osm_entity_bits::area) | (m_with_areas ? osmium::osm_entity_bits::node | osmium::osm_entity_bits::way : osmium::osm_entity_bits::nothing)),
|
||||||
|
m_location_handler(location_handler),
|
||||||
|
m_reader(file, m_entities),
|
||||||
|
m_assembler_config(),
|
||||||
|
m_collector(m_assembler_config)
|
||||||
|
{
|
||||||
|
m_location_handler.ignore_errors();
|
||||||
|
if (m_with_areas) {
|
||||||
|
osmium::io::Reader reader(file, osmium::osm_entity_bits::relation);
|
||||||
|
m_collector.read_relations(reader);
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit FlexReader(const std::string& filename, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) :
|
||||||
|
FlexReader(osmium::io::File(filename), location_handler, entities) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit FlexReader(const char* filename, TLocationHandler& location_handler, osmium::osm_entity_bits::type entities = osmium::osm_entity_bits::nwr) :
|
||||||
|
FlexReader(osmium::io::File(filename), location_handler, entities) {
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::memory::Buffer read() {
|
||||||
|
osmium::memory::Buffer buffer = m_reader.read();
|
||||||
|
|
||||||
|
if (buffer) {
|
||||||
|
if (m_with_areas) {
|
||||||
|
std::vector<osmium::memory::Buffer> area_buffers;
|
||||||
|
osmium::apply(buffer, m_location_handler, m_collector.handler([&area_buffers](osmium::memory::Buffer&& area_buffer) {
|
||||||
|
area_buffers.push_back(std::move(area_buffer));
|
||||||
|
}));
|
||||||
|
for (const osmium::memory::Buffer& b : area_buffers) {
|
||||||
|
buffer.add_buffer(b);
|
||||||
|
buffer.commit();
|
||||||
|
}
|
||||||
|
} else if (m_entities & (osmium::osm_entity_bits::node | osmium::osm_entity_bits::way)) {
|
||||||
|
osmium::apply(buffer, m_location_handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::io::Header header() {
|
||||||
|
return m_reader.header();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
return m_reader.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eof() const {
|
||||||
|
return m_reader.eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
const osmium::area::MultipolygonCollector<osmium::area::Assembler>& collector() const {
|
||||||
|
return m_collector;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class FlexReader
|
||||||
|
|
||||||
|
} // namespace experimental
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
|
70
include/osmium/fwd.hpp
Normal file
70
include/osmium/fwd.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef OSMIUM_FWD_HPP
|
||||||
|
#define OSMIUM_FWD_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* This file contains forward declarations for commonly used Osmium classes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
class Area;
|
||||||
|
class Box;
|
||||||
|
class Changeset;
|
||||||
|
class ChangesetComment;
|
||||||
|
class ChangesetDiscussion;
|
||||||
|
class InnerRing;
|
||||||
|
class Location;
|
||||||
|
class Node;
|
||||||
|
class NodeRef;
|
||||||
|
class NodeRefList;
|
||||||
|
class OSMEntity;
|
||||||
|
class OSMObject;
|
||||||
|
class OuterRing;
|
||||||
|
class Relation;
|
||||||
|
class RelationMemberList;
|
||||||
|
class Segment;
|
||||||
|
class Tag;
|
||||||
|
class TagList;
|
||||||
|
class Timestamp;
|
||||||
|
class Way;
|
||||||
|
class WayNodeList;
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_FWD_HPP
|
96
include/osmium/geom/coordinates.hpp
Normal file
96
include/osmium/geom/coordinates.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_COORDINATES_HPP
|
||||||
|
#define OSMIUM_GEOM_COORDINATES_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <iosfwd>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/util/double.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
struct Coordinates {
|
||||||
|
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
explicit Coordinates(double cx, double cy) noexcept : x(cx), y(cy) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates(const osmium::Location& location) : x(location.lon()), y(location.lat()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_to_string(std::string& s, const char infix, int precision) const {
|
||||||
|
osmium::util::double2string(s, x, precision);
|
||||||
|
s += infix;
|
||||||
|
osmium::util::double2string(s, y, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append_to_string(std::string& s, const char prefix, const char infix, const char suffix, int precision) const {
|
||||||
|
s += prefix;
|
||||||
|
append_to_string(s, infix, precision);
|
||||||
|
s += suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct coordinates
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare whether two Coordinates are identical. Might not give the
|
||||||
|
* right result if the coordinates have been the result of some
|
||||||
|
* calculation that introduced rounding errors.
|
||||||
|
*/
|
||||||
|
inline bool operator==(const Coordinates& lhs, const Coordinates& rhs) noexcept {
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||||
|
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const Coordinates& lhs, const Coordinates& rhs) noexcept {
|
||||||
|
return ! operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TChar, typename TTraits>
|
||||||
|
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const Coordinates& c) {
|
||||||
|
return out << '(' << c.x << ',' << c.y << ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_COORDINATES_HPP
|
419
include/osmium/geom/factory.hpp
Normal file
419
include/osmium/geom/factory.hpp
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_FACTORY_HPP
|
||||||
|
#define OSMIUM_GEOM_FACTORY_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/memory/collection.hpp>
|
||||||
|
#include <osmium/memory/item.hpp>
|
||||||
|
#include <osmium/osm/area.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when an invalid geometry is encountered. An example
|
||||||
|
* would be a linestring with less than two points.
|
||||||
|
*/
|
||||||
|
class geometry_error : public std::runtime_error {
|
||||||
|
|
||||||
|
std::string m_message;
|
||||||
|
osmium::object_id_type m_id;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit geometry_error(const std::string& message, const char* object_type = "", osmium::object_id_type id = 0) :
|
||||||
|
std::runtime_error(message),
|
||||||
|
m_message(message),
|
||||||
|
m_id(id) {
|
||||||
|
if (m_id != 0) {
|
||||||
|
m_message += " (";
|
||||||
|
m_message += object_type;
|
||||||
|
m_message += "_id=";
|
||||||
|
m_message += std::to_string(m_id);
|
||||||
|
m_message += ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_id(const char* object_type, osmium::object_id_type id) {
|
||||||
|
if (m_id == 0 && id != 0) {
|
||||||
|
m_message += " (";
|
||||||
|
m_message += object_type;
|
||||||
|
m_message += "_id=";
|
||||||
|
m_message += std::to_string(id);
|
||||||
|
m_message += ")";
|
||||||
|
}
|
||||||
|
m_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::object_id_type id() const noexcept {
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* what() const noexcept override {
|
||||||
|
return m_message.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct geometry_error
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Everything related to geometry handling.
|
||||||
|
*/
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which nodes of a way to use for a linestring.
|
||||||
|
*/
|
||||||
|
enum class use_nodes : bool {
|
||||||
|
unique = true, ///< Remove consecutive nodes with same location.
|
||||||
|
all = false ///< Use all nodes.
|
||||||
|
}; // enum class use_nodes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which direction the linestring created from a way
|
||||||
|
* should have.
|
||||||
|
*/
|
||||||
|
enum class direction : bool {
|
||||||
|
backward = true, ///< Linestring has reverse direction.
|
||||||
|
forward = false ///< Linestring has same direction as way.
|
||||||
|
}; // enum class direction
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This pseudo projection just returns its WGS84 input unchanged.
|
||||||
|
* Used as a template parameter if a real projection is not needed.
|
||||||
|
*/
|
||||||
|
class IdentityProjection {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Coordinates operator()(osmium::Location location) const {
|
||||||
|
return Coordinates{location.lon(), location.lat()};
|
||||||
|
}
|
||||||
|
|
||||||
|
int epsg() const noexcept {
|
||||||
|
return 4326;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string proj_string() const {
|
||||||
|
return "+proj=longlat +datum=WGS84 +no_defs";
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class IdentityProjection
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geometry factory.
|
||||||
|
*/
|
||||||
|
template <typename TGeomImpl, typename TProjection = IdentityProjection>
|
||||||
|
class GeometryFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all points of an outer or inner ring to a multipolygon.
|
||||||
|
*/
|
||||||
|
void add_points(const osmium::OuterRing& nodes) {
|
||||||
|
osmium::Location last_location;
|
||||||
|
for (const osmium::NodeRef& node_ref : nodes) {
|
||||||
|
if (last_location != node_ref.location()) {
|
||||||
|
last_location = node_ref.location();
|
||||||
|
m_impl.multipolygon_add_location(m_projection(last_location));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TProjection m_projection;
|
||||||
|
TGeomImpl m_impl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for default initialized projection.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
explicit GeometryFactory<TGeomImpl, TProjection>(TArgs&&... args) :
|
||||||
|
m_projection(),
|
||||||
|
m_impl(std::forward<TArgs>(args)...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for explicitly initialized projection. Note that the
|
||||||
|
* projection is moved into the GeometryFactory.
|
||||||
|
*/
|
||||||
|
template <typename... TArgs>
|
||||||
|
explicit GeometryFactory<TGeomImpl, TProjection>(TProjection&& projection, TArgs&&... args) :
|
||||||
|
m_projection(std::move(projection)),
|
||||||
|
m_impl(std::forward<TArgs>(args)...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TProjection projection_type;
|
||||||
|
typedef typename TGeomImpl::point_type point_type;
|
||||||
|
typedef typename TGeomImpl::linestring_type linestring_type;
|
||||||
|
typedef typename TGeomImpl::polygon_type polygon_type;
|
||||||
|
typedef typename TGeomImpl::multipolygon_type multipolygon_type;
|
||||||
|
typedef typename TGeomImpl::ring_type ring_type;
|
||||||
|
|
||||||
|
int epsg() const {
|
||||||
|
return m_projection.epsg();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string proj_string() const {
|
||||||
|
return m_projection.proj_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
point_type create_point(const osmium::Location& location) const {
|
||||||
|
return m_impl.make_point(m_projection(location));
|
||||||
|
}
|
||||||
|
|
||||||
|
point_type create_point(const osmium::Node& node) {
|
||||||
|
try {
|
||||||
|
return create_point(node.location());
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
e.set_id("node", node.id());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
point_type create_point(const osmium::NodeRef& node_ref) {
|
||||||
|
try {
|
||||||
|
return create_point(node_ref.location());
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
e.set_id("node", node_ref.ref());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
void linestring_start() {
|
||||||
|
m_impl.linestring_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIter>
|
||||||
|
size_t fill_linestring(TIter it, TIter end) {
|
||||||
|
size_t num_points = 0;
|
||||||
|
for (; it != end; ++it, ++num_points) {
|
||||||
|
m_impl.linestring_add_location(m_projection(it->location()));
|
||||||
|
}
|
||||||
|
return num_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIter>
|
||||||
|
size_t fill_linestring_unique(TIter it, TIter end) {
|
||||||
|
size_t num_points = 0;
|
||||||
|
osmium::Location last_location;
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (last_location != it->location()) {
|
||||||
|
last_location = it->location();
|
||||||
|
m_impl.linestring_add_location(m_projection(last_location));
|
||||||
|
++num_points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t num_points) {
|
||||||
|
return m_impl.linestring_finish(num_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
|
||||||
|
linestring_start();
|
||||||
|
size_t num_points = 0;
|
||||||
|
|
||||||
|
if (un == use_nodes::unique) {
|
||||||
|
osmium::Location last_location;
|
||||||
|
switch (dir) {
|
||||||
|
case direction::forward:
|
||||||
|
num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend());
|
||||||
|
break;
|
||||||
|
case direction::backward:
|
||||||
|
num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (dir) {
|
||||||
|
case direction::forward:
|
||||||
|
num_points = fill_linestring(wnl.cbegin(), wnl.cend());
|
||||||
|
break;
|
||||||
|
case direction::backward:
|
||||||
|
num_points = fill_linestring(wnl.crbegin(), wnl.crend());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_points < 2) {
|
||||||
|
throw osmium::geometry_error("need at least two points for linestring");
|
||||||
|
}
|
||||||
|
|
||||||
|
return linestring_finish(num_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type create_linestring(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||||
|
try {
|
||||||
|
return create_linestring(way.nodes(), un, dir);
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
e.set_id("way", way.id());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Polygon */
|
||||||
|
|
||||||
|
void polygon_start() {
|
||||||
|
m_impl.polygon_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIter>
|
||||||
|
size_t fill_polygon(TIter it, TIter end) {
|
||||||
|
size_t num_points = 0;
|
||||||
|
for (; it != end; ++it, ++num_points) {
|
||||||
|
m_impl.polygon_add_location(m_projection(it->location()));
|
||||||
|
}
|
||||||
|
return num_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TIter>
|
||||||
|
size_t fill_polygon_unique(TIter it, TIter end) {
|
||||||
|
size_t num_points = 0;
|
||||||
|
osmium::Location last_location;
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (last_location != it->location()) {
|
||||||
|
last_location = it->location();
|
||||||
|
m_impl.polygon_add_location(m_projection(last_location));
|
||||||
|
++num_points;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_type polygon_finish(size_t num_points) {
|
||||||
|
return m_impl.polygon_finish(num_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_type create_polygon(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
|
||||||
|
polygon_start();
|
||||||
|
size_t num_points = 0;
|
||||||
|
|
||||||
|
if (un == use_nodes::unique) {
|
||||||
|
osmium::Location last_location;
|
||||||
|
switch (dir) {
|
||||||
|
case direction::forward:
|
||||||
|
num_points = fill_polygon_unique(wnl.cbegin(), wnl.cend());
|
||||||
|
break;
|
||||||
|
case direction::backward:
|
||||||
|
num_points = fill_polygon_unique(wnl.crbegin(), wnl.crend());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (dir) {
|
||||||
|
case direction::forward:
|
||||||
|
num_points = fill_polygon(wnl.cbegin(), wnl.cend());
|
||||||
|
break;
|
||||||
|
case direction::backward:
|
||||||
|
num_points = fill_polygon(wnl.crbegin(), wnl.crend());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_points < 4) {
|
||||||
|
throw osmium::geometry_error("need at least four points for polygon");
|
||||||
|
}
|
||||||
|
|
||||||
|
return polygon_finish(num_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_type create_polygon(const osmium::Way& way, use_nodes un=use_nodes::unique, direction dir=direction::forward) {
|
||||||
|
try {
|
||||||
|
return create_polygon(way.nodes(), un, dir);
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
e.set_id("way", way.id());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
multipolygon_type create_multipolygon(const osmium::Area& area) {
|
||||||
|
try {
|
||||||
|
size_t num_polygons = 0;
|
||||||
|
size_t num_rings = 0;
|
||||||
|
m_impl.multipolygon_start();
|
||||||
|
|
||||||
|
for (auto it = area.cbegin(); it != area.cend(); ++it) {
|
||||||
|
const osmium::OuterRing& ring = static_cast<const osmium::OuterRing&>(*it);
|
||||||
|
if (it->type() == osmium::item_type::outer_ring) {
|
||||||
|
if (num_polygons > 0) {
|
||||||
|
m_impl.multipolygon_polygon_finish();
|
||||||
|
}
|
||||||
|
m_impl.multipolygon_polygon_start();
|
||||||
|
m_impl.multipolygon_outer_ring_start();
|
||||||
|
add_points(ring);
|
||||||
|
m_impl.multipolygon_outer_ring_finish();
|
||||||
|
++num_rings;
|
||||||
|
++num_polygons;
|
||||||
|
} else if (it->type() == osmium::item_type::inner_ring) {
|
||||||
|
m_impl.multipolygon_inner_ring_start();
|
||||||
|
add_points(ring);
|
||||||
|
m_impl.multipolygon_inner_ring_finish();
|
||||||
|
++num_rings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there are no rings, this area is invalid
|
||||||
|
if (num_rings == 0) {
|
||||||
|
throw osmium::geometry_error("area contains no rings");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_impl.multipolygon_polygon_finish();
|
||||||
|
return m_impl.multipolygon_finish();
|
||||||
|
} catch (osmium::geometry_error& e) {
|
||||||
|
e.set_id("area", area.id());
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class GeometryFactory
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_FACTORY_HPP
|
160
include/osmium/geom/geojson.hpp
Normal file
160
include/osmium/geom/geojson.hpp
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_GEOJSON_HPP
|
||||||
|
#define OSMIUM_GEOM_GEOJSON_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class GeoJSONFactoryImpl {
|
||||||
|
|
||||||
|
std::string m_str;
|
||||||
|
int m_precision;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::string point_type;
|
||||||
|
typedef std::string linestring_type;
|
||||||
|
typedef std::string polygon_type;
|
||||||
|
typedef std::string multipolygon_type;
|
||||||
|
typedef std::string ring_type;
|
||||||
|
|
||||||
|
GeoJSONFactoryImpl(int precision = 7) :
|
||||||
|
m_precision(precision) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
// { "type": "Point", "coordinates": [100.0, 0.0] }
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
std::string str {"{\"type\":\"Point\",\"coordinates\":"};
|
||||||
|
xy.append_to_string(str, '[', ',', ']', m_precision);
|
||||||
|
str += "}";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
// { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
|
||||||
|
void linestring_start() {
|
||||||
|
m_str = "{\"type\":\"LineString\",\"coordinates\":[";
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
xy.append_to_string(m_str, '[', ',', ']', m_precision);
|
||||||
|
m_str += ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t /* num_points */) {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(str, m_str);
|
||||||
|
|
||||||
|
str.back() = ']';
|
||||||
|
str += "}";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_str = "{\"type\":\"MultiPolygon\",\"coordinates\":[";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
m_str += '[';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
m_str += "],";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
m_str += '[';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
m_str.back() = ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
m_str += ",[";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
m_str.back() = ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
xy.append_to_string(m_str, '[', ',', ']', m_precision);
|
||||||
|
m_str += ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(str, m_str);
|
||||||
|
|
||||||
|
str.back() = ']';
|
||||||
|
str += "}";
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class GeoJSONFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TProjection = IdentityProjection>
|
||||||
|
using GeoJSONFactory = GeometryFactory<osmium::geom::detail::GeoJSONFactoryImpl, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_GEOJSON_HPP
|
240
include/osmium/geom/geos.hpp
Normal file
240
include/osmium/geom/geos.hpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_GEOS_HPP
|
||||||
|
#define OSMIUM_GEOM_GEOS_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* This file contains code for conversion of OSM geometries into GDAL
|
||||||
|
* geometries.
|
||||||
|
*
|
||||||
|
* @attention If you include this file, you'll need to link with `libgeos`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <geos/geom/Coordinate.h>
|
||||||
|
#include <geos/geom/CoordinateSequence.h>
|
||||||
|
#include <geos/geom/CoordinateSequenceFactory.h>
|
||||||
|
#include <geos/geom/GeometryFactory.h>
|
||||||
|
#include <geos/geom/LinearRing.h>
|
||||||
|
#include <geos/geom/MultiPolygon.h>
|
||||||
|
#include <geos/geom/Point.h>
|
||||||
|
#include <geos/geom/Polygon.h>
|
||||||
|
#include <geos/geom/PrecisionModel.h>
|
||||||
|
#include <geos/util/GEOSException.h>
|
||||||
|
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
|
||||||
|
// MSVC doesn't support throw_with_nested yet
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# define THROW throw
|
||||||
|
#else
|
||||||
|
# define THROW std::throw_with_nested
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
struct geos_geometry_error : public geometry_error {
|
||||||
|
|
||||||
|
geos_geometry_error(const char* message) :
|
||||||
|
geometry_error(std::string("geometry creation failed in GEOS library: ") + message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct geos_geometry_error
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class GEOSFactoryImpl {
|
||||||
|
|
||||||
|
std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
|
||||||
|
std::unique_ptr<geos::geom::GeometryFactory> m_our_geos_factory;
|
||||||
|
geos::geom::GeometryFactory* m_geos_factory;
|
||||||
|
|
||||||
|
std::unique_ptr<geos::geom::CoordinateSequence> m_coordinate_sequence;
|
||||||
|
std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
|
||||||
|
std::vector<std::unique_ptr<geos::geom::Polygon>> m_polygons;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::unique_ptr<geos::geom::Point> point_type;
|
||||||
|
typedef std::unique_ptr<geos::geom::LineString> linestring_type;
|
||||||
|
typedef std::unique_ptr<geos::geom::Polygon> polygon_type;
|
||||||
|
typedef std::unique_ptr<geos::geom::MultiPolygon> multipolygon_type;
|
||||||
|
typedef std::unique_ptr<geos::geom::LinearRing> ring_type;
|
||||||
|
|
||||||
|
explicit GEOSFactoryImpl(geos::geom::GeometryFactory& geos_factory) :
|
||||||
|
m_precision_model(nullptr),
|
||||||
|
m_our_geos_factory(nullptr),
|
||||||
|
m_geos_factory(&geos_factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit GEOSFactoryImpl(int srid = -1) :
|
||||||
|
m_precision_model(new geos::geom::PrecisionModel),
|
||||||
|
m_our_geos_factory(new geos::geom::GeometryFactory(m_precision_model.get(), srid)),
|
||||||
|
m_geos_factory(m_our_geos_factory.get()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
try {
|
||||||
|
return point_type(m_geos_factory->createPoint(geos::geom::Coordinate(xy.x, xy.y)));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
void linestring_start() {
|
||||||
|
try {
|
||||||
|
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
try {
|
||||||
|
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t /* num_points */) {
|
||||||
|
try {
|
||||||
|
return linestring_type(m_geos_factory->createLineString(m_coordinate_sequence.release()));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_polygons.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
m_rings.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
try {
|
||||||
|
assert(!m_rings.empty());
|
||||||
|
auto inner_rings = new std::vector<geos::geom::Geometry*>;
|
||||||
|
std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
|
||||||
|
return r.release();
|
||||||
|
});
|
||||||
|
m_polygons.emplace_back(m_geos_factory->createPolygon(m_rings[0].release(), inner_rings));
|
||||||
|
m_rings.clear();
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
try {
|
||||||
|
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
try {
|
||||||
|
m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
try {
|
||||||
|
m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<size_t>(0), 2));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
try {
|
||||||
|
m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
try {
|
||||||
|
m_coordinate_sequence->add(geos::geom::Coordinate(xy.x, xy.y));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
try {
|
||||||
|
auto polygons = new std::vector<geos::geom::Geometry*>;
|
||||||
|
std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr<geos::geom::Polygon>& p) {
|
||||||
|
return p.release();
|
||||||
|
});
|
||||||
|
m_polygons.clear();
|
||||||
|
return multipolygon_type(m_geos_factory->createMultiPolygon(polygons));
|
||||||
|
} catch (geos::util::GEOSException& e) {
|
||||||
|
THROW(osmium::geos_geometry_error(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class GEOSFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TProjection = IdentityProjection>
|
||||||
|
using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#undef THROW
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_GEOS_HPP
|
94
include/osmium/geom/haversine.hpp
Normal file
94
include/osmium/geom/haversine.hpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_HAVERSINE_HPP
|
||||||
|
#define OSMIUM_GEOM_HAVERSINE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cmath>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/util.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Functions to calculate arc distance on Earth using the haversine formula.
|
||||||
|
*
|
||||||
|
* See http://en.wikipedia.org/wiki/Haversine_formula
|
||||||
|
*
|
||||||
|
* Implementation derived from
|
||||||
|
* http://blog.julien.cayzac.name/2008/10/arc-and-distance-between-two-points-on.html
|
||||||
|
*/
|
||||||
|
namespace haversine {
|
||||||
|
|
||||||
|
/// @brief Earth's quadratic mean radius for WGS84
|
||||||
|
constexpr double EARTH_RADIUS_IN_METERS = 6372797.560856;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate distance in meters between two sets of coordinates.
|
||||||
|
*/
|
||||||
|
inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) {
|
||||||
|
double lonh = sin(deg_to_rad(c1.x - c2.x) * 0.5);
|
||||||
|
lonh *= lonh;
|
||||||
|
double lath = sin(deg_to_rad(c1.y - c2.y) * 0.5);
|
||||||
|
lath *= lath;
|
||||||
|
const double tmp = cos(deg_to_rad(c1.y)) * cos(deg_to_rad(c2.y));
|
||||||
|
return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(lath + tmp*lonh));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate length of way.
|
||||||
|
*/
|
||||||
|
inline double distance(const osmium::WayNodeList& wnl) {
|
||||||
|
double sum_length = 0;
|
||||||
|
|
||||||
|
for (auto it = wnl.begin(); it != wnl.end(); ++it) {
|
||||||
|
if (std::next(it) != wnl.end()) {
|
||||||
|
sum_length += distance(it->location(), std::next(it)->location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace haversine
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_HAVERSINE_HPP
|
110
include/osmium/geom/mercator_projection.hpp
Normal file
110
include/osmium/geom/mercator_projection.hpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||||
|
#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cmath>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/util.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
constexpr double earth_radius_for_epsg3857 = 6378137.0;
|
||||||
|
constexpr double max_coordinate_epsg3857 = 20037508.34;
|
||||||
|
|
||||||
|
constexpr inline double lon_to_x(double lon) {
|
||||||
|
return earth_radius_for_epsg3857 * deg_to_rad(lon);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double lat_to_y(double lat) { // not constexpr because math functions aren't
|
||||||
|
return earth_radius_for_epsg3857 * std::log(std::tan(osmium::geom::PI/4 + deg_to_rad(lat)/2));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline double x_to_lon(double x) {
|
||||||
|
return rad_to_deg(x) / earth_radius_for_epsg3857;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double y_to_lat(double y) { // not constexpr because math functions aren't
|
||||||
|
return rad_to_deg(2 * std::atan(std::exp(y / earth_radius_for_epsg3857)) - osmium::geom::PI/2);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum latitude that can be projected with the Web Mercator
|
||||||
|
* (EPSG:3857) projection.
|
||||||
|
*/
|
||||||
|
constexpr double MERCATOR_MAX_LAT = 85.0511288;
|
||||||
|
|
||||||
|
inline Coordinates lonlat_to_mercator(const Coordinates& c) {
|
||||||
|
return Coordinates(detail::lon_to_x(c.x), detail::lat_to_y(c.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Coordinates mercator_to_lonlat(const Coordinates& c) {
|
||||||
|
return Coordinates(detail::x_to_lon(c.x), detail::y_to_lat(c.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functor that does projection from WGS84 (EPSG:4326) to "Web
|
||||||
|
* Mercator" (EPSG:3857)
|
||||||
|
*/
|
||||||
|
class MercatorProjection {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Coordinates operator()(osmium::Location location) const {
|
||||||
|
return Coordinates {detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
|
||||||
|
}
|
||||||
|
|
||||||
|
int epsg() const noexcept {
|
||||||
|
return 3857;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string proj_string() const {
|
||||||
|
return "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs";
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class MercatorProjection
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
178
include/osmium/geom/ogr.hpp
Normal file
178
include/osmium/geom/ogr.hpp
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_OGR_HPP
|
||||||
|
#define OSMIUM_GEOM_OGR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* This file contains code for conversion of OSM geometries into OGR
|
||||||
|
* geometries.
|
||||||
|
*
|
||||||
|
* @attention If you include this file, you'll need to link with `libgdal`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <ogr_geometry.h>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class OGRFactoryImpl {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::unique_ptr<OGRPoint> point_type;
|
||||||
|
typedef std::unique_ptr<OGRLineString> linestring_type;
|
||||||
|
typedef std::unique_ptr<OGRPolygon> polygon_type;
|
||||||
|
typedef std::unique_ptr<OGRMultiPolygon> multipolygon_type;
|
||||||
|
typedef std::unique_ptr<OGRLinearRing> ring_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
linestring_type m_linestring;
|
||||||
|
multipolygon_type m_multipolygon;
|
||||||
|
polygon_type m_polygon;
|
||||||
|
ring_type m_ring;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
OGRFactoryImpl() = default;
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
return point_type(new OGRPoint(xy.x, xy.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
void linestring_start() {
|
||||||
|
m_linestring = std::unique_ptr<OGRLineString>(new OGRLineString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
assert(!!m_linestring);
|
||||||
|
m_linestring->addPoint(xy.x, xy.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t /* num_points */) {
|
||||||
|
return std::move(m_linestring);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Polygon */
|
||||||
|
|
||||||
|
void polygon_start() {
|
||||||
|
m_ring = std::unique_ptr<OGRLinearRing>(new OGRLinearRing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void polygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
assert(!!m_ring);
|
||||||
|
m_ring->addPoint(xy.x, xy.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_type polygon_finish(size_t /* num_points */) {
|
||||||
|
std::unique_ptr<OGRPolygon> polygon = std::unique_ptr<OGRPolygon>(new OGRPolygon());
|
||||||
|
polygon->addRingDirectly(m_ring.release());
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_multipolygon.reset(new OGRMultiPolygon());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
m_polygon.reset(new OGRPolygon());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
assert(!!m_multipolygon);
|
||||||
|
assert(!!m_polygon);
|
||||||
|
m_multipolygon->addGeometryDirectly(m_polygon.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
m_ring.reset(new OGRLinearRing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
assert(!!m_polygon);
|
||||||
|
assert(!!m_ring);
|
||||||
|
m_polygon->addRingDirectly(m_ring.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
m_ring.reset(new OGRLinearRing());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
assert(!!m_polygon);
|
||||||
|
assert(!!m_ring);
|
||||||
|
m_polygon->addRingDirectly(m_ring.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
assert(!!m_polygon);
|
||||||
|
assert(!!m_ring);
|
||||||
|
m_ring->addPoint(xy.x, xy.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
assert(!!m_multipolygon);
|
||||||
|
return std::move(m_multipolygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class OGRFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TProjection = IdentityProjection>
|
||||||
|
using OGRFactory = GeometryFactory<osmium::geom::detail::OGRFactoryImpl, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_OGR_HPP
|
170
include/osmium/geom/projection.hpp
Normal file
170
include/osmium/geom/projection.hpp
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_PROJECTION_HPP
|
||||||
|
#define OSMIUM_GEOM_PROJECTION_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* This file contains code for projecting OSM locations to arbitrary
|
||||||
|
* coordinate reference systems. It is based on the Proj.4 library.
|
||||||
|
*
|
||||||
|
* @attention If you include this file, you'll need to link with `libproj`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <proj_api.h>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/util.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C++ wrapper for a Coordinate Reference System of the proj library.
|
||||||
|
*/
|
||||||
|
class CRS {
|
||||||
|
|
||||||
|
struct ProjCRSDeleter {
|
||||||
|
void operator()(void* crs) {
|
||||||
|
pj_free(crs);
|
||||||
|
}
|
||||||
|
}; // struct ProjCRSDeleter
|
||||||
|
|
||||||
|
std::unique_ptr<void, ProjCRSDeleter> m_crs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CRS(const std::string& crs) :
|
||||||
|
m_crs(pj_init_plus(crs.c_str()), ProjCRSDeleter()) {
|
||||||
|
if (!m_crs) {
|
||||||
|
throw osmium::projection_error(std::string("creation of CRS failed: ") + pj_strerrno(*pj_get_errno_ref()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CRS(int epsg) :
|
||||||
|
CRS(std::string("+init=epsg:") + std::to_string(epsg)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get underlying projPJ handle from proj library.
|
||||||
|
*/
|
||||||
|
projPJ get() const {
|
||||||
|
return m_crs.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_latlong() const {
|
||||||
|
return pj_is_latlong(m_crs.get()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_geocent() const {
|
||||||
|
return pj_is_geocent(m_crs.get()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class CRS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform coordinates from one CRS into another. Wraps the same
|
||||||
|
* function of the proj library.
|
||||||
|
*
|
||||||
|
* Coordinates have to be in radians and are produced in radians.
|
||||||
|
*
|
||||||
|
* @throws osmmium::projection_error if the projection fails
|
||||||
|
*/
|
||||||
|
inline Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) {
|
||||||
|
int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr);
|
||||||
|
if (result != 0) {
|
||||||
|
throw osmium::projection_error(std::string("projection failed: ") + pj_strerrno(result));
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functor that does projection from WGS84 (EPSG:4326) to the given
|
||||||
|
* CRS.
|
||||||
|
*/
|
||||||
|
class Projection {
|
||||||
|
|
||||||
|
int m_epsg;
|
||||||
|
std::string m_proj_string;
|
||||||
|
CRS m_crs_wgs84 {4326};
|
||||||
|
CRS m_crs_user;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Projection(const std::string& proj_string) :
|
||||||
|
m_epsg(-1),
|
||||||
|
m_proj_string(proj_string),
|
||||||
|
m_crs_user(proj_string) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Projection(int epsg) :
|
||||||
|
m_epsg(epsg),
|
||||||
|
m_proj_string(std::string("+init=epsg:") + std::to_string(epsg)),
|
||||||
|
m_crs_user(epsg) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates operator()(osmium::Location location) const {
|
||||||
|
Coordinates c {location.lon(), location.lat()};
|
||||||
|
|
||||||
|
if (m_epsg != 4326) {
|
||||||
|
c = transform(m_crs_wgs84, m_crs_user, Coordinates(deg_to_rad(location.lon()), deg_to_rad(location.lat())));
|
||||||
|
if (m_crs_user.is_latlong()) {
|
||||||
|
c.x = rad_to_deg(c.x);
|
||||||
|
c.y = rad_to_deg(c.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int epsg() const noexcept {
|
||||||
|
return m_epsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string proj_string() const {
|
||||||
|
return m_proj_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Projection
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_PROJECTION_HPP
|
190
include/osmium/geom/rapid_geojson.hpp
Normal file
190
include/osmium/geom/rapid_geojson.hpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||||
|
#define OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A geometry factory implementation that can be used with the
|
||||||
|
* RapidJSON (https://github.com/miloyip/rapidjson) JSON writer.
|
||||||
|
*/
|
||||||
|
template <typename TWriter>
|
||||||
|
class RapidGeoJSONFactoryImpl {
|
||||||
|
|
||||||
|
TWriter* m_writer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef void point_type;
|
||||||
|
typedef void linestring_type;
|
||||||
|
typedef void polygon_type;
|
||||||
|
typedef void multipolygon_type;
|
||||||
|
typedef void ring_type;
|
||||||
|
|
||||||
|
RapidGeoJSONFactoryImpl(TWriter& writer) :
|
||||||
|
m_writer(&writer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
// { "type": "Point", "coordinates": [100.0, 0.0] }
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
m_writer->String("geometry");
|
||||||
|
m_writer->StartObject();
|
||||||
|
m_writer->String("type");
|
||||||
|
m_writer->String("Point");
|
||||||
|
m_writer->String("coordinates");
|
||||||
|
m_writer->StartArray();
|
||||||
|
m_writer->Double(xy.x);
|
||||||
|
m_writer->Double(xy.y);
|
||||||
|
m_writer->EndArray();
|
||||||
|
m_writer->EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
// { "type": "LineString", "coordinates": [ [100.0, 0.0], [101.0, 1.0] ] }
|
||||||
|
void linestring_start() {
|
||||||
|
m_writer->String("geometry");
|
||||||
|
m_writer->StartObject();
|
||||||
|
m_writer->String("type");
|
||||||
|
m_writer->String("LineString");
|
||||||
|
m_writer->String("coordinates");
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
m_writer->StartArray();
|
||||||
|
m_writer->Double(xy.x);
|
||||||
|
m_writer->Double(xy.y);
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t /* num_points */) {
|
||||||
|
m_writer->EndArray();
|
||||||
|
m_writer->EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Polygon */
|
||||||
|
|
||||||
|
// { "type": "Polygon", "coordinates": [[[100.0, 0.0], [101.0, 1.0]]] }
|
||||||
|
void polygon_start() {
|
||||||
|
m_writer->String("geometry");
|
||||||
|
m_writer->StartObject();
|
||||||
|
m_writer->String("type");
|
||||||
|
m_writer->String("Polygon");
|
||||||
|
m_writer->String("coordinates");
|
||||||
|
m_writer->StartArray();
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void polygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
m_writer->StartArray();
|
||||||
|
m_writer->Double(xy.x);
|
||||||
|
m_writer->Double(xy.y);
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
polygon_type polygon_finish(size_t /* num_points */) {
|
||||||
|
m_writer->EndArray();
|
||||||
|
m_writer->EndArray();
|
||||||
|
m_writer->EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_writer->String("geometry");
|
||||||
|
m_writer->StartObject();
|
||||||
|
m_writer->String("type");
|
||||||
|
m_writer->String("MultiPolygon");
|
||||||
|
m_writer->String("coordinates");
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
m_writer->StartArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
m_writer->StartArray();
|
||||||
|
m_writer->Double(xy.x);
|
||||||
|
m_writer->Double(xy.y);
|
||||||
|
m_writer->EndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
m_writer->EndArray();
|
||||||
|
m_writer->EndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class RapidGeoJSONFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TWriter, typename TProjection = IdentityProjection>
|
||||||
|
using RapidGeoJSONFactory = GeometryFactory<detail::RapidGeoJSONFactoryImpl<TWriter>, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
57
include/osmium/geom/relations.hpp
Normal file
57
include/osmium/geom/relations.hpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_RELATIONS_HPP
|
||||||
|
#define OSMIUM_GEOM_RELATIONS_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/osm/box.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether one geometry contains another.
|
||||||
|
*/
|
||||||
|
inline bool contains(const osmium::Box& a, const osmium::Box& b) {
|
||||||
|
return ((a.bottom_left().x() >= b.bottom_left().x()) &&
|
||||||
|
(a.top_right().x() <= b.top_right().x()) &&
|
||||||
|
(a.bottom_left().y() >= b.bottom_left().y()) &&
|
||||||
|
(a.top_right().y() <= b.top_right().y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_RELATIONS_HPP
|
101
include/osmium/geom/tile.hpp
Normal file
101
include/osmium/geom/tile.hpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_TILE_HPP
|
||||||
|
#define OSMIUM_GEOM_TILE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstdint>
|
||||||
|
|
||||||
|
#include <osmium/geom/mercator_projection.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T restrict_to_range(T value, T min, T max) {
|
||||||
|
if (value < min) return min;
|
||||||
|
if (value > max) return max;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tile in the usual Mercator projection.
|
||||||
|
*/
|
||||||
|
struct Tile {
|
||||||
|
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t y;
|
||||||
|
uint32_t z;
|
||||||
|
|
||||||
|
explicit Tile(uint32_t zoom, uint32_t tx, uint32_t ty) noexcept : x(tx), y(ty), z(zoom) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit Tile(uint32_t zoom, const osmium::Location& location) :
|
||||||
|
z(zoom) {
|
||||||
|
osmium::geom::Coordinates c = lonlat_to_mercator(location);
|
||||||
|
const int32_t n = 1 << zoom;
|
||||||
|
const double scale = detail::max_coordinate_epsg3857 * 2 / n;
|
||||||
|
x = uint32_t(detail::restrict_to_range<int32_t>(int32_t((c.x + detail::max_coordinate_epsg3857) / scale), 0, n-1));
|
||||||
|
y = uint32_t(detail::restrict_to_range<int32_t>(int32_t((detail::max_coordinate_epsg3857 - c.y) / scale), 0, n-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct Tile
|
||||||
|
|
||||||
|
inline bool operator==(const Tile& a, const Tile& b) {
|
||||||
|
return a.z == b.z && a.x == b.x && a.y == b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const Tile& a, const Tile& b) {
|
||||||
|
return ! (a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This defines an arbitrary order on tiles for use in std::map etc.
|
||||||
|
*/
|
||||||
|
inline bool operator<(const Tile& a, const Tile& b) {
|
||||||
|
if (a.z < b.z) return true;
|
||||||
|
if (a.z > b.z) return false;
|
||||||
|
if (a.x < b.x) return true;
|
||||||
|
if (a.x > b.x) return false;
|
||||||
|
return a.y < b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_TILE_HPP
|
75
include/osmium/geom/util.hpp
Normal file
75
include/osmium/geom/util.hpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_UTIL_HPP
|
||||||
|
#define OSMIUM_GEOM_UTIL_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a projection object can not be initialized or the
|
||||||
|
* projection of some coordinates can not be calculated.
|
||||||
|
*/
|
||||||
|
struct projection_error : public std::runtime_error {
|
||||||
|
|
||||||
|
projection_error(const std::string& what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
projection_error(const char* what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct projection_error
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
constexpr double PI = 3.14159265358979323846;
|
||||||
|
|
||||||
|
/// Convert angle from degrees to radians.
|
||||||
|
inline constexpr double deg_to_rad(double degree) noexcept {
|
||||||
|
return degree * (PI / 180.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert angle from radians to degrees.
|
||||||
|
inline constexpr double rad_to_deg(double radians) noexcept {
|
||||||
|
return radians * (180.0 / PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_UTIL_HPP
|
273
include/osmium/geom/wkb.hpp
Normal file
273
include/osmium/geom/wkb.hpp
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_WKB_HPP
|
||||||
|
#define OSMIUM_GEOM_WKB_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
#include <osmium/util/cast.hpp>
|
||||||
|
#include <osmium/util/endian.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
enum class wkb_type : bool {
|
||||||
|
wkb = false,
|
||||||
|
ewkb = true
|
||||||
|
}; // enum class wkb_type
|
||||||
|
|
||||||
|
enum class out_type : bool {
|
||||||
|
binary = false,
|
||||||
|
hex = true
|
||||||
|
}; // enum class out_type
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void str_push(std::string& str, T data) {
|
||||||
|
size_t size = str.size();
|
||||||
|
str.resize(size + sizeof(T));
|
||||||
|
std::copy_n(reinterpret_cast<char*>(&data), sizeof(T), &str[size]);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string convert_to_hex(const std::string& str) {
|
||||||
|
static const char* lookup_hex = "0123456789ABCDEF";
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
for (char c : str) {
|
||||||
|
out += lookup_hex[(c >> 4) & 0xf];
|
||||||
|
out += lookup_hex[c & 0xf];
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WKBFactoryImpl {
|
||||||
|
|
||||||
|
/// OSM data always uses SRID 4326 (WGS84).
|
||||||
|
static constexpr uint32_t srid = 4326;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of WKB geometry.
|
||||||
|
* These definitions are from
|
||||||
|
* 99-049_OpenGIS_Simple_Features_Specification_For_SQL_Rev_1.1.pdf (for WKB)
|
||||||
|
* and http://trac.osgeo.org/postgis/browser/trunk/doc/ZMSgeoms.txt (for EWKB).
|
||||||
|
* They are used to encode geometries into the WKB format.
|
||||||
|
*/
|
||||||
|
enum wkbGeometryType : uint32_t {
|
||||||
|
wkbPoint = 1,
|
||||||
|
wkbLineString = 2,
|
||||||
|
wkbPolygon = 3,
|
||||||
|
wkbMultiPoint = 4,
|
||||||
|
wkbMultiLineString = 5,
|
||||||
|
wkbMultiPolygon = 6,
|
||||||
|
wkbGeometryCollection = 7,
|
||||||
|
|
||||||
|
// SRID-presence flag (EWKB)
|
||||||
|
wkbSRID = 0x20000000
|
||||||
|
}; // enum wkbGeometryType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte order marker in WKB geometry.
|
||||||
|
*/
|
||||||
|
enum class wkb_byte_order_type : uint8_t {
|
||||||
|
XDR = 0, // Big Endian
|
||||||
|
NDR = 1 // Little Endian
|
||||||
|
}; // enum class wkb_byte_order_type
|
||||||
|
|
||||||
|
std::string m_data;
|
||||||
|
uint32_t m_points {0};
|
||||||
|
wkb_type m_wkb_type;
|
||||||
|
out_type m_out_type;
|
||||||
|
|
||||||
|
size_t m_linestring_size_offset = 0;
|
||||||
|
size_t m_polygons = 0;
|
||||||
|
size_t m_rings = 0;
|
||||||
|
size_t m_multipolygon_size_offset = 0;
|
||||||
|
size_t m_polygon_size_offset = 0;
|
||||||
|
size_t m_ring_size_offset = 0;
|
||||||
|
|
||||||
|
size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
|
||||||
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
|
str_push(str, wkb_byte_order_type::NDR);
|
||||||
|
#else
|
||||||
|
str_push(str, wkb_byte_order_type::XDR);
|
||||||
|
#endif
|
||||||
|
if (m_wkb_type == wkb_type::ewkb) {
|
||||||
|
str_push(str, type | wkbSRID);
|
||||||
|
str_push(str, srid);
|
||||||
|
} else {
|
||||||
|
str_push(str, type);
|
||||||
|
}
|
||||||
|
size_t offset = str.size();
|
||||||
|
if (add_length) {
|
||||||
|
str_push(str, static_cast<uint32_t>(0));
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_size(const size_t offset, const size_t size) {
|
||||||
|
*reinterpret_cast<uint32_t*>(&m_data[offset]) = static_cast_with_assert<uint32_t>(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::string point_type;
|
||||||
|
typedef std::string linestring_type;
|
||||||
|
typedef std::string polygon_type;
|
||||||
|
typedef std::string multipolygon_type;
|
||||||
|
typedef std::string ring_type;
|
||||||
|
|
||||||
|
explicit WKBFactoryImpl(wkb_type wtype = wkb_type::wkb, out_type otype = out_type::binary) :
|
||||||
|
m_wkb_type(wtype),
|
||||||
|
m_out_type(otype) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
std::string data;
|
||||||
|
header(data, wkbPoint, false);
|
||||||
|
str_push(data, xy.x);
|
||||||
|
str_push(data, xy.y);
|
||||||
|
|
||||||
|
if (m_out_type == out_type::hex) {
|
||||||
|
return convert_to_hex(data);
|
||||||
|
} else {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
void linestring_start() {
|
||||||
|
m_data.clear();
|
||||||
|
m_linestring_size_offset = header(m_data, wkbLineString, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
str_push(m_data, xy.x);
|
||||||
|
str_push(m_data, xy.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t num_points) {
|
||||||
|
set_size(m_linestring_size_offset, num_points);
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(data, m_data);
|
||||||
|
|
||||||
|
if (m_out_type == out_type::hex) {
|
||||||
|
return convert_to_hex(data);
|
||||||
|
} else {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_data.clear();
|
||||||
|
m_polygons = 0;
|
||||||
|
m_multipolygon_size_offset = header(m_data, wkbMultiPolygon, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
++m_polygons;
|
||||||
|
m_rings = 0;
|
||||||
|
m_polygon_size_offset = header(m_data, wkbPolygon, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
set_size(m_polygon_size_offset, m_rings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
++m_rings;
|
||||||
|
m_points = 0;
|
||||||
|
m_ring_size_offset = m_data.size();
|
||||||
|
str_push(m_data, static_cast<uint32_t>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
set_size(m_ring_size_offset, m_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
++m_rings;
|
||||||
|
m_points = 0;
|
||||||
|
m_ring_size_offset = m_data.size();
|
||||||
|
str_push(m_data, static_cast<uint32_t>(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
set_size(m_ring_size_offset, m_points);
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
str_push(m_data, xy.x);
|
||||||
|
str_push(m_data, xy.y);
|
||||||
|
++m_points;
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
set_size(m_multipolygon_size_offset, m_polygons);
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(data, m_data);
|
||||||
|
|
||||||
|
if (m_out_type == out_type::hex) {
|
||||||
|
return convert_to_hex(data);
|
||||||
|
} else {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class WKBFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TProjection = IdentityProjection>
|
||||||
|
using WKBFactory = GeometryFactory<osmium::geom::detail::WKBFactoryImpl, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_WKB_HPP
|
156
include/osmium/geom/wkt.hpp
Normal file
156
include/osmium/geom/wkt.hpp
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#ifndef OSMIUM_GEOM_WKT_HPP
|
||||||
|
#define OSMIUM_GEOM_WKT_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/geom/coordinates.hpp>
|
||||||
|
#include <osmium/geom/factory.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace geom {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class WKTFactoryImpl {
|
||||||
|
|
||||||
|
std::string m_str;
|
||||||
|
int m_precision;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::string point_type;
|
||||||
|
typedef std::string linestring_type;
|
||||||
|
typedef std::string polygon_type;
|
||||||
|
typedef std::string multipolygon_type;
|
||||||
|
typedef std::string ring_type;
|
||||||
|
|
||||||
|
WKTFactoryImpl(int precision = 7) :
|
||||||
|
m_precision(precision) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Point */
|
||||||
|
|
||||||
|
point_type make_point(const osmium::geom::Coordinates& xy) const {
|
||||||
|
std::string str {"POINT"};
|
||||||
|
xy.append_to_string(str, '(', ' ', ')', m_precision);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LineString */
|
||||||
|
|
||||||
|
void linestring_start() {
|
||||||
|
m_str = "LINESTRING(";
|
||||||
|
}
|
||||||
|
|
||||||
|
void linestring_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
xy.append_to_string(m_str, ' ', m_precision);
|
||||||
|
m_str += ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
linestring_type linestring_finish(size_t /* num_points */) {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(str, m_str);
|
||||||
|
|
||||||
|
str.back() = ')';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MultiPolygon */
|
||||||
|
|
||||||
|
void multipolygon_start() {
|
||||||
|
m_str = "MULTIPOLYGON(";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_start() {
|
||||||
|
m_str += '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_polygon_finish() {
|
||||||
|
m_str += "),";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_start() {
|
||||||
|
m_str += '(';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_outer_ring_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
m_str.back() = ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_start() {
|
||||||
|
m_str += ",(";
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_inner_ring_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
m_str.back() = ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
|
||||||
|
xy.append_to_string(m_str, ' ', m_precision);
|
||||||
|
m_str += ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
multipolygon_type multipolygon_finish() {
|
||||||
|
assert(!m_str.empty());
|
||||||
|
std::string str;
|
||||||
|
|
||||||
|
using std::swap;
|
||||||
|
swap(str, m_str);
|
||||||
|
|
||||||
|
str.back() = ')';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class WKTFactoryImpl
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename TProjection = IdentityProjection>
|
||||||
|
using WKTFactory = GeometryFactory<osmium::geom::detail::WKTFactoryImpl, TProjection>;
|
||||||
|
|
||||||
|
} // namespace geom
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_GEOM_WKT_HPP
|
94
include/osmium/handler.hpp
Normal file
94
include/osmium/handler.hpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_HPP
|
||||||
|
#define OSMIUM_HANDLER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/fwd.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Osmium handlers provide callbacks for OSM objects
|
||||||
|
*/
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
class Handler {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void osm_object(const osmium::OSMObject&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void node(const osmium::Node&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(const osmium::Area&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset(const osmium::Changeset&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void tag_list(const osmium::TagList&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void way_node_list(const osmium::WayNodeList&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation_member_list(const osmium::RelationMemberList&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void outer_ring(const osmium::OuterRing&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void inner_ring(const osmium::InnerRing&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset_discussion(const osmium::ChangesetDiscussion&) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() const {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Handler
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_HPP
|
128
include/osmium/handler/chain.hpp
Normal file
128
include/osmium/handler/chain.hpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_CHAIN_HPP
|
||||||
|
#define OSMIUM_HANDLER_CHAIN_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <tuple>
|
||||||
|
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
|
||||||
|
#define OSMIUM_CHAIN_HANDLER_CALL(_func_, _type_) \
|
||||||
|
template <int N, int SIZE, typename THandlers> \
|
||||||
|
struct call_ ## _func_ { \
|
||||||
|
void operator()(THandlers& handlers, osmium::_type_& object) { \
|
||||||
|
std::get<N>(handlers)._func_(object); \
|
||||||
|
call_ ## _func_<N+1, SIZE, THandlers>()(handlers, object); \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
template <int SIZE, typename THandlers> \
|
||||||
|
struct call_ ## _func_<SIZE, SIZE, THandlers> { \
|
||||||
|
void operator()(THandlers&, osmium::_type_&) {} \
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
class Node;
|
||||||
|
class Way;
|
||||||
|
class Relation;
|
||||||
|
class Area;
|
||||||
|
class Changeset;
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handler allows chaining of any number of handlers into a single
|
||||||
|
* handler.
|
||||||
|
*/
|
||||||
|
template <typename... THandler>
|
||||||
|
class ChainHandler : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
typedef std::tuple<THandler&...> handlers_type;
|
||||||
|
handlers_type m_handlers;
|
||||||
|
|
||||||
|
template <int N, int SIZE, typename THandlers>
|
||||||
|
struct call_flush {
|
||||||
|
void operator()(THandlers& handlers) {
|
||||||
|
std::get<N>(handlers).flush();
|
||||||
|
call_flush<N+1, SIZE, THandlers>()(handlers);
|
||||||
|
}
|
||||||
|
}; // struct call_flush
|
||||||
|
|
||||||
|
template <int SIZE, typename THandlers>
|
||||||
|
struct call_flush<SIZE, SIZE, THandlers> {
|
||||||
|
void operator()(THandlers&) {}
|
||||||
|
}; // struct call_flush
|
||||||
|
|
||||||
|
OSMIUM_CHAIN_HANDLER_CALL(node, Node)
|
||||||
|
OSMIUM_CHAIN_HANDLER_CALL(way, Way)
|
||||||
|
OSMIUM_CHAIN_HANDLER_CALL(relation, Relation)
|
||||||
|
OSMIUM_CHAIN_HANDLER_CALL(changeset, Changeset)
|
||||||
|
OSMIUM_CHAIN_HANDLER_CALL(area, Area)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ChainHandler(THandler&... handlers) :
|
||||||
|
m_handlers(handlers...) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void node(osmium::Node& node) {
|
||||||
|
call_node<0, sizeof...(THandler), handlers_type>()(m_handlers, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(osmium::Way& way) {
|
||||||
|
call_way<0, sizeof...(THandler), handlers_type>()(m_handlers, way);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(osmium::Relation& relation) {
|
||||||
|
call_relation<0, sizeof...(THandler), handlers_type>()(m_handlers, relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset( osmium::Changeset& changeset) {
|
||||||
|
call_changeset<0, sizeof...(THandler), handlers_type>()(m_handlers, changeset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(osmium::Area& area) {
|
||||||
|
call_area<0, sizeof...(THandler), handlers_type>()(m_handlers, area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
call_flush<0, sizeof...(THandler), handlers_type>()(m_handlers);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ChainHandler
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_CHAIN_HPP
|
136
include/osmium/handler/check_order.hpp
Normal file
136
include/osmium/handler/check_order.hpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_CHECK_ORDER_HPP
|
||||||
|
#define OSMIUM_HANDLER_CHECK_ORDER_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <limits>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a method in the CheckOrder class detects
|
||||||
|
* that the input is out of order.
|
||||||
|
*/
|
||||||
|
struct out_of_order_error : public std::runtime_error {
|
||||||
|
|
||||||
|
out_of_order_error(const std::string& what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
out_of_order_error(const char* what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct out_of_order_error
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler that can be used to check that an OSM file is ordered
|
||||||
|
* correctly. Ordered in this case refers to the usual order in OSM
|
||||||
|
* files: First nodes in the order of their IDs, then ways in the order
|
||||||
|
* of their IDs, then relations in the order or their IDs. IDs have to
|
||||||
|
* be unique for each type.
|
||||||
|
*
|
||||||
|
* To use this add a CheckOrder member variable to your handler and
|
||||||
|
* call the node(), way(), and relation() methods from your node(),
|
||||||
|
* way(), and relations() handlers, respectively. An out_of_order_error
|
||||||
|
* exception will be thrown when the input is not in order.
|
||||||
|
*/
|
||||||
|
class CheckOrder : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
osmium::object_id_type m_max_node_id = std::numeric_limits<osmium::object_id_type>::min();
|
||||||
|
osmium::object_id_type m_max_way_id = std::numeric_limits<osmium::object_id_type>::min();
|
||||||
|
osmium::object_id_type m_max_relation_id = std::numeric_limits<osmium::object_id_type>::min();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
if (m_max_way_id > 0) {
|
||||||
|
throw out_of_order_error("Found a node after a way.");
|
||||||
|
}
|
||||||
|
if (m_max_relation_id > 0) {
|
||||||
|
throw out_of_order_error("Found a node after a relation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_max_node_id >= node.id()) {
|
||||||
|
throw out_of_order_error("Node IDs out of order.");
|
||||||
|
}
|
||||||
|
m_max_node_id = node.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
if (m_max_relation_id > 0) {
|
||||||
|
throw out_of_order_error("Found a way after a relation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_max_way_id >= way.id()) {
|
||||||
|
throw out_of_order_error("Way IDs out of order.");
|
||||||
|
}
|
||||||
|
m_max_way_id = way.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
if (m_max_relation_id >= relation.id()) {
|
||||||
|
throw out_of_order_error("Relation IDs out of order.");
|
||||||
|
}
|
||||||
|
m_max_relation_id = relation.id();
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::object_id_type max_node_id() const noexcept {
|
||||||
|
return m_max_node_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::object_id_type max_way_id() const noexcept {
|
||||||
|
return m_max_way_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
osmium::object_id_type max_relation_id() const noexcept {
|
||||||
|
return m_max_relation_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class CheckOrder
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_CHECK_ORDER_HPP
|
111
include/osmium/handler/disk_store.hpp
Normal file
111
include/osmium/handler/disk_store.hpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_DISK_STORE_HPP
|
||||||
|
#define OSMIUM_HANDLER_DISK_STORE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/index/map.hpp>
|
||||||
|
#include <osmium/io/detail/read_write.hpp>
|
||||||
|
#include <osmium/memory/buffer.hpp>
|
||||||
|
#include <osmium/memory/item_iterator.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Note: This handler will only work if either all object IDs are
|
||||||
|
* positive or all object IDs are negative.
|
||||||
|
*/
|
||||||
|
class DiskStore : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
typedef osmium::index::map::Map<unsigned_object_id_type, size_t> offset_index_type;
|
||||||
|
|
||||||
|
size_t m_offset = 0;
|
||||||
|
int m_data_fd;
|
||||||
|
|
||||||
|
offset_index_type& m_node_index;
|
||||||
|
offset_index_type& m_way_index;
|
||||||
|
offset_index_type& m_relation_index;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit DiskStore(int data_fd, offset_index_type& node_index, offset_index_type& way_index, offset_index_type& relation_index) :
|
||||||
|
m_data_fd(data_fd),
|
||||||
|
m_node_index(node_index),
|
||||||
|
m_way_index(way_index),
|
||||||
|
m_relation_index(relation_index) {
|
||||||
|
}
|
||||||
|
|
||||||
|
DiskStore(const DiskStore&) = delete;
|
||||||
|
DiskStore& operator=(const DiskStore&) = delete;
|
||||||
|
|
||||||
|
~DiskStore() noexcept = default;
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
m_node_index.set(node.positive_id(), m_offset);
|
||||||
|
m_offset += node.byte_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
m_way_index.set(way.positive_id(), m_offset);
|
||||||
|
m_offset += way.byte_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
m_relation_index.set(relation.positive_id(), m_offset);
|
||||||
|
m_offset += relation.byte_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
void operator()(const osmium::memory::Buffer& buffer) {
|
||||||
|
osmium::io::detail::reliable_write(m_data_fd, buffer.data(), buffer.committed());
|
||||||
|
|
||||||
|
osmium::apply(buffer.begin(), buffer.end(), *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class DiskStore
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_DISK_STORE_HPP
|
294
include/osmium/handler/dump.hpp
Normal file
294
include/osmium/handler/dump.hpp
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_DUMP_HPP
|
||||||
|
#define OSMIUM_HANDLER_DUMP_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/memory/collection.hpp>
|
||||||
|
#include <osmium/memory/item.hpp>
|
||||||
|
#include <osmium/osm/area.hpp>
|
||||||
|
#include <osmium/osm/box.hpp>
|
||||||
|
#include <osmium/osm/changeset.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/object.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/tag.hpp>
|
||||||
|
#include <osmium/osm/timestamp.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
#include <osmium/visitor.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
class Dump : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
std::ostream* m_out;
|
||||||
|
bool m_with_size;
|
||||||
|
std::string m_prefix;
|
||||||
|
|
||||||
|
void print_title(const char* title, const osmium::memory::Item& item) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< title
|
||||||
|
<< ":";
|
||||||
|
|
||||||
|
if (m_with_size) {
|
||||||
|
*m_out << " ["
|
||||||
|
<< item.byte_size()
|
||||||
|
<< "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_out << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_meta(const osmium::OSMObject& object) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " id="
|
||||||
|
<< object.id()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " version="
|
||||||
|
<< object.version()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " uid="
|
||||||
|
<< object.uid()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " user=|"
|
||||||
|
<< object.user()
|
||||||
|
<< "|\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " changeset="
|
||||||
|
<< object.changeset()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " timestamp="
|
||||||
|
<< object.timestamp().to_iso()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " visible="
|
||||||
|
<< (object.visible() ? "yes" : "no")
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||||
|
osmium::apply(object.cbegin(), object.cend(), dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_location(const osmium::Node& node) {
|
||||||
|
const osmium::Location& location = node.location();
|
||||||
|
|
||||||
|
if (location) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " lon="
|
||||||
|
<< std::fixed
|
||||||
|
<< std::setprecision(7)
|
||||||
|
<< location.lon_without_check()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " lat="
|
||||||
|
<< location.lat_without_check()
|
||||||
|
<< "\n";
|
||||||
|
} else {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " lon=\n"
|
||||||
|
<< m_prefix
|
||||||
|
<< " lat=\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Dump(std::ostream& out, bool with_size = true, const std::string& prefix = "") :
|
||||||
|
m_out(&out),
|
||||||
|
m_with_size(with_size),
|
||||||
|
m_prefix(prefix) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void tag_list(const osmium::TagList& tags) {
|
||||||
|
print_title("TAGS", tags);
|
||||||
|
for (const auto& tag : tags) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " k=|"
|
||||||
|
<< tag.key()
|
||||||
|
<< "| v=|"
|
||||||
|
<< tag.value()
|
||||||
|
<< "|"
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void way_node_list(const osmium::WayNodeList& wnl) {
|
||||||
|
print_title("NODES", wnl);
|
||||||
|
for (const auto& node_ref : wnl) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " ref="
|
||||||
|
<< node_ref.ref();
|
||||||
|
if (node_ref.location()) {
|
||||||
|
*m_out << " pos="
|
||||||
|
<< node_ref.location();
|
||||||
|
}
|
||||||
|
*m_out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation_member_list(const osmium::RelationMemberList& rml) {
|
||||||
|
print_title("MEMBERS", rml);
|
||||||
|
for (const auto& member : rml) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " type="
|
||||||
|
<< item_type_to_name(member.type())
|
||||||
|
<< " ref="
|
||||||
|
<< member.ref()
|
||||||
|
<< " role=|"
|
||||||
|
<< member.role()
|
||||||
|
<< "|\n";
|
||||||
|
if (member.full_member()) {
|
||||||
|
Dump dump(*m_out, m_with_size, m_prefix + " | ");
|
||||||
|
osmium::apply_item(member.get_object(), dump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void outer_ring(const osmium::OuterRing& ring) {
|
||||||
|
print_title("OUTER RING", ring);
|
||||||
|
for (const auto& node_ref : ring) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " ref="
|
||||||
|
<< node_ref.ref();
|
||||||
|
if (node_ref.location()) {
|
||||||
|
*m_out << " pos="
|
||||||
|
<< node_ref.location();
|
||||||
|
}
|
||||||
|
*m_out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void inner_ring(const osmium::InnerRing& ring) {
|
||||||
|
print_title("INNER RING", ring);
|
||||||
|
for (const auto& node_ref : ring) {
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " ref="
|
||||||
|
<< node_ref.ref();
|
||||||
|
if (node_ref.location()) {
|
||||||
|
*m_out << " pos="
|
||||||
|
<< node_ref.location();
|
||||||
|
}
|
||||||
|
*m_out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
print_title("NODE", node);
|
||||||
|
print_meta(node);
|
||||||
|
print_location(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
print_title("WAY", way);
|
||||||
|
print_meta(way);
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
print_title("RELATION", relation);
|
||||||
|
print_meta(relation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void area(const osmium::Area& area) {
|
||||||
|
print_title("AREA", area);
|
||||||
|
print_meta(area);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changeset(const osmium::Changeset& changeset) {
|
||||||
|
print_title("CHANGESET", changeset);
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " id="
|
||||||
|
<< changeset.id()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " num_changes="
|
||||||
|
<< changeset.num_changes()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " uid="
|
||||||
|
<< changeset.uid()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " user=|"
|
||||||
|
<< changeset.user()
|
||||||
|
<< "|\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " created_at="
|
||||||
|
<< changeset.created_at().to_iso()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " closed_at="
|
||||||
|
<< changeset.closed_at().to_iso()
|
||||||
|
<< "\n";
|
||||||
|
*m_out << m_prefix
|
||||||
|
<< " bounds=";
|
||||||
|
|
||||||
|
if (changeset.bounds()) {
|
||||||
|
*m_out << '('
|
||||||
|
<< changeset.bounds().bottom_left().lon_without_check()
|
||||||
|
<< ','
|
||||||
|
<< changeset.bounds().bottom_left().lat_without_check()
|
||||||
|
<< ','
|
||||||
|
<< changeset.bounds().top_right().lon_without_check()
|
||||||
|
<< ','
|
||||||
|
<< changeset.bounds().top_right().lat_without_check()
|
||||||
|
<< ')';
|
||||||
|
} else {
|
||||||
|
*m_out << "(undefined)";
|
||||||
|
}
|
||||||
|
|
||||||
|
*m_out << "\n";
|
||||||
|
|
||||||
|
Dump dump(*m_out, m_with_size, m_prefix + " ");
|
||||||
|
osmium::apply(changeset.cbegin(), changeset.cend(), dump);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Dump
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_DUMP_HPP
|
180
include/osmium/handler/node_locations_for_ways.hpp
Normal file
180
include/osmium/handler/node_locations_for_ways.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
||||||
|
#define OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <type_traits>
|
||||||
|
|
||||||
|
#include <osmium/handler.hpp>
|
||||||
|
#include <osmium/index/index.hpp>
|
||||||
|
#include <osmium/index/map/dummy.hpp>
|
||||||
|
#include <osmium/osm/location.hpp>
|
||||||
|
#include <osmium/osm/node.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
#include <osmium/index/node_locations_map.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
typedef osmium::index::map::Dummy<osmium::unsigned_object_id_type, osmium::Location> dummy_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to retrieve locations from nodes and add them to ways.
|
||||||
|
*
|
||||||
|
* @tparam TStoragePosIDs Class that handles the actual storage of the node locations
|
||||||
|
* (for positive IDs). It must support the set(id, value) and
|
||||||
|
* get(id) methods.
|
||||||
|
* @tparam TStorageNegIDs Same but for negative IDs.
|
||||||
|
*/
|
||||||
|
template <typename TStoragePosIDs, typename TStorageNegIDs = dummy_type>
|
||||||
|
class NodeLocationsForWays : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStoragePosIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||||
|
|
||||||
|
static_assert(std::is_base_of<osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>, TStorageNegIDs>::value, "Index class must be derived from osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>");
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef TStoragePosIDs index_pos_type;
|
||||||
|
typedef TStorageNegIDs index_neg_type;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/// Object that handles the actual storage of the node locations (with positive IDs).
|
||||||
|
TStoragePosIDs& m_storage_pos;
|
||||||
|
|
||||||
|
/// Object that handles the actual storage of the node locations (with negative IDs).
|
||||||
|
TStorageNegIDs& m_storage_neg;
|
||||||
|
|
||||||
|
bool m_ignore_errors {false};
|
||||||
|
|
||||||
|
bool m_must_sort {false};
|
||||||
|
|
||||||
|
// It is okay to have this static dummy instance, even when using several threads,
|
||||||
|
// because it is read-only.
|
||||||
|
static dummy_type& get_dummy() {
|
||||||
|
static dummy_type instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit NodeLocationsForWays(TStoragePosIDs& storage_pos,
|
||||||
|
TStorageNegIDs& storage_neg = get_dummy()) :
|
||||||
|
m_storage_pos(storage_pos),
|
||||||
|
m_storage_neg(storage_neg) {
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeLocationsForWays(const NodeLocationsForWays&) = delete;
|
||||||
|
NodeLocationsForWays& operator=(const NodeLocationsForWays&) = delete;
|
||||||
|
|
||||||
|
NodeLocationsForWays(NodeLocationsForWays&&) = default;
|
||||||
|
NodeLocationsForWays& operator=(NodeLocationsForWays&&) = default;
|
||||||
|
|
||||||
|
~NodeLocationsForWays() noexcept = default;
|
||||||
|
|
||||||
|
void ignore_errors() {
|
||||||
|
m_ignore_errors = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the location of the node in the storage.
|
||||||
|
*/
|
||||||
|
void node(const osmium::Node& node) {
|
||||||
|
m_must_sort = true;
|
||||||
|
const osmium::object_id_type id = node.id();
|
||||||
|
if (id >= 0) {
|
||||||
|
m_storage_pos.set(static_cast<osmium::unsigned_object_id_type>( id), node.location());
|
||||||
|
} else {
|
||||||
|
m_storage_neg.set(static_cast<osmium::unsigned_object_id_type>(-id), node.location());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get location of node with given id.
|
||||||
|
*/
|
||||||
|
osmium::Location get_node_location(const osmium::object_id_type id) const {
|
||||||
|
if (id >= 0) {
|
||||||
|
return m_storage_pos.get(static_cast<osmium::unsigned_object_id_type>( id));
|
||||||
|
} else {
|
||||||
|
return m_storage_neg.get(static_cast<osmium::unsigned_object_id_type>(-id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve locations of all nodes in the way from storage and add
|
||||||
|
* them to the way object.
|
||||||
|
*/
|
||||||
|
void way(osmium::Way& way) {
|
||||||
|
if (m_must_sort) {
|
||||||
|
m_storage_pos.sort();
|
||||||
|
m_storage_neg.sort();
|
||||||
|
m_must_sort = false;
|
||||||
|
}
|
||||||
|
bool error = false;
|
||||||
|
for (auto& node_ref : way.nodes()) {
|
||||||
|
try {
|
||||||
|
node_ref.set_location(get_node_location(node_ref.ref()));
|
||||||
|
if (!node_ref.location()) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
} catch (osmium::not_found&) {
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (error && !m_ignore_errors) {
|
||||||
|
throw osmium::not_found("location for one or more nodes not found in node location index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call clear on the location indexes. Makes the
|
||||||
|
* NodeLocationsForWays handler unusable. Used to explicitly free
|
||||||
|
* memory if thats needed.
|
||||||
|
*/
|
||||||
|
void clear() {
|
||||||
|
m_storage_pos.clear();
|
||||||
|
m_storage_neg.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class NodeLocationsForWays
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_NODE_LOCATIONS_FOR_WAYS_HPP
|
106
include/osmium/handler/object_relations.hpp
Normal file
106
include/osmium/handler/object_relations.hpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#ifndef OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
||||||
|
#define OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/handler.hpp>
|
||||||
|
#include <osmium/index/multimap.hpp>
|
||||||
|
#include <osmium/osm/node_ref.hpp>
|
||||||
|
#include <osmium/osm/item_type.hpp>
|
||||||
|
#include <osmium/osm/relation.hpp>
|
||||||
|
#include <osmium/osm/types.hpp>
|
||||||
|
#include <osmium/osm/way.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace handler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Note: This handler will only work if either all object IDs are
|
||||||
|
* positive or all object IDs are negative.
|
||||||
|
*/
|
||||||
|
class ObjectRelations : public osmium::handler::Handler {
|
||||||
|
|
||||||
|
typedef osmium::index::multimap::Multimap<unsigned_object_id_type, unsigned_object_id_type> index_type;
|
||||||
|
|
||||||
|
index_type& m_index_n2w;
|
||||||
|
index_type& m_index_n2r;
|
||||||
|
index_type& m_index_w2r;
|
||||||
|
index_type& m_index_r2r;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ObjectRelations(index_type& n2w, index_type& n2r, index_type& w2r, index_type& r2r) :
|
||||||
|
m_index_n2w(n2w),
|
||||||
|
m_index_n2r(n2r),
|
||||||
|
m_index_w2r(w2r),
|
||||||
|
m_index_r2r(r2r) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectRelations(const ObjectRelations&) = delete;
|
||||||
|
ObjectRelations& operator=(const ObjectRelations&) = delete;
|
||||||
|
|
||||||
|
~ObjectRelations() noexcept = default;
|
||||||
|
|
||||||
|
void way(const osmium::Way& way) {
|
||||||
|
for (const auto& node_ref : way.nodes()) {
|
||||||
|
m_index_n2w.set(node_ref.positive_ref(), way.positive_id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void relation(const osmium::Relation& relation) {
|
||||||
|
for (const auto& member : relation.members()) {
|
||||||
|
switch (member.type()) {
|
||||||
|
case osmium::item_type::node:
|
||||||
|
m_index_n2r.set(member.positive_ref(), relation.positive_id());
|
||||||
|
break;
|
||||||
|
case osmium::item_type::way:
|
||||||
|
m_index_w2r.set(member.positive_ref(), relation.positive_id());
|
||||||
|
break;
|
||||||
|
case osmium::item_type::relation:
|
||||||
|
m_index_r2r.set(member.positive_ref(), relation.positive_id());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class ObjectRelations
|
||||||
|
|
||||||
|
} // namespace handler
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_HANDLER_OBJECT_RELATIONS_HPP
|
85
include/osmium/index/bool_vector.hpp
Normal file
85
include/osmium/index/bool_vector.hpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_BOOL_VECTOR_HPP
|
||||||
|
#define OSMIUM_INDEX_BOOL_VECTOR_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Index storing one bit for each Id. The index automatically scales
|
||||||
|
* with the Ids stored. Default value is 'false'. Storage uses
|
||||||
|
* std::vector<bool> and needs a minimum of memory if the Ids are
|
||||||
|
* dense.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class BoolVector {
|
||||||
|
|
||||||
|
static_assert(std::is_unsigned<T>::value, "Needs unsigned type");
|
||||||
|
|
||||||
|
std::vector<bool> m_bits;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BoolVector() = default;
|
||||||
|
|
||||||
|
BoolVector(const BoolVector&) = default;
|
||||||
|
BoolVector(BoolVector&&) = default;
|
||||||
|
BoolVector& operator=(const BoolVector&) = default;
|
||||||
|
BoolVector& operator=(BoolVector&&) = default;
|
||||||
|
|
||||||
|
~BoolVector() noexcept = default;
|
||||||
|
|
||||||
|
void set(T id, bool value = true) {
|
||||||
|
if (m_bits.size() <= id) {
|
||||||
|
m_bits.resize(id + 1024 * 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bits[id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get(T id) const {
|
||||||
|
return id < m_bits.size() && m_bits[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class BoolVector
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_BOOL_VECTOR_HPP
|
70
include/osmium/index/detail/create_map_with_fd.hpp
Normal file
70
include/osmium/index/detail/create_map_with_fd.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cassert>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T* create_map_with_fd(const std::vector<std::string>& config) {
|
||||||
|
if (config.size() == 1) {
|
||||||
|
return new T();
|
||||||
|
}
|
||||||
|
assert(config.size() > 1);
|
||||||
|
const std::string& filename = config[1];
|
||||||
|
int fd = ::open(filename.c_str(), O_CREAT | O_RDWR, 0644);
|
||||||
|
if (fd == -1) {
|
||||||
|
throw std::runtime_error(std::string("can't open file '") + filename + "': " + strerror(errno));
|
||||||
|
}
|
||||||
|
return new T(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_CREATE_MAP_WITH_FD_HPP
|
67
include/osmium/index/detail/mmap_vector_anon.hpp
Normal file
67
include/osmium/index/detail/mmap_vector_anon.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#include <osmium/index/detail/mmap_vector_base.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class looks and behaves like STL vector, but uses mmap
|
||||||
|
* internally.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class mmap_vector_anon : public mmap_vector_base<T> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
mmap_vector_anon() :
|
||||||
|
mmap_vector_base<T>() {
|
||||||
|
}
|
||||||
|
|
||||||
|
~mmap_vector_anon() noexcept = default;
|
||||||
|
|
||||||
|
}; // class mmap_vector_anon
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // __linux__
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_ANON_HPP
|
180
include/osmium/index/detail/mmap_vector_base.hpp
Normal file
180
include/osmium/index/detail/mmap_vector_base.hpp
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <new> // IWYU pragma: keep
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <osmium/util/memory_mapping.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
constexpr size_t mmap_vector_size_increment = 1024 * 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a base class for implementing classes that look like
|
||||||
|
* STL vector but use mmap internally. Do not use this class itself,
|
||||||
|
* use the derived classes mmap_vector_anon or mmap_vector_file.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class mmap_vector_base {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
size_t m_size;
|
||||||
|
osmium::util::TypedMemoryMapping<T> m_mapping;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
mmap_vector_base(int fd, size_t capacity, size_t size = 0) :
|
||||||
|
m_size(size),
|
||||||
|
m_mapping(capacity, osmium::util::MemoryMapping::mapping_mode::write_shared, fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit mmap_vector_base(size_t capacity = mmap_vector_size_increment) :
|
||||||
|
m_size(0),
|
||||||
|
m_mapping(capacity) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~mmap_vector_base() noexcept = default;
|
||||||
|
|
||||||
|
typedef T value_type;
|
||||||
|
typedef T& reference;
|
||||||
|
typedef const T& const_reference;
|
||||||
|
typedef T* pointer;
|
||||||
|
typedef const T* const_pointer;
|
||||||
|
typedef T* iterator;
|
||||||
|
typedef const T* const_iterator;
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
m_mapping.unmap();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t capacity() const noexcept {
|
||||||
|
return m_mapping.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const noexcept {
|
||||||
|
return m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const noexcept {
|
||||||
|
return m_size == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T* data() const {
|
||||||
|
return m_mapping.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
T* data() {
|
||||||
|
return m_mapping.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator[](size_t n) {
|
||||||
|
return data()[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
T at(size_t n) const {
|
||||||
|
if (n >= m_size) {
|
||||||
|
throw std::out_of_range("out of range");
|
||||||
|
}
|
||||||
|
return data()[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() noexcept {
|
||||||
|
m_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shrink_to_fit() {
|
||||||
|
// XXX do something here
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
if (m_size >= capacity()) {
|
||||||
|
resize(m_size+1);
|
||||||
|
}
|
||||||
|
data()[m_size] = value;
|
||||||
|
++m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t new_capacity) {
|
||||||
|
if (new_capacity > capacity()) {
|
||||||
|
m_mapping.resize(new_capacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t new_size) {
|
||||||
|
if (new_size > capacity()) {
|
||||||
|
reserve(new_size + osmium::detail::mmap_vector_size_increment);
|
||||||
|
}
|
||||||
|
if (new_size > size()) {
|
||||||
|
new (data() + size()) T[new_size - size()];
|
||||||
|
}
|
||||||
|
m_size = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() noexcept {
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() noexcept {
|
||||||
|
return data() + m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const noexcept {
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const noexcept {
|
||||||
|
return data() + m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const noexcept {
|
||||||
|
return data();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const noexcept {
|
||||||
|
return data() + m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class mmap_vector_base
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_BASE_HPP
|
74
include/osmium/index/detail/mmap_vector_file.hpp
Normal file
74
include/osmium/index/detail/mmap_vector_file.hpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/index/detail/mmap_vector_base.hpp>
|
||||||
|
#include <osmium/index/detail/tmpfile.hpp>
|
||||||
|
#include <osmium/util/file.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class looks and behaves like STL vector, but mmap's a file
|
||||||
|
* internally.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class mmap_vector_file : public mmap_vector_base<T> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
mmap_vector_file() :
|
||||||
|
mmap_vector_base<T>(
|
||||||
|
osmium::detail::create_tmp_file(),
|
||||||
|
osmium::detail::mmap_vector_size_increment) {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit mmap_vector_file(int fd) :
|
||||||
|
mmap_vector_base<T>(
|
||||||
|
fd,
|
||||||
|
osmium::util::file_size(fd) / sizeof(T),
|
||||||
|
osmium::util::file_size(fd) / sizeof(T)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~mmap_vector_file() noexcept = default;
|
||||||
|
|
||||||
|
}; // class mmap_vector_file
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_MMAP_VECTOR_FILE_HPP
|
62
include/osmium/index/detail/tmpfile.hpp
Normal file
62
include/osmium/index/detail/tmpfile.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_TMPFILE_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_TMPFILE_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cerrno>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and open a temporary file. It is removed after opening.
|
||||||
|
*
|
||||||
|
* @returns File descriptor of temporary file.
|
||||||
|
* @throws std::system_error if something went wrong.
|
||||||
|
*/
|
||||||
|
inline int create_tmp_file() {
|
||||||
|
FILE* file = ::tmpfile();
|
||||||
|
if (!file) {
|
||||||
|
throw std::system_error(errno, std::system_category(), "tempfile failed");
|
||||||
|
}
|
||||||
|
return fileno(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_TMPFILE_HPP
|
246
include/osmium/index/detail/vector_map.hpp
Normal file
246
include/osmium/index/detail/vector_map.hpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/index/index.hpp>
|
||||||
|
#include <osmium/index/map.hpp>
|
||||||
|
#include <osmium/io/detail/read_write.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
namespace map {
|
||||||
|
|
||||||
|
template <typename TVector, typename TId, typename TValue>
|
||||||
|
class VectorBasedDenseMap : public Map<TId, TValue> {
|
||||||
|
|
||||||
|
TVector m_vector;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef TValue element_type;
|
||||||
|
typedef TVector vector_type;
|
||||||
|
typedef typename vector_type::iterator iterator;
|
||||||
|
typedef typename vector_type::const_iterator const_iterator;
|
||||||
|
|
||||||
|
VectorBasedDenseMap() :
|
||||||
|
m_vector() {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit VectorBasedDenseMap(int fd) :
|
||||||
|
m_vector(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~VectorBasedDenseMap() noexcept final = default;
|
||||||
|
|
||||||
|
void reserve(const size_t size) final {
|
||||||
|
m_vector.reserve(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(const TId id, const TValue value) final {
|
||||||
|
if (size() <= id) {
|
||||||
|
m_vector.resize(id+1);
|
||||||
|
}
|
||||||
|
m_vector[id] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TValue get(const TId id) const final {
|
||||||
|
try {
|
||||||
|
const TValue& value = m_vector.at(id);
|
||||||
|
if (value == osmium::index::empty_value<TValue>()) {
|
||||||
|
not_found_error(id);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
} catch (std::out_of_range&) {
|
||||||
|
not_found_error(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const final {
|
||||||
|
return m_vector.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t byte_size() const {
|
||||||
|
return m_vector.size() * sizeof(element_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t used_memory() const final {
|
||||||
|
return sizeof(TValue) * size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() final {
|
||||||
|
m_vector.clear();
|
||||||
|
m_vector.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_as_array(const int fd) final {
|
||||||
|
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return m_vector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return m_vector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class VectorBasedDenseMap
|
||||||
|
|
||||||
|
|
||||||
|
template <typename TId, typename TValue, template<typename...> class TVector>
|
||||||
|
class VectorBasedSparseMap : public Map<TId, TValue> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef typename std::pair<TId, TValue> element_type;
|
||||||
|
typedef TVector<element_type> vector_type;
|
||||||
|
typedef typename vector_type::iterator iterator;
|
||||||
|
typedef typename vector_type::const_iterator const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vector_type m_vector;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
VectorBasedSparseMap() :
|
||||||
|
m_vector() {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit VectorBasedSparseMap(int fd) :
|
||||||
|
m_vector(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~VectorBasedSparseMap() final = default;
|
||||||
|
|
||||||
|
void set(const TId id, const TValue value) final {
|
||||||
|
m_vector.push_back(element_type(id, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
const TValue get(const TId id) const final {
|
||||||
|
const element_type element {
|
||||||
|
id,
|
||||||
|
osmium::index::empty_value<TValue>()
|
||||||
|
};
|
||||||
|
const auto result = std::lower_bound(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
if (result == m_vector.end() || result->first != id) {
|
||||||
|
not_found_error(id);
|
||||||
|
} else {
|
||||||
|
return result->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const final {
|
||||||
|
return m_vector.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t byte_size() const {
|
||||||
|
return m_vector.size() * sizeof(element_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t used_memory() const final {
|
||||||
|
return sizeof(element_type) * size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() final {
|
||||||
|
m_vector.clear();
|
||||||
|
m_vector.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sort() final {
|
||||||
|
std::sort(m_vector.begin(), m_vector.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_as_list(const int fd) final {
|
||||||
|
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return m_vector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return m_vector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class VectorBasedSparseMap
|
||||||
|
|
||||||
|
} // namespace map
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_VECTOR_MAP_HPP
|
186
include/osmium/index/detail/vector_multimap.hpp
Normal file
186
include/osmium/index/detail/vector_multimap.hpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP
|
||||||
|
#define OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <osmium/index/index.hpp>
|
||||||
|
#include <osmium/index/multimap.hpp>
|
||||||
|
#include <osmium/io/detail/read_write.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
namespace multimap {
|
||||||
|
|
||||||
|
template <typename TId, typename TValue, template<typename...> class TVector>
|
||||||
|
class VectorBasedSparseMultimap : public Multimap<TId, TValue> {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef typename std::pair<TId, TValue> element_type;
|
||||||
|
typedef TVector<element_type> vector_type;
|
||||||
|
typedef typename vector_type::iterator iterator;
|
||||||
|
typedef typename vector_type::const_iterator const_iterator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vector_type m_vector;
|
||||||
|
|
||||||
|
static bool is_removed(element_type& element) {
|
||||||
|
return element.second == osmium::index::empty_value<TValue>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
VectorBasedSparseMultimap() :
|
||||||
|
m_vector() {
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit VectorBasedSparseMultimap(int fd) :
|
||||||
|
m_vector(fd) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~VectorBasedSparseMultimap() noexcept final = default;
|
||||||
|
|
||||||
|
void set(const TId id, const TValue value) final {
|
||||||
|
m_vector.push_back(element_type(id, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void unsorted_set(const TId id, const TValue value) {
|
||||||
|
m_vector.push_back(element_type(id, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<iterator, iterator> get_all(const TId id) {
|
||||||
|
const element_type element {
|
||||||
|
id,
|
||||||
|
osmium::index::empty_value<TValue>()
|
||||||
|
};
|
||||||
|
return std::equal_range(m_vector.begin(), m_vector.end(), element, [](const element_type& a, const element_type& b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<const_iterator, const_iterator> get_all(const TId id) const {
|
||||||
|
const element_type element {
|
||||||
|
id,
|
||||||
|
osmium::index::empty_value<TValue>()
|
||||||
|
};
|
||||||
|
return std::equal_range(m_vector.cbegin(), m_vector.cend(), element, [](const element_type& a, const element_type& b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const final {
|
||||||
|
return m_vector.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t byte_size() const {
|
||||||
|
return m_vector.size() * sizeof(element_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t used_memory() const final {
|
||||||
|
return sizeof(element_type) * size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() final {
|
||||||
|
m_vector.clear();
|
||||||
|
m_vector.shrink_to_fit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sort() final {
|
||||||
|
std::sort(m_vector.begin(), m_vector.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(const TId id, const TValue value) {
|
||||||
|
auto r = get_all(id);
|
||||||
|
for (auto it = r.first; it != r.second; ++it) {
|
||||||
|
if (it->second == value) {
|
||||||
|
it->second = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void consolidate() {
|
||||||
|
std::sort(m_vector.begin(), m_vector.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase_removed() {
|
||||||
|
m_vector.erase(
|
||||||
|
std::remove_if(m_vector.begin(), m_vector.end(), is_removed),
|
||||||
|
m_vector.end()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_as_list(const int fd) final {
|
||||||
|
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return m_vector.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return m_vector.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cbegin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator cend() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return m_vector.cbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return m_vector.cend();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class VectorBasedSparseMultimap
|
||||||
|
|
||||||
|
} // namespace multimap
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_DETAIL_VECTOR_MULTIMAP_HPP
|
100
include/osmium/index/index.hpp
Normal file
100
include/osmium/index/index.hpp
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_INDEX_HPP
|
||||||
|
#define OSMIUM_INDEX_INDEX_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception signaling that an element could not be
|
||||||
|
* found in an index.
|
||||||
|
*/
|
||||||
|
struct not_found : public std::runtime_error {
|
||||||
|
|
||||||
|
not_found(const std::string& what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
not_found(const char* what) :
|
||||||
|
std::runtime_error(what) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // struct not_found
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Indexing of OSM data, Locations, etc.
|
||||||
|
*/
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
template <typename TKey>
|
||||||
|
OSMIUM_NORETURN void not_found_error(TKey key) {
|
||||||
|
std::stringstream s;
|
||||||
|
s << "id " << key << " not found";
|
||||||
|
throw not_found(s.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some of the index classes need an "empty" value that can
|
||||||
|
* never appear in real data. This function must return this
|
||||||
|
* empty value for any class used as a value in an index.
|
||||||
|
* The default implementation returns a default constructed
|
||||||
|
* object, but it can be specialized.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr T empty_value() {
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size_t value in indexes is usually used for offsets
|
||||||
|
* into a buffer or file. It is unlikely that we ever need
|
||||||
|
* the full range, so the max value is a good "empty" value.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
inline constexpr size_t empty_value<size_t>() {
|
||||||
|
return std::numeric_limits<size_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_INDEX_HPP
|
275
include/osmium/index/map.hpp
Normal file
275
include/osmium/index/map.hpp
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_MAP_HPP
|
||||||
|
#define OSMIUM_INDEX_MAP_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <cstddef>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <osmium/util/compatibility.hpp>
|
||||||
|
#include <osmium/util/string.hpp>
|
||||||
|
|
||||||
|
namespace osmium {
|
||||||
|
|
||||||
|
namespace index {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Key-value containers with unique integer values for a key
|
||||||
|
*/
|
||||||
|
namespace map {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstract class defines an interface to storage classes
|
||||||
|
* intended for storing small pieces of data (such as coordinates)
|
||||||
|
* indexed by a positive integer (such as an object ID). The
|
||||||
|
* storage must be very space efficient and able to scale to billions
|
||||||
|
* of objects.
|
||||||
|
*
|
||||||
|
* Subclasses have different implementations that store the
|
||||||
|
* data in different ways in memory and/or on disk. Some storage
|
||||||
|
* classes are better suited when working with the whole planet,
|
||||||
|
* some are better for data extracts.
|
||||||
|
*
|
||||||
|
* Note that these classes are not required to track "empty" fields.
|
||||||
|
* When reading data you have to be sure you have put something in
|
||||||
|
* there before.
|
||||||
|
*
|
||||||
|
* A typical use for this and derived classes is storage of node
|
||||||
|
* locations indexed by node ID. These indexes will only work
|
||||||
|
* on 64 bit systems if used in this case. 32 bit systems just
|
||||||
|
* can't address that much memory!
|
||||||
|
*
|
||||||
|
* @tparam TId Id type, usually osmium::unsigned_object_id_type,
|
||||||
|
* must be an unsigned integral type.
|
||||||
|
* @tparam TValue Value type, usually osmium::Location or size_t.
|
||||||
|
* Copied by value, so should be "small" type.
|
||||||
|
*/
|
||||||
|
template <typename TId, typename TValue>
|
||||||
|
class Map {
|
||||||
|
|
||||||
|
static_assert(std::is_integral<TId>::value && std::is_unsigned<TId>::value,
|
||||||
|
"TId template parameter for class Map must be unsigned integral type");
|
||||||
|
|
||||||
|
Map(const Map&) = delete;
|
||||||
|
Map& operator=(const Map&) = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Map(Map&&) = default;
|
||||||
|
Map& operator=(Map&&) = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// The "key" type, usually osmium::unsigned_object_id_type.
|
||||||
|
typedef TId key_type;
|
||||||
|
|
||||||
|
/// The "value" type, usually a Location or size_t.
|
||||||
|
typedef TValue value_type;
|
||||||
|
|
||||||
|
Map() = default;
|
||||||
|
|
||||||
|
virtual ~Map() noexcept = default;
|
||||||
|
|
||||||
|
virtual void reserve(const size_t) {
|
||||||
|
// default implementation is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the field with id to value.
|
||||||
|
virtual void set(const TId id, const TValue value) = 0;
|
||||||
|
|
||||||
|
/// Retrieve value by id. Does not check for overflow or empty fields.
|
||||||
|
virtual const TValue get(const TId id) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the approximate number of items in the storage. The storage
|
||||||
|
* might allocate memory in blocks, so this size might not be
|
||||||
|
* accurate. You can not use this to find out how much memory the
|
||||||
|
* storage uses. Use used_memory() for that.
|
||||||
|
*/
|
||||||
|
virtual size_t size() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the memory used for this storage in bytes. Note that this
|
||||||
|
* is not necessarily entirely accurate but an approximation.
|
||||||
|
* For storage classes that store the data in memory, this is
|
||||||
|
* the main memory used, for storage classes storing data on disk
|
||||||
|
* this is the memory used on disk.
|
||||||
|
*/
|
||||||
|
virtual size_t used_memory() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear memory used for this storage. After this you can not
|
||||||
|
* use the storage container any more.
|
||||||
|
*/
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort data in map. Call this after writing all data and
|
||||||
|
* before reading. Not all implementations need this.
|
||||||
|
*/
|
||||||
|
virtual void sort() {
|
||||||
|
// default implementation is empty
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function could usually be const in derived classes,
|
||||||
|
// but not always. It could, for instance, sort internal data.
|
||||||
|
// This is why it is not declared const here.
|
||||||
|
virtual void dump_as_list(const int /*fd*/) {
|
||||||
|
throw std::runtime_error("can't dump as list");
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function could usually be const in derived classes,
|
||||||
|
// but not always. It could, for instance, sort internal data.
|
||||||
|
// This is why it is not declared const here.
|
||||||
|
virtual void dump_as_array(const int /*fd*/) {
|
||||||
|
throw std::runtime_error("can't dump as array");
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class Map
|
||||||
|
|
||||||
|
} // namespace map
|
||||||
|
|
||||||
|
template <typename TId, typename TValue>
|
||||||
|
class MapFactory {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef TId id_type;
|
||||||
|
typedef TValue value_type;
|
||||||
|
typedef osmium::index::map::Map<id_type, value_type> map_type;
|
||||||
|
typedef std::function<map_type*(const std::vector<std::string>&)> create_map_func;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::map<const std::string, create_map_func> m_callbacks;
|
||||||
|
|
||||||
|
MapFactory() = default;
|
||||||
|
|
||||||
|
MapFactory(const MapFactory&) = delete;
|
||||||
|
MapFactory& operator=(const MapFactory&) = delete;
|
||||||
|
|
||||||
|
MapFactory(MapFactory&&) = delete;
|
||||||
|
MapFactory& operator=(MapFactory&&) = delete;
|
||||||
|
|
||||||
|
OSMIUM_NORETURN static void error(const std::string& map_type_name) {
|
||||||
|
std::string error_message {"Support for map type '"};
|
||||||
|
error_message += map_type_name;
|
||||||
|
error_message += "' not compiled into this binary.";
|
||||||
|
throw std::runtime_error(error_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static MapFactory<id_type, value_type>& instance() {
|
||||||
|
static MapFactory<id_type, value_type> factory;
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool register_map(const std::string& map_type_name, create_map_func func) {
|
||||||
|
return m_callbacks.emplace(map_type_name, func).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_map_type(const std::string& map_type_name) const {
|
||||||
|
return m_callbacks.count(map_type_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> map_types() const {
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
for (const auto& cb : m_callbacks) {
|
||||||
|
result.push_back(cb.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(result.begin(), result.end());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<map_type> create_map(const std::string& config_string) const {
|
||||||
|
std::vector<std::string> config = osmium::split_string(config_string, ',');
|
||||||
|
|
||||||
|
if (config.empty()) {
|
||||||
|
throw std::runtime_error("Need non-empty map type name.");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = m_callbacks.find(config[0]);
|
||||||
|
if (it != m_callbacks.end()) {
|
||||||
|
return std::unique_ptr<map_type>((it->second)(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
error(config[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // class MapFactory
|
||||||
|
|
||||||
|
namespace map {
|
||||||
|
|
||||||
|
template <typename TId, typename TValue, template<typename, typename> class TMap>
|
||||||
|
struct create_map {
|
||||||
|
TMap<TId, TValue>* operator()(const std::vector<std::string>&) {
|
||||||
|
return new TMap<TId, TValue>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace map
|
||||||
|
|
||||||
|
template <typename TId, typename TValue, template<typename, typename> class TMap>
|
||||||
|
inline bool register_map(const std::string& name) {
|
||||||
|
return osmium::index::MapFactory<TId, TValue>::instance().register_map(name, [](const std::vector<std::string>& config) {
|
||||||
|
return map::create_map<TId, TValue, TMap>()(config);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OSMIUM_CONCATENATE_DETAIL_(x, y) x##y
|
||||||
|
#define OSMIUM_CONCATENATE_(x, y) OSMIUM_CONCATENATE_DETAIL_(x, y)
|
||||||
|
|
||||||
|
#define REGISTER_MAP(id, value, klass, name) \
|
||||||
|
namespace osmium { namespace index { namespace detail { \
|
||||||
|
const bool OSMIUM_CONCATENATE_(registered_, name) = osmium::index::register_map<id, value, klass>(#name); \
|
||||||
|
inline bool OSMIUM_CONCATENATE_(get_registered_, name)() noexcept { \
|
||||||
|
return OSMIUM_CONCATENATE_(registered_, name); \
|
||||||
|
} \
|
||||||
|
} } }
|
||||||
|
|
||||||
|
} // namespace index
|
||||||
|
|
||||||
|
} // namespace osmium
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_MAP_HPP
|
46
include/osmium/index/map/all.hpp
Normal file
46
include/osmium/index/map/all.hpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef OSMIUM_INDEX_MAP_ALL_HPP
|
||||||
|
#define OSMIUM_INDEX_MAP_ALL_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||||
|
|
||||||
|
Copyright 2013-2016 Jochen Topf <jochen@topf.org> and others (see README).
|
||||||
|
|
||||||
|
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 <osmium/index/map/dense_file_array.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/dense_mem_array.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/dense_mmap_array.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/dummy.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/sparse_file_array.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/sparse_mem_array.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/sparse_mem_map.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/sparse_mem_table.hpp> // IWYU pragma: keep
|
||||||
|
#include <osmium/index/map/sparse_mmap_array.hpp> // IWYU pragma: keep
|
||||||
|
|
||||||
|
#endif // OSMIUM_INDEX_MAP_ALL_HPP
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user