Merge commit '6eb4f090f98f6b17a23c57768c16b7716b6c9cbd' as 'third_party/libosmium'
This commit is contained in:
commit
95442d45aa
7
third_party/libosmium/.codecov.yml
vendored
Normal file
7
third_party/libosmium/.codecov.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
ignore:
|
||||
- "include/gdalcpp.hpp"
|
||||
- "include/protozero"
|
||||
- "include/utf8"
|
||||
- "test/include/catch.hpp"
|
||||
|
6
third_party/libosmium/.gitignore
vendored
Normal file
6
third_party/libosmium/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.swp
|
||||
.ycm_extra_conf.pyc
|
||||
/_build*
|
||||
/build
|
||||
/libosmium-deps
|
||||
/.vs*
|
218
third_party/libosmium/.travis.yml
vendored
Normal file
218
third_party/libosmium/.travis.yml
vendored
Normal file
@ -0,0 +1,218 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Configuration for continuous integration service at travis-ci.org
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
language: generic
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.ccache
|
||||
|
||||
env:
|
||||
global:
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CASHER_TIME_OUT=1000
|
||||
|
||||
matrix:
|
||||
include:
|
||||
|
||||
# 1/ Linux Clang Builds
|
||||
- os: linux
|
||||
compiler: linux-clang35-release
|
||||
addons:
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['clang-3.5', 'cmake', '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: linux-clang35-dev
|
||||
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: linux-clang37-release
|
||||
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: linux-clang37-dev
|
||||
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'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: linux-clang38-release
|
||||
addons:
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['clang-3.8', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: linux-clang38-dev
|
||||
addons:
|
||||
apt:
|
||||
sources: ['llvm-toolchain-precise-3.8', 'ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['clang-3.8', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='clang++-3.8' BUILD_TYPE='Dev'
|
||||
|
||||
|
||||
# 2/ Linux GCC Builds
|
||||
- os: linux
|
||||
compiler: linux-gcc48-release
|
||||
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: linux-gcc48-dev
|
||||
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: linux-gcc49-release
|
||||
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: linux-gcc49-dev
|
||||
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: linux-gcc5-release
|
||||
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: linux-gcc5-dev
|
||||
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'
|
||||
|
||||
|
||||
- os: linux
|
||||
compiler: linux-gcc6-release
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['g++-6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Release'
|
||||
|
||||
- os: linux
|
||||
compiler: linux-gcc6-dev
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['g++-6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Dev'
|
||||
|
||||
- os: linux
|
||||
compiler: linux-gcc6-coverage
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'boost-latest']
|
||||
packages: ['g++-6', 'libboost1.55-all-dev', 'libgdal-dev', 'libgeos++-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin']
|
||||
env: COMPILER='g++-6' BUILD_TYPE='Coverage'
|
||||
|
||||
|
||||
# 3/ OSX Clang Builds
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: xcode64-clang-release
|
||||
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
compiler: xcode64-clang-dev
|
||||
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7
|
||||
compiler: xcode7-clang-release
|
||||
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7
|
||||
compiler: xcode7-clang-dev
|
||||
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: xcode8-clang-release
|
||||
env: COMPILER='clang++' BUILD_TYPE='Release'
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
compiler: xcode8-clang-dev
|
||||
env: COMPILER='clang++' BUILD_TYPE='Dev'
|
||||
|
||||
|
||||
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 || true
|
||||
fi
|
||||
- cmake --version
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- mkdir build && cd build
|
||||
- CXX=${COMPILER} CXXFLAGS=${COMPILER_FLAGS} cmake -LA .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DBUILD_WITH_CCACHE=1 -DOSM_TESTDATA="${TRAVIS_BUILD_DIR}/deps/osm-testdata"
|
||||
|
||||
script:
|
||||
- make VERBOSE=1 && ctest --output-on-failure
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [ "${BUILD_TYPE}" = "Coverage" ]; then
|
||||
curl -S -f https://codecov.io/bash -o codecov
|
||||
chmod +x codecov
|
||||
gcov-${COMPILER#g++-} -p $(find test/CMakeFiles -name '*.o')
|
||||
./codecov -Z -c -F unit_tests
|
||||
gcov-${COMPILER#g++-} -p $(find test/data-tests -name '*.o')
|
||||
./codecov -Z -c -F data_tests
|
||||
gcov-${COMPILER#g++-} -p $(find examples -name '*.o')
|
||||
./codecov -Z -c -F examples
|
||||
fi
|
||||
|
53
third_party/libosmium/.ycm_extra_conf.py
vendored
Normal file
53
third_party/libosmium/.ycm_extra_conf.py
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# 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++',
|
||||
|
||||
# workaround for https://github.com/Valloric/YouCompleteMe/issues/303
|
||||
# also see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=800618
|
||||
'-isystem',
|
||||
'/usr/lib/ycmd/clang_includes/',
|
||||
|
||||
# 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
|
||||
}
|
770
third_party/libosmium/CHANGELOG.md
vendored
Normal file
770
third_party/libosmium/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,770 @@
|
||||
|
||||
# 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.13.1] - 2017-08-25
|
||||
|
||||
### Added
|
||||
|
||||
- New "blackhole" file format which throws away all data written into it.
|
||||
Used for benchmarking.
|
||||
|
||||
### Changed
|
||||
|
||||
- When reading OPL files, CRLF file endings are now handled correctly.
|
||||
- Reduce the max number of threads allowed for the `Pool` to 32. This should
|
||||
still be plenty and might help with test failures on some architectures.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Tests now run correctly independent of git `core.autocrlf` setting.
|
||||
- Set binary mode for all files on Windows in example code.
|
||||
- Low-level file functions now set an invalid parameter handler on Windows
|
||||
to properly handle errors.
|
||||
- Restore earlier behaviour allowing zero-length mmap. It is important to
|
||||
allow zero-length memory mapping, because it is possible that such an index
|
||||
is empty, for instance when one type of object is missing from an input
|
||||
file as in https://github.com/osmcode/osmium-tool/issues/65. Drawback is
|
||||
that files must be opened read-write for this to work, even if we only
|
||||
want to read from them.
|
||||
- Use Approx() to compare floating point values in tests.
|
||||
- Fix broken `Item` test on 32 bit platforms.
|
||||
|
||||
|
||||
## [2.13.0] - 2017-08-15
|
||||
|
||||
### Added
|
||||
|
||||
- New `RelationsManager` class superseeds the `relations::Collector` class.
|
||||
The new class is much more modular and easier to extend. If you are using
|
||||
the Collector class, you are encouraged to switch.
|
||||
- New `MultipolygonManager` based on the `RelationsManager` class superseeds
|
||||
the `MultipolygonCollector` class. The examples have been changed to use the
|
||||
new class and all users are encouraged to switch. There is also a
|
||||
`MultipolygonManagerLegacy` class if you still need old-style multipolygon
|
||||
support (see below).
|
||||
- New `FlexMem` index class that works with input files of any size and
|
||||
stores the index in memory. This should now be used as the default index
|
||||
for node location stores. Several example programs now use this index.
|
||||
- New `CallbackBuffer` class, basically a convenient wrapper around the
|
||||
`Buffer` class with an additional callback function that is called whenever
|
||||
the buffer is full.
|
||||
- Introduce new `ItemStash` class for storing OSM objects in memory.
|
||||
- New `osmium::geom::overlaps()` function to check if two `Box` objects
|
||||
overlap.
|
||||
- Add function `IdSet::used_memory()` to get estimate of memory used in the
|
||||
set.
|
||||
- New `is_defined()` and `is_undefined()` methods on `Location` class.
|
||||
- Tests for all provided example programs. (Some tests currently fail
|
||||
on Windows for the `osmium_index_lookup` program.)
|
||||
|
||||
### Changed
|
||||
|
||||
- The area `Assembler` now doesn't work with old-style multipolygons (those
|
||||
are multipolygon relations with the tags on the outer ways(s) instead of
|
||||
on the relation) any more. Because old-style multipolygons are now (mostly)
|
||||
gone from the OSM database this is usually what you want. The new
|
||||
`AssemblerLegacy` class can be used if you actually need support for
|
||||
old-style multipolygons, for instance if you are working with historical
|
||||
data. (In that case you also need to use the `MultipolygonManagerLegacy`
|
||||
class instead of the `MultipolygonManager` class.)
|
||||
- Changes for consistent ordering of OSM data: OSM data can come in any order,
|
||||
but usual OSM files are ordered by type, ID, and version. These changes
|
||||
extend this ordering to negative IDs which are sometimes used for objects
|
||||
that have not been uploaded to the OSM server yet. The negative IDs are
|
||||
ordered now before the positive ones, both in order of their absolute value.
|
||||
This is the same ordering as JOSM uses.
|
||||
- Multipolygon assembler now checks for three or more overlapping segments
|
||||
which are always an error and can report them.
|
||||
- Enable use of user-provided `thread::Pool` instances in `Reader` and
|
||||
`Writer` for special use cases.
|
||||
- Growing a `Buffer` will now work with any capacity parameter, it is
|
||||
always rounded up for proper alignment. Buffer constructor with three
|
||||
arguments will now check that commmitted is not larger than capacity.
|
||||
- Updated embedded protozero to 1.5.2.
|
||||
- Update version of Catch unit test framework to 1.9.7.
|
||||
- And, as always, lots of small code cleanups and more tests.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Buffers larger than 2^32 bytes do now work.
|
||||
- Output coordinate with value of -2^31 correctly.
|
||||
- Changeset comments with more than 2^16 characters are now allowed. The new
|
||||
maximum size is 2^32.
|
||||
- `ChangesetDiscussionBuilder::add_comment_text()` could fail silently instead
|
||||
of throwing an exception.
|
||||
- Changeset bounding boxes are now always output to OSM files (any format)
|
||||
if at least one of the corners is defined. This is needed to handle broken
|
||||
data from the main OSM database which contains such cases. The OPL reader
|
||||
has also been fixed to handle this case.
|
||||
- In the example `osmium_location_cache_create`, the index file written is
|
||||
always truncated first.
|
||||
|
||||
|
||||
## [2.12.2] - 2017-05-03
|
||||
|
||||
### Added
|
||||
|
||||
- Add two argument (key, value) overload of `TagMatcher::operator()`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Detect, report, and remove duplicate ways in multipolygon relations.
|
||||
- Change EOF behaviour of Reader: The `Reader::read()` function will now
|
||||
always return an invalid buffer exactly once to signal EOF.
|
||||
- Update QGIS multipolygon project that is part of the test suite to show
|
||||
more problem types.
|
||||
- Copy multipolygon QGIS file for tests to build dir in cmake step.
|
||||
- Some code cleanups and improved debug output in multipolygon code.
|
||||
- Refactor I/O code to simplify code.
|
||||
- Disable some warnings on MSVC.
|
||||
- Various small code and build script changes.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Two bugs in area assembler affecting very complex multipolygons and
|
||||
multipolygons with overlapping or nearly overlapping lines.
|
||||
- Invalid use of iterators leading to undefined behaviour in area assembler
|
||||
code.
|
||||
- Area assembler stats were not correctly counting inner rings that are
|
||||
areas in their own right.
|
||||
- Fix a thread problem valgrind found that might or might not be real.
|
||||
- Read OPL file correctly even if trailing newline in file is missing.
|
||||
- Include order for `osmium/index/map` headers and
|
||||
`osmium/index/node_locations_map.hpp` (or
|
||||
`osmium/handler/node_locations_for_ways.hpp`) doesn't matter any more.
|
||||
|
||||
|
||||
## [2.12.1] - 2017-04-10
|
||||
|
||||
### Added
|
||||
|
||||
- New `TagsFilter::set_default_result()` function.
|
||||
|
||||
### Changed
|
||||
|
||||
- Use larger capacity for `Buffer` if necessary for alignment instead of
|
||||
throwing an exception. Minimum buffer size is now 64 bytes.
|
||||
- Check order of input data in relations collector. The relations collector
|
||||
can not deal with history data or a changes file. This was documented as a
|
||||
requirement, but often lead to problems, because this was ignored by users.
|
||||
So it now checks that the input data it gets is ordered and throws an
|
||||
exception otherwise.
|
||||
- When writing an OSM file, set generator to libosmium if not set by app.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Infinite loop in `Buffer::reserve_space()`. (Issue #202.)
|
||||
- `ObjectPointerCollection::unique()` now removes elements at end.
|
||||
- Tests comparing double using `==` operator.
|
||||
- Build on Cygwin.
|
||||
|
||||
|
||||
## [2.12.0] - 2017-03-07
|
||||
|
||||
### Added
|
||||
|
||||
- `TagMatcher` and `TagsFilter` classes for more flexibly matching tags and
|
||||
selecting objects based on tags. This obsoletes the less flexible classes
|
||||
based on `osmium::tags::Filter` classes.
|
||||
- Extended `index::RelationsMap(Stash|Index)` classes to also allow
|
||||
parent-to-member lookups.
|
||||
- New `nrw_array` helper class.
|
||||
- `ObjectPointerCollection::unique()` function.
|
||||
|
||||
### Changed
|
||||
|
||||
- Area assembler can now detect invalid locations and report them in the
|
||||
stats and through the problem reporter. If the new config option
|
||||
`ignore_invalid_locations` is set, the Assembler will pretend they weren't
|
||||
even referenced in the ways. (Issue #195.)
|
||||
- `osmium::area::Assembler::operator()` will now return a boolean reporting
|
||||
whether building of the area(s) was successful.
|
||||
- Split up area `Assembler` class into three classes: The
|
||||
`detail::BasicAssembler` is now the parent class. `Assembler` is the child
|
||||
class for usual use. The new `GeomAssembler` also derives from
|
||||
`BasicAssembler` and builds areas without taking tags into account at all.
|
||||
This is to support osm2pgsql which does tag handling itself. (Issue #194.)
|
||||
- The `Projection` class can do any projection supported by the Proj.4
|
||||
library. As a special case it now uses our own Mercator projection
|
||||
functions when the web mercator projection (EPSG 3857) is used. This is
|
||||
much faster than going through Proj.4.
|
||||
- Better error messages for low-level file utility functions.
|
||||
- Mark `build_tag_list*` functions in `builder_helper.hpp` as deprecated. You
|
||||
should use the functions from `osmium/builder/attr.hpp` instead.
|
||||
- Improved performance of the `osmium::tags::match_(any|all|none)_of`
|
||||
functions.
|
||||
- Improved performance of string comparison in `tags::Filter`.
|
||||
- Update version of Catch unit test framework to 1.8.1. This meant some
|
||||
tests had to be updated.
|
||||
- Use `get_noexcept()` in `NodeLocationsForWays` handler.
|
||||
- And lots of code and test cleanups...
|
||||
|
||||
### Fixed
|
||||
|
||||
- Terminate called on full non-auto-growing buffer. (Issue #189.)
|
||||
- When file formats were used that were not compiled into the binary, it
|
||||
terminated instead of throwing. (Issue #197.)
|
||||
- Windows build problem related to including two different winsock versions.
|
||||
- Windows build problem related to forced build for old Windows versions.
|
||||
(Issue #196.)
|
||||
- Clear stream contents in ProblemReporterException correctly.
|
||||
- Add `-pthread` compiler and linker options on Linux/OSX. This should fix
|
||||
a problem where some linker versions will not link binaries correctly when
|
||||
the `--as-needed` option is used.
|
||||
- The `Filter::count()` method didn't compile at all.
|
||||
- XML reader doesn't fail on relation member ref=0 any more.
|
||||
|
||||
|
||||
## [2.11.0] - 2017-01-14
|
||||
|
||||
### Added
|
||||
|
||||
- New index::RelationsMap(Stash|Index) classes implementing an index for
|
||||
looking up parent relation IDs given a member relation ID.
|
||||
- Add `get_noexcept()` method to all index maps. For cases where ids are
|
||||
often not in the index using this can speed up a program considerably.
|
||||
- New non-const WayNodeList::operator[].
|
||||
- Default constructed "invalid" Coordinates.
|
||||
- Tile constructor from web mercator coordinates and some helper
|
||||
functions for tile arithmetic.
|
||||
- Tag matcher matching keys using a regex.
|
||||
- New `envelope()` functions on `NodeRefList`, `Way`, and `Area` returning a
|
||||
`Box` object with the geometric envelope of the object.
|
||||
- Add `amenity_list` example.
|
||||
|
||||
### Changed
|
||||
|
||||
- Replaced the implementation for the web mercator projection using the usual
|
||||
tan-formula with a polynomial approximation which is much faster and good
|
||||
enough for OSM data which only has ~1cm resolution anyway. See
|
||||
https://github.com/osmcode/mercator-projection for all the details and
|
||||
benchmarks. You can disable this by defining the macro
|
||||
`OSMIUM_USE_SLOW_MERCATOR_PROJECTION` before including any of the Osmium
|
||||
headers.
|
||||
- Removed the outdated `Makefile`. Always use CMake directly to build.
|
||||
- Refactoring of `osmium::apply()` removing the resursive templates for faster
|
||||
compile times and allowing rvalue handlers.
|
||||
- Lots of code and test cleanups and more documentation.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Handle endianess on FreeBSD properly.
|
||||
- Fixed doxygen config for reproducible builds.
|
||||
|
||||
|
||||
## [2.10.3] - 2016-11-20
|
||||
|
||||
### Changed
|
||||
|
||||
- Round out ObjectPointerCollection implementation and test it.
|
||||
- Updated embedded protozero to 1.4.5.
|
||||
|
||||
|
||||
## [2.10.2] - 2016-11-16
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated embedded protozero to 1.4.4.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Buffer overflow in osmium::Buffer.
|
||||
|
||||
|
||||
## [2.10.1] - 2016-11-15
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated embedded protozero to 1.4.3.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Made IdSet work on 32bit systems.
|
||||
- Fixed endianness check for WKB tests.
|
||||
|
||||
|
||||
## [2.10.0] - 2016-11-11
|
||||
|
||||
### Added
|
||||
|
||||
- The `Reader` can take an additional optional `read_meta` flag. If this is
|
||||
set to false the PBF input will ignore metadata on OSM objects (like version,
|
||||
timestamp, uid, ...) which speeds up file reading by 10 to 20%.
|
||||
- New `IdSet` virtual class with two implementations: `IdSetDense` and
|
||||
`IdSetSmall`. Used to efficiently store a set of Ids. This is often needed
|
||||
to track, for instance, which nodes are needed for ways, etc.
|
||||
- Added more examples and better documented existing examples.
|
||||
- Add a benchmark "mercator" converting all node locations in a file to
|
||||
WebMercator and creating geometries in WKB format.
|
||||
|
||||
### Changed
|
||||
|
||||
- Better queue handling makes I/O faster in some circumstances.
|
||||
- The `FindOsmium.cmake` CMake script can now check a current enough libosmium
|
||||
version is found.
|
||||
- Builders can now be constructed with a reference to parent builder.
|
||||
- Made builders more robust by adding asserts that will catch common usage
|
||||
problems.
|
||||
- Calling `OSMObjectBuilder::add_user()` is now optional, and the method was
|
||||
renamed to `set_user()`. (`add_user()` is marked as deprecated.)
|
||||
- Benchmarks now show compiler and compiler options used.
|
||||
- `Builder::add_item()` now takes a reference instead of pointer (old version
|
||||
of the function marked as deprecated).
|
||||
- GEOS support is deprecated. It does not work any more for GEOS 3.6 or newer.
|
||||
Reason is the changed interface in GEOS 3.6. If there is interest for the
|
||||
GEOS support, we can add support back in later (but probably using the
|
||||
GEOS C API which is more stable than the C++ API). Some tests using GEOS
|
||||
were rewritten to work without it.
|
||||
- The `BoolVector` has been deprecated in favour of the new `IdSet` classes.
|
||||
- Lots of code cleanups and improved API documentation in many places.
|
||||
- The relations collector can now tell you whether a relation member was in
|
||||
the input data. See the new `is_available()` and
|
||||
`get_availability_and_offset()` methods.
|
||||
- Updated embedded Catch unit test header to version 1.5.8.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Parsing of coordinates starting with decimal dot and coordinates in
|
||||
scientific notation.
|
||||
- `~` operator for `entity_bits` doesn't set unused bits any more.
|
||||
- Progress bar can now be (temporarily) removed, to allow other output.
|
||||
|
||||
|
||||
## [2.9.0] - 2016-09-15
|
||||
|
||||
### Added
|
||||
|
||||
- Support for reading OPL files.
|
||||
- For diff output OSM objects in buffers can be marked as only in one or the
|
||||
other file. The OPL and debug output formats support diff output based on
|
||||
this.
|
||||
- Add documentation and range checks to `Tile` struct.
|
||||
- More documentation.
|
||||
- More examples and more extensive comments on examples.
|
||||
- Support for a progress report in `osmium::io::Reader()` and a `ProgressBar`
|
||||
utility class to use it.
|
||||
- New `OSMObject::set_timestamp(const char*)` function.
|
||||
|
||||
### Changed
|
||||
|
||||
- Parse coordinates in scientific notations ourselves.
|
||||
- Updated included protozero version to 1.4.2.
|
||||
- Lots of one-argument constructors are now explicit.
|
||||
- Timestamp parser now uses our own implementation instead of strptime.
|
||||
This is faster and independant of locale settings.
|
||||
- More cases of invalid areas with duplicate segments are reported as
|
||||
errors.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed a problem limiting cache file sizes on Windows to 32 bit.
|
||||
- Fixed includes.
|
||||
- Exception messages for invalid areas do not report "area contains no rings"
|
||||
any more, but "invalid area".
|
||||
|
||||
|
||||
## [2.8.0] - 2016-08-04
|
||||
|
||||
### Added
|
||||
|
||||
- EWKT support.
|
||||
- Track `pop` type calls and queue underruns when `OSMIUM_DEBUG_QUEUE_SIZE`
|
||||
environment variable is set.
|
||||
|
||||
### Changed
|
||||
|
||||
- Switched to newest protozero v1.4.0. This should deliver some speedups
|
||||
when parsing PBF files. This also removes the DeltaEncodeIterator class,
|
||||
which isn't needed any more.
|
||||
- Uses `std::unordered_map` instead of `std::map` in PBF string table code
|
||||
speeding up writing of PBF files considerably.
|
||||
- Uses less memory when writing PBF files (smaller string table by default).
|
||||
- Removes dependency on sparsehash and boost program options libraries for
|
||||
examples.
|
||||
- Cleaned up threaded queue code.
|
||||
|
||||
### Fixed
|
||||
|
||||
- A potentially very bad bug was fixed: When there are many and/or long strings
|
||||
in tag keys and values and/or user names and/or relation roles, the string
|
||||
table inside a PBF block would overflow. I have never seen this happen for
|
||||
normal OSM data, but that doesn't mean it can't happen. The result is that
|
||||
the strings will all be mixed up, keys for values, values for user names or
|
||||
whatever.
|
||||
- Automatically set correct SRID when creating WKB and GEOS geometries.
|
||||
Note that this changes the behaviour of libosmium when creating GEOS
|
||||
geometries. Before we created them with -1 as SRID unless set otherwise.
|
||||
Manual setting of the SRID on the GEOSGeometryFactory is now deprecated.
|
||||
- Allow coordinates of nodes in scientific notation when reading XML files.
|
||||
This shouldn't be used really, but sometimes you can find them.
|
||||
|
||||
|
||||
## [2.7.2] - 2016-06-08
|
||||
|
||||
### Changed
|
||||
|
||||
- Much faster output of OSM files in XML, OPL, or debug formats.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Parsing and output of coordinates now faster and always uses decimal dot
|
||||
independant of locale setting.
|
||||
- Do not output empty discussion elements in changeset XML output.
|
||||
- Data corruption regression in mmap based indexes.
|
||||
|
||||
|
||||
## [2.7.1] - 2016-06-01
|
||||
|
||||
### Fixes
|
||||
|
||||
- Update version number in version.hpp.
|
||||
|
||||
|
||||
## [2.7.0] - 2016-06-01
|
||||
|
||||
### Added
|
||||
|
||||
- New functions for iterating over specific item types in buffers
|
||||
(`osmium::memory::Buffer::select()`), over specific subitems
|
||||
(`osmium::OSMObject::subitems()`), and for iterating over all rings of
|
||||
an area (`osmium::Areas::outer_rings()`, `inner_rings()`).
|
||||
- Debug output optionally prints CRC32 when `add_crc32` file option is set.
|
||||
|
||||
### Changed
|
||||
|
||||
- XML parser will not allow any XML entities which are usually not used in OSM
|
||||
files anyway. This can help avoiding DOS attacks.
|
||||
- Removed SortedQueue implementation which was never used.
|
||||
- Also incorporate Locations in NodeRefs into CRC32 checksums. This means
|
||||
all checksums will be different compared to earlier versions of libosmium.
|
||||
- The completely new algorithm for assembling multipolygons is much faster,
|
||||
has better error reporting, generates statistics and can build more complex
|
||||
multipolygons correctly. The ProblemReporter classes have changed to make
|
||||
this happen, if you have written your own, you have to fix it.
|
||||
- Sparse node location stores are now only sorted if needed, ie. when nodes
|
||||
come in unordered.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Output operator for Location shows full precision.
|
||||
- Undefined behaviour in WKB writer and `types_from_string()` function.
|
||||
- Fix unsigned overflow in pool.hpp.
|
||||
- OSM objects are now ordered by type (nodes, then ways, then relations),
|
||||
then ID, then version, then timestamp. Ordering by timestamp is normally
|
||||
not necessary, because there can't be two objects with same type, ID, and
|
||||
version but different timestamp. But this can happen when diffs are
|
||||
created from OSM extracts, so we check for this here. This change also
|
||||
makes sure IDs are always ordered by absolute IDs, positives first, so
|
||||
order is 0, 1, -1, 2, -2, ...
|
||||
- Data corruption bug fixed in disk based indexes (used for the node
|
||||
location store for instance). This only affected you, if you created
|
||||
and index, closed it, and re-opened it (possibly in a different process)
|
||||
and if there were missing nodes. If you looked up those nodes, you got
|
||||
location (0,0) back instead of an error.
|
||||
- Memory corruption bug showing up with GDAL 2.
|
||||
|
||||
|
||||
## [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.13.1...HEAD
|
||||
[2.13.1]: https://github.com/osmcode/libosmium/compare/v2.13.0...v2.13.1
|
||||
[2.13.0]: https://github.com/osmcode/libosmium/compare/v2.12.2...v2.13.0
|
||||
[2.12.2]: https://github.com/osmcode/libosmium/compare/v2.12.1...v2.12.2
|
||||
[2.12.1]: https://github.com/osmcode/libosmium/compare/v2.12.0...v2.12.1
|
||||
[2.12.0]: https://github.com/osmcode/libosmium/compare/v2.11.0...v2.12.0
|
||||
[2.11.0]: https://github.com/osmcode/libosmium/compare/v2.10.3...v2.11.0
|
||||
[2.10.3]: https://github.com/osmcode/libosmium/compare/v2.10.2...v2.10.3
|
||||
[2.10.2]: https://github.com/osmcode/libosmium/compare/v2.10.1...v2.10.2
|
||||
[2.10.1]: https://github.com/osmcode/libosmium/compare/v2.10.0...v2.10.1
|
||||
[2.10.0]: https://github.com/osmcode/libosmium/compare/v2.9.0...v2.10.0
|
||||
[2.9.0]: https://github.com/osmcode/libosmium/compare/v2.8.0...v2.9.0
|
||||
[2.8.0]: https://github.com/osmcode/libosmium/compare/v2.7.2...v2.8.0
|
||||
[2.7.2]: https://github.com/osmcode/libosmium/compare/v2.7.1...v2.7.2
|
||||
[2.7.1]: https://github.com/osmcode/libosmium/compare/v2.7.0...v2.7.1
|
||||
[2.7.0]: https://github.com/osmcode/libosmium/compare/v2.6.1...v2.7.0
|
||||
[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
|
||||
|
569
third_party/libosmium/CMakeLists.txt
vendored
Normal file
569
third_party/libosmium/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,569 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# 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 13)
|
||||
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)
|
||||
set(data_test_build ON)
|
||||
else()
|
||||
set(dev_build OFF)
|
||||
set(data_test_build OFF)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Coverage")
|
||||
set(data_test_build ON)
|
||||
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" ${data_test_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)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# CCache support
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
option(BUILD_WITH_CCACHE "build using ccache" OFF)
|
||||
|
||||
if(BUILD_WITH_CCACHE)
|
||||
find_program(CCACHE_PROGRAM ccache)
|
||||
if(CCACHE_PROGRAM)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "CCACHE_CPP2=1 ${CCACHE_PROGRAM}")
|
||||
|
||||
# workaround for some clang versions
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_definitions(-Qunused-arguments)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Coverage support
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
## This leads to all sorts of compile problems, so disable for now
|
||||
#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)
|
||||
message(WARNING "Coverage builds don't work for anything but the 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)
|
||||
if(CYGWIN)
|
||||
set(USE_CPP_VERSION gnu++11)
|
||||
else()
|
||||
set(USE_CPP_VERSION c++11)
|
||||
endif()
|
||||
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")
|
||||
# do not show warnings caused by missing .pdb files for libraries
|
||||
set(USUAL_LINK_OPTIONS "/debug /ignore:4099")
|
||||
else()
|
||||
set(USUAL_COMPILE_OPTIONS "-O3 -g")
|
||||
set(USUAL_LINK_OPTIONS "")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32)
|
||||
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)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${USUAL_LINK_OPTIONS}"
|
||||
CACHE STRING "Flags used by the linker during RELWITHDEBINFO builds."
|
||||
FORCE)
|
||||
|
||||
mark_as_advanced(
|
||||
CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
if(BUILD_EXAMPLES)
|
||||
add_subdirectory(test/examples)
|
||||
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
|
||||
--language=c++
|
||||
--quiet
|
||||
-j4
|
||||
--inline-suppr
|
||||
--enable=warning,style,performance,portability,information,missingInclude
|
||||
--force
|
||||
-Uassert -DPROTOZERO_STRICT_API -DPROTOZERO_USE_BUILTIN_BSWAP -UPROTOZERO_USE_VIEW)
|
||||
|
||||
# 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-*"
|
||||
"-modernize-make-unique") # not available in C++11
|
||||
|
||||
list(APPEND CT_CHECKS "readability-*"
|
||||
"-readability-identifier-naming"
|
||||
"-readability-implicit-bool-cast"
|
||||
"-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()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
12
third_party/libosmium/CONTRIBUTING.md
vendored
Normal file
12
third_party/libosmium/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
Some rules for contributing to this project:
|
||||
|
||||
* Please open a separate issue for each problem, question, or comment you have.
|
||||
Do not re-use existing issues for other topics, even if they are similar. This
|
||||
keeps issues small and manageable and makes it much easier to follow through
|
||||
and make sure each problem is taken care of.
|
||||
|
||||
* We'd love for you to send pull requests for fixes you have made or new features
|
||||
you have added. Please read the [notes for developers](NOTES_FOR_DEVELOPERS.md)
|
||||
beforehand which contains some coding guidelines.
|
||||
|
233
third_party/libosmium/EXTERNAL_LICENSES.txt
vendored
Normal file
233
third_party/libosmium/EXTERNAL_LICENSES.txt
vendored
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
third_party/libosmium/LICENSE.txt
vendored
Normal file
23
third_party/libosmium/LICENSE.txt
vendored
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.
|
157
third_party/libosmium/NOTES_FOR_DEVELOPERS.md
vendored
Normal file
157
third_party/libosmium/NOTES_FOR_DEVELOPERS.md
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
|
||||
# Notes for Developers
|
||||
|
||||
Read this if you want to contribute to Libosmium.
|
||||
|
||||
|
||||
## 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` or `libosmium.dll`.
|
||||
|
||||
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 a 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.
|
||||
|
||||
|
||||
## 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.
|
||||
|
||||
Use `include/osmium/util/compatibility.hpp` if there are compatibility problems
|
||||
between compilers due to different C++11 support.
|
||||
|
||||
|
||||
## Operating systems
|
||||
|
||||
Usually all code must work on Linux, OSX, and Windows. Execptions are allowed
|
||||
for some minor functionality, but please discuss this first.
|
||||
|
||||
When writing code and tests, care must be taken that everything works with the
|
||||
CR line ending convention used on Linux and OSX and the CRLF line ending used
|
||||
on Windows. Note that `git` can be run with different settings regarding line
|
||||
ending rewritings on different machines making things more difficult. Some
|
||||
files have been "forced" to LF line endings using `.gitattributes` files.
|
||||
|
||||
|
||||
## 32bit systems
|
||||
|
||||
Libosmium tries to work on 32bit systems whereever possible. But there are
|
||||
some parts which will not work on 32bit systems, mainly because the amount
|
||||
of main memory available is not enough for it to work anyway.
|
||||
|
||||
|
||||
## 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 unit tests using the Catch Unit Test Framework in the `test`
|
||||
directory, some data tests in `test/osm-testdata` and tests of the examples in
|
||||
`test/examples`. They are built by the default cmake config. Run `ctest` to
|
||||
run them. We can always use more tests.
|
||||
|
||||
Tests are run automatically using the Travis (Linux/Mac) and Appveyor (Windows)
|
||||
services. We automatically create coverage reports on Codevoc.io. Note that
|
||||
the coverage percentages reported are not always accurate, because code that
|
||||
is not used in tests at all will not necessarily end up in the binary and
|
||||
the code coverage tool will not know it is there.
|
||||
|
||||
[](https://travis-ci.org/osmcode/libosmium)
|
||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||
[](https://codecov.io/gh/osmcode/libosmium)
|
||||
|
||||
|
||||
## Documenting the code
|
||||
|
||||
All namespaces, classes, functions, attributes, etc. should be documented.
|
||||
|
||||
Osmium uses the [Doxygen](http://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`.
|
||||
|
97
third_party/libosmium/README.md
vendored
Normal file
97
third_party/libosmium/README.md
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
# Libosmium
|
||||
|
||||
http://osmcode.org/libosmium
|
||||
|
||||
A fast and flexible C++ library for working with OpenStreetMap data.
|
||||
|
||||
Libosmium works on Linux, Mac OSX and Windows.
|
||||
|
||||
[](https://travis-ci.org/osmcode/libosmium)
|
||||
[](https://ci.appveyor.com/project/Mapbox/libosmium)
|
||||
[](https://codecov.io/gh/osmcode/libosmium)
|
||||
|
||||
Please see the [Libosmium manual](http://osmcode.org/libosmium/manual.html)
|
||||
for more details than this README can provide.
|
||||
|
||||
|
||||
## 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](http://osmcode.org/libosmium/manual.html#dependencies) in the
|
||||
manual.
|
||||
|
||||
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/)
|
||||
|
||||
|
||||
## Directories
|
||||
|
||||
* benchmarks: Some benchmarks checking different parts of Libosmium.
|
||||
|
||||
* cmake: CMake configuration scripts.
|
||||
|
||||
* doc: Config for API reference 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 detals see the
|
||||
[Building Libosmium](http://osmcode.org/libosmium/manual.html#building-libosmium)
|
||||
chapter in the manual.
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
See the
|
||||
[Libosmium Manual](http://osmcode.org/libosmium/manual.html#running-tests)
|
||||
for instructions.
|
||||
|
||||
|
||||
## 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](http://osmcode.org/libosmium/manual.html#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.
|
||||
|
39
third_party/libosmium/appveyor.yml
vendored
Normal file
39
third_party/libosmium/appveyor.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Configuration for continuous integration service at appveyor.com
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- config: Dev
|
||||
autocrlf: true
|
||||
- config: Dev
|
||||
autocrlf: false
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: true
|
||||
- config: RelWithDebInfo
|
||||
autocrlf: false
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
# Operating system (build VM template)
|
||||
os: Visual Studio 2015
|
||||
|
||||
# scripts that are called at very beginning, before repo cloning
|
||||
init:
|
||||
- git config --global core.autocrlf %autocrlf%
|
||||
- git config --get core.autocrlf
|
||||
|
||||
# clone directory
|
||||
clone_folder: c:\projects\libosmium
|
||||
|
||||
platform: x64
|
||||
|
||||
build_script:
|
||||
- build-appveyor.bat
|
||||
|
||||
# remove garbage VS messages
|
||||
# http://help.appveyor.com/discussions/problems/4569-the-target-_convertpdbfiles-listed-in-a-beforetargets-attribute-at-c-does-not-exist-in-the-project-and-will-be-ignored
|
||||
before_build:
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
53
third_party/libosmium/benchmarks/CMakeLists.txt
vendored
Normal file
53
third_party/libosmium/benchmarks/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# CMake Config
|
||||
#
|
||||
# Libosmium benchmarks
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
message(STATUS "Configuring benchmarks")
|
||||
|
||||
set(BENCHMARKS
|
||||
count
|
||||
count_tag
|
||||
index_map
|
||||
mercator
|
||||
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}})
|
||||
set_pthread_on_target(osmium_benchmark_${benchmark})
|
||||
configure_file(run_benchmark_${benchmark}.sh
|
||||
${CMAKE_CURRENT_BINARY_DIR}/run_benchmark_${benchmark}.sh
|
||||
@ONLY)
|
||||
endforeach()
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" _cmake_build_type)
|
||||
set(_cxx_flags "${CMAKE_CXX_FLAGS_${_cmake_build_type}}")
|
||||
foreach(file setup run_benchmarks)
|
||||
configure_file(${file}.sh ${CMAKE_CURRENT_BINARY_DIR}/${file}.sh @ONLY)
|
||||
endforeach()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
message(STATUS "Configuring benchmarks - done")
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
41
third_party/libosmium/benchmarks/README.md
vendored
Normal file
41
third_party/libosmium/benchmarks/README.md
vendored
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
third_party/libosmium/benchmarks/download_data.sh
vendored
Executable file
12
third_party/libosmium/benchmarks/download_data.sh
vendored
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 2 MB
|
||||
curl --location --output 2_bremen.osm.pbf http://download.geofabrik.de/europe/germany/bremen-latest.osm.pbf # about 16 MB
|
||||
curl --location --output 3_sachsen.osm.pbf http://download.geofabrik.de/europe/germany/sachsen-latest.osm.pbf # about 160 MB
|
||||
curl --location --output 4_germany.osm.pbf http://download.geofabrik.de/europe/germany-latest.osm.pbf # about 3 GB
|
||||
curl --location --output 5_planet.osm.pbf http://planet.osm.org/pbf/planet-latest.osm.pbf # about 35 GB
|
||||
|
55
third_party/libosmium/benchmarks/osmium_benchmark_count.cpp
vendored
Normal file
55
third_party/libosmium/benchmarks/osmium_benchmark_count.cpp
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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(const osmium::Node&) {
|
||||
++nodes;
|
||||
}
|
||||
|
||||
void way(const osmium::Way&) {
|
||||
++ways;
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation&) {
|
||||
++relations;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const 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";
|
||||
}
|
||||
|
56
third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp
vendored
Normal file
56
third_party/libosmium/benchmarks/osmium_benchmark_count_tag.cpp
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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(const osmium::Node& node) {
|
||||
++all;
|
||||
const char* amenity = node.tags().get_value_by_key("amenity");
|
||||
if (amenity && !strcmp(amenity, "post_box")) {
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
void way(const osmium::Way&) {
|
||||
++all;
|
||||
}
|
||||
|
||||
void relation(const osmium::Relation&) {
|
||||
++all;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const 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";
|
||||
}
|
||||
|
41
third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp
vendored
Normal file
41
third_party/libosmium/benchmarks/osmium_benchmark_index_map.cpp
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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>
|
||||
|
||||
using index_type = osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE FORMAT\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const std::string input_filename{argv[1]};
|
||||
const 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();
|
||||
}
|
||||
|
43
third_party/libosmium/benchmarks/osmium_benchmark_mercator.cpp
vendored
Normal file
43
third_party/libosmium/benchmarks/osmium_benchmark_mercator.cpp
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/io/any_input.hpp>
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/visitor.hpp>
|
||||
#include <osmium/geom/wkb.hpp>
|
||||
#include <osmium/geom/mercator_projection.hpp>
|
||||
|
||||
struct GeomHandler : public osmium::handler::Handler {
|
||||
|
||||
osmium::geom::WKBFactory<osmium::geom::MercatorProjection> factory;
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
const std::string geom = factory.create_point(node);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const std::string input_filename{argv[1]};
|
||||
|
||||
osmium::io::Reader reader{input_filename};
|
||||
|
||||
GeomHandler handler;
|
||||
osmium::apply(reader, handler);
|
||||
reader.close();
|
||||
}
|
||||
|
137
third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp
vendored
Normal file
137
third_party/libosmium/benchmarks/osmium_benchmark_static_vs_dynamic_index.cpp
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
|
||||
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 <cstdlib>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#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>
|
||||
|
||||
using static_index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
const std::string location_store{"sparse_mem_array"};
|
||||
|
||||
using dynamic_index_type = osmium::index::map::Map<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
using static_location_handler_type = osmium::handler::NodeLocationsForWays<static_index_type>;
|
||||
using dynamic_location_handler_type = osmium::handler::NodeLocationsForWays<dynamic_index_type>;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const 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};
|
||||
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
osmium::apply(tmp_buffer, static_location_handler);
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
|
||||
const 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();
|
||||
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
osmium::apply(tmp_buffer, dynamic_location_handler);
|
||||
const auto end = std::chrono::steady_clock::now();
|
||||
|
||||
const 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;
|
||||
}
|
||||
}
|
||||
|
||||
const double static_avg = static_sum/runs;
|
||||
const 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";
|
||||
|
||||
const double rfactor = 100.0;
|
||||
const double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor;
|
||||
const double diff_avg = std::round((dynamic_avg - static_avg) * rfactor) / rfactor;
|
||||
const double diff_max = std::round((dynamic_max - static_max) * rfactor) / rfactor;
|
||||
|
||||
const double prfactor = 10.0;
|
||||
const double percent_min = std::round((100.0 * diff_min / static_min) * prfactor) / prfactor;
|
||||
const double percent_avg = std::round((100.0 * diff_avg / static_avg) * prfactor) / prfactor;
|
||||
const 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";
|
||||
}
|
||||
|
35
third_party/libosmium/benchmarks/osmium_benchmark_write_pbf.cpp
vendored
Normal file
35
third_party/libosmium/benchmarks/osmium_benchmark_write_pbf.cpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
|
||||
The code in this file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#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";
|
||||
std::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
third_party/libosmium/benchmarks/run_benchmark_count.sh
vendored
Executable file
22
third_party/libosmium/benchmarks/run_benchmark_count.sh
vendored
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
third_party/libosmium/benchmarks/run_benchmark_count_tag.sh
vendored
Executable file
22
third_party/libosmium/benchmarks/run_benchmark_count_tag.sh
vendored
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
third_party/libosmium/benchmarks/run_benchmark_index_map.sh
vendored
Executable file
27
third_party/libosmium/benchmarks/run_benchmark_index_map.sh
vendored
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
|
||||
|
22
third_party/libosmium/benchmarks/run_benchmark_mercator.sh
vendored
Executable file
22
third_party/libosmium/benchmarks/run_benchmark_mercator.sh
vendored
Executable file
@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# run_benchmark_mercator.sh
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
BENCHMARK_NAME=mercator
|
||||
|
||||
. @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
|
||||
|
21
third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh
vendored
Executable file
21
third_party/libosmium/benchmarks/run_benchmark_static_vs_dynamic_index.sh
vendored
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
third_party/libosmium/benchmarks/run_benchmark_write_pbf.sh
vendored
Executable file
28
third_party/libosmium/benchmarks/run_benchmark_write_pbf.sh
vendored
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
third_party/libosmium/benchmarks/run_benchmarks.sh
vendored
Executable file
15
third_party/libosmium/benchmarks/run_benchmarks.sh
vendored
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
|
||||
|
44
third_party/libosmium/benchmarks/setup.sh
vendored
Executable file
44
third_party/libosmium/benchmarks/setup.sh
vendored
Executable file
@ -0,0 +1,44 @@
|
||||
#!/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_BUILD_TYPE=@CMAKE_BUILD_TYPE@
|
||||
OB_COMPILER=@CMAKE_CXX_COMPILER@
|
||||
OB_COMPILER_VERSION=`$OB_COMPILER --version | head -1`
|
||||
OB_CXXFLAGS="@_cxx_flags@"
|
||||
|
||||
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 "BUILD:"
|
||||
echo "build type\t: $OB_BUILD_TYPE"
|
||||
echo "compiler\t: $OB_COMPILER"
|
||||
echo "CXX version\t: $OB_COMPILER_VERSION"
|
||||
echo "CXX flags\t: $OB_CXXFLAGS"
|
||||
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:"
|
||||
|
126
third_party/libosmium/build-appveyor.bat
vendored
Normal file
126
third_party/libosmium/build-appveyor.bat
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO ~~~~~~ %~f0 ~~~~~~
|
||||
|
||||
SET CUSTOM_CMAKE=cmake-3.6.2-win64-x64
|
||||
::show all available env vars
|
||||
SET
|
||||
ECHO cmake on AppVeyor
|
||||
cmake -version
|
||||
|
||||
ECHO activating VS cmd prompt && CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET lodir=%CD%
|
||||
SET PATH=%lodir%\%CUSTOM_CMAKE%\bin;%PATH%
|
||||
SET LODEPSDIR=%lodir%\libosmium-deps
|
||||
SET PROJ_LIB=%LODEPSDIR%\proj\share
|
||||
SET GDAL_DATA=%LODEPSDIR%\gdal\data
|
||||
::gdal.dll
|
||||
SET PATH=%LODEPSDIR%\gdal\lib;%PATH%
|
||||
::geos.dll
|
||||
SET PATH=%LODEPSDIR%\geos\lib;%PATH%
|
||||
::libtiff.dll
|
||||
SET PATH=%LODEPSDIR%\libtiff\lib;%PATH%
|
||||
::jpeg.dll
|
||||
SET PATH=%LODEPSDIR%\jpeg\lib;%PATH%
|
||||
::libexpat.dll
|
||||
SET PATH=%LODEPSDIR%\expat\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:\=/%
|
||||
|
||||
IF NOT EXIST cm.7z ECHO downloading cmake %CUSTOM_CMAKE% ... && powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/%CUSTOM_CMAKE%.7z -OutFile cm.7z
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
IF NOT EXIST lodeps.7z ECHO downloading binary dependencies... && powershell Invoke-WebRequest https://mapbox.s3.amazonaws.com/windows-builds/windows-build-deps/libosmium-deps-win-14.0-x64.7z -OutFile lodeps.7z
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
IF NOT EXIST %CUSTOM_CMAKE% ECHO extracting cmake... && 7z x cm.7z | %windir%\system32\find "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
IF NOT EXIST %LODEPSDIR% ECHO extracting binary dependencies... && 7z x lodeps.7z | %windir%\system32\find "ing archive"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ECHO %LODEPSDIR%
|
||||
DIR %LODEPSDIR%
|
||||
::TREE %LODEPSDIR%
|
||||
|
||||
::powershell (Get-ChildItem $env:LODEPSDIR\boost\lib -Filter *boost*.dll)[0].BaseName.split('_')[-1]
|
||||
FOR /F "tokens=1 usebackq" %%i in (`powershell ^(Get-ChildItem %LODEPSDIR%\boost\lib -Filter *boost*.dll^)[0].BaseName.split^('_'^)[-1]`) DO SET BOOST_VERSION=%%i
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ECHO BOOST_VERSION^: %BOOST_VERSION%
|
||||
|
||||
ECHO our own cmake
|
||||
cmake -version
|
||||
|
||||
CD %lodir%\..
|
||||
|
||||
IF NOT EXIST osm-testdata ECHO cloning osm-testdata && git clone --depth 1 https://github.com/osmcode/osm-testdata.git
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
CD osm-testdata
|
||||
git fetch
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
git pull
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
CD %lodir%
|
||||
IF EXIST build ECHO deleting build dir... && RD /Q /S build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
MKDIR build
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
CD build
|
||||
ECHO config^: %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
|
||||
SET CMAKE_CMD=cmake .. ^
|
||||
-LA -G "Visual Studio 14 Win64" ^
|
||||
-DOsmium_DEBUG=TRUE ^
|
||||
-DCMAKE_BUILD_TYPE=%config% ^
|
||||
-DBUILD_HEADERS=OFF ^
|
||||
-DBOOST_ROOT=%LODEPSDIR%\boost ^
|
||||
-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
|
||||
|
||||
ECHO calling^: %CMAKE_CMD%
|
||||
%CMAKE_CMD%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
SET avlogger=
|
||||
IF /I "%APPVEYOR%"=="True" SET avlogger=/logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
|
||||
msbuild libosmium.sln ^
|
||||
/p:Configuration=%config% ^
|
||||
/toolsversion:14.0 ^
|
||||
/p:Platform=x64 ^
|
||||
/p:PlatformToolset=v140 %avlogger%
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
ctest --output-on-failure ^
|
||||
-C %config% ^
|
||||
-E testdata-overview
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
|
||||
GOTO DONE
|
||||
|
||||
:ERROR
|
||||
ECHO ~~~~~~ ERROR %~f0 ~~~~~~
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
IF %EL% NEQ 0 ECHO. && ECHO !!! ERRORLEVEL^: %EL% !!! && ECHO.
|
||||
ECHO ~~~~~~ DONE %~f0 ~~~~~~
|
||||
|
||||
EXIT /b %EL%
|
43
third_party/libosmium/build-local.bat
vendored
Normal file
43
third_party/libosmium/build-local.bat
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
SET EL=0
|
||||
|
||||
ECHO ~~~~~~ %~f0 ~~~~~~
|
||||
|
||||
ECHO.
|
||||
ECHO build-local ["config=Dev"]
|
||||
ECHO default config^: RelWithDebInfo
|
||||
ECHO.
|
||||
|
||||
SET platform=x64
|
||||
SET config=RelWithDebInfo
|
||||
|
||||
:: OVERRIDE PARAMETERS >>>>>>>>
|
||||
:NEXT-ARG
|
||||
|
||||
IF '%1'=='' GOTO ARGS-DONE
|
||||
ECHO setting %1
|
||||
SET %1
|
||||
SHIFT
|
||||
GOTO NEXT-ARG
|
||||
|
||||
:ARGS-DONE
|
||||
::<<<<< OVERRIDE PARAMETERS
|
||||
|
||||
WHERE 7z
|
||||
IF %ERRORLEVEL% NEQ 0 ECHO 7zip not on PATH && GOTO ERROR
|
||||
|
||||
CALL build-appveyor.bat
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
|
||||
|
||||
GOTO DONE
|
||||
|
||||
:ERROR
|
||||
ECHO ~~~~~~ ERROR %~f0 ~~~~~~
|
||||
SET EL=%ERRORLEVEL%
|
||||
|
||||
:DONE
|
||||
IF %EL% NEQ 0 ECHO. && ECHO !!! ERRORLEVEL^: %EL% !!! && ECHO.
|
||||
ECHO ~~~~~~ DONE %~f0 ~~~~~~
|
||||
|
||||
EXIT /b %EL%
|
153
third_party/libosmium/cmake/FindGem.cmake
vendored
Normal file
153
third_party/libosmium/cmake/FindGem.cmake
vendored
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")
|
||||
|
370
third_party/libosmium/cmake/FindOsmium.cmake
vendored
Normal file
370
third_party/libosmium/cmake/FindOsmium.cmake
vendored
Normal file
@ -0,0 +1,370 @@
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# 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 [version] REQUIRED COMPONENTS <XXX>)
|
||||
# include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||
#
|
||||
# The version number is optional. If it is not set, any version of
|
||||
# libosmium will do.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# This is the list of directories where we look for osmium and protozero
|
||||
# includes.
|
||||
set(_osmium_include_path
|
||||
../libosmium
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/opt/local # DarwinPorts
|
||||
/opt
|
||||
)
|
||||
|
||||
# Look for the header file.
|
||||
find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp
|
||||
PATH_SUFFIXES include
|
||||
PATHS ${_osmium_include_path}
|
||||
)
|
||||
|
||||
# Check libosmium version number
|
||||
if(Osmium_FIND_VERSION)
|
||||
file(STRINGS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp" _libosmium_version_define REGEX "#define LIBOSMIUM_VERSION_STRING")
|
||||
if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"")
|
||||
set(_libosmium_version "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
set(_libosmium_version "unknown")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
||||
message(STATUS "Looking for protozero")
|
||||
find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp
|
||||
PATH_SUFFIXES include
|
||||
PATHS ${_osmium_include_path}
|
||||
${OSMIUM_INCLUDE_DIR}
|
||||
)
|
||||
if(PROTOZERO_INCLUDE_DIR)
|
||||
message(STATUS "Looking for protozero - found")
|
||||
else()
|
||||
message(STATUS "Looking for protozero - not found")
|
||||
endif()
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR)
|
||||
if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_INCLUDE_DIR)
|
||||
list(APPEND OSMIUM_PBF_LIBRARIES
|
||||
${ZLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
if(WIN32)
|
||||
# This is needed for the ntohl() function
|
||||
list(APPEND OSMIUM_PBF_LIBRARIES ws2_32)
|
||||
endif()
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${PROTOZERO_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 the optional version check
|
||||
# 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}
|
||||
VERSION_VAR _libosmium_version)
|
||||
unset(OSMIUM_EXTRA_FIND_VARS)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# A function for setting the -pthread option in compilers/linkers
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
function(set_pthread_on_target _target)
|
||||
if(NOT MSVC)
|
||||
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "-pthread")
|
||||
if(NOT APPLE)
|
||||
set_target_properties(${_target} PROPERTIES LINK_FLAGS "-pthread")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# 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)
|
||||
|
||||
# Disable warning C4503: "decorated name length exceeded, name was truncated"
|
||||
# there are more than 150 of generated names in libosmium longer than 4096 symbols supported in MSVC
|
||||
add_definitions(-wd4503)
|
||||
|
||||
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
third_party/libosmium/cmake/README
vendored
Normal file
3
third_party/libosmium/cmake/README
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
FindGem.cmake from https://github.com/rock-core/base-cmake
|
||||
|
15
third_party/libosmium/cmake/build.bat
vendored
Normal file
15
third_party/libosmium/cmake/build.bat
vendored
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
|
48
third_party/libosmium/cmake/iwyu.sh
vendored
Executable file
48
third_party/libosmium/cmake/iwyu.sh
vendored
Executable file
@ -0,0 +1,48 @@
|
||||
#!/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...
|
||||
#
|
||||
|
||||
# If these are set, the wrong compiler is used by iwyu and there will be
|
||||
# errors about missing includes.
|
||||
unset CC
|
||||
unset CXX
|
||||
|
||||
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
third_party/libosmium/doc/CMakeLists.txt
vendored
Normal file
33
third_party/libosmium/doc/CMakeLists.txt
vendored
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
third_party/libosmium/doc/Doxyfile.in
vendored
Normal file
2313
third_party/libosmium/doc/Doxyfile.in
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
third_party/libosmium/doc/README.md
vendored
Normal file
8
third_party/libosmium/doc/README.md
vendored
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.
|
||||
|
21
third_party/libosmium/doc/doc.md
vendored
Normal file
21
third_party/libosmium/doc/doc.md
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
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
third_party/libosmium/doc/header.html
vendored
Normal file
56
third_party/libosmium/doc/header.html
vendored
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
third_party/libosmium/doc/osmium.css
vendored
Normal file
22
third_party/libosmium/doc/osmium.css
vendored
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;
|
||||
}
|
||||
|
74
third_party/libosmium/examples/CMakeLists.txt
vendored
Normal file
74
third_party/libosmium/examples/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# CMake Config
|
||||
#
|
||||
# Libosmium examples
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
message(STATUS "Configuring examples")
|
||||
|
||||
set(EXAMPLES
|
||||
amenity_list
|
||||
area_test
|
||||
change_tags
|
||||
convert
|
||||
count
|
||||
create_pois
|
||||
debug
|
||||
dump_internal
|
||||
filter_discussions
|
||||
index_lookup
|
||||
location_cache_create
|
||||
location_cache_use
|
||||
pub_names
|
||||
read
|
||||
read_with_progress
|
||||
road_length
|
||||
tiles
|
||||
CACHE STRING "Example programs"
|
||||
)
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Examples depending on wingetopt
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
set(GETOPT_EXAMPLES area_test convert index_lookup)
|
||||
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()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
#
|
||||
# Configure examples
|
||||
#
|
||||
#-----------------------------------------------------------------------------
|
||||
message(STATUS "Configuring examples - Building these examples:")
|
||||
foreach(example ${EXAMPLES})
|
||||
message(STATUS " - osmium_${example}")
|
||||
add_executable(osmium_${example} "osmium_${example}.cpp")
|
||||
set_pthread_on_target(osmium_${example})
|
||||
target_link_libraries(osmium_${example} ${OSMIUM_IO_LIBRARIES} ${EXAMPLE_LIBS_${example}})
|
||||
add_test(NAME examples_usage_${example} COMMAND osmium_${example})
|
||||
set_tests_properties(examples_usage_${example} PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "^Usage: "
|
||||
)
|
||||
endforeach()
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
message(STATUS "Configuring examples - done")
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
45
third_party/libosmium/examples/README.md
vendored
Normal file
45
third_party/libosmium/examples/README.md
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
# Osmium example programs
|
||||
|
||||
The programs in this directory are intended as examples for developers. They
|
||||
contain extensive comments explaining what's going on. Note that the examples
|
||||
only cover a small part of what Osmium can do, you should also read the manuals
|
||||
and API documentation.
|
||||
|
||||
All programs can be run without arguments and they will tell you how to use
|
||||
them.
|
||||
|
||||
## Very simple examples
|
||||
|
||||
* `osmium_read`
|
||||
* `osmium_count`
|
||||
* `osmium_debug`
|
||||
* `osmium_tiles`
|
||||
|
||||
## Still reasonably simple examples
|
||||
|
||||
* `osmium_amenity_list`
|
||||
* `osmium_read_with_progress`
|
||||
* `osmium_filter_discussions`
|
||||
* `osmium_convert`
|
||||
* `osmium_pub_names`
|
||||
* `osmium_road_length`
|
||||
|
||||
## More advanced examples
|
||||
|
||||
* `osmium_area_test`
|
||||
* `osmium_create_pois`
|
||||
|
||||
## Even more advanced examples
|
||||
|
||||
* `osmium_change_tags`
|
||||
* `osmium_location_cache_create`
|
||||
* `osmium_location_cache_use`
|
||||
* `osmium_dump_internal`
|
||||
* `osmium_index_lookup`
|
||||
|
||||
## License
|
||||
|
||||
The code in these example files is released into the Public Domain. Feel free
|
||||
to copy the code and build on it.
|
||||
|
171
third_party/libosmium/examples/osmium_amenity_list.cpp
vendored
Normal file
171
third_party/libosmium/examples/osmium_amenity_list.cpp
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_amenity_list
|
||||
|
||||
Create a list of all amenities in the OSM input data. The type of amenity
|
||||
(tag value) and, if available, the name is printed. For nodes, the location
|
||||
is printed, for areas the center location.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* the MultipolygonManager and Assembler to assemble areas (multipolygons)
|
||||
* your own handler that works with areas (multipolygons)
|
||||
* accessing tags
|
||||
* osmium::geom::Coordinates
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_debug
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdio> // for std::printf
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cerr
|
||||
#include <string> // for std::string
|
||||
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
// For assembling multipolygons
|
||||
#include <osmium/area/assembler.hpp>
|
||||
#include <osmium/area/multipolygon_manager.hpp>
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// For osmium::geom::Coordinates
|
||||
#include <osmium/geom/coordinates.hpp>
|
||||
|
||||
class AmenityHandler : public osmium::handler::Handler {
|
||||
|
||||
// Print info about one amenity to stdout.
|
||||
void print_amenity(const char* type, const char* name, const osmium::geom::Coordinates& c) {
|
||||
std::printf("%8.4f,%8.4f %-15s %s\n", c.x, c.y, type, name ? name : "");
|
||||
}
|
||||
|
||||
// Calculate the center point of a NodeRefList.
|
||||
osmium::geom::Coordinates calc_center(const osmium::NodeRefList& nr_list) {
|
||||
// Coordinates simply store an X and Y coordinate pair as doubles.
|
||||
// (Unlike osmium::Location which stores them more efficiently as
|
||||
// 32 bit integers.) Use Coordinates when you want to do calculations
|
||||
// or store projected coordinates.
|
||||
osmium::geom::Coordinates c{0.0, 0.0};
|
||||
|
||||
for (const auto& nr : nr_list) {
|
||||
c.x += nr.lon();
|
||||
c.y += nr.lat();
|
||||
}
|
||||
|
||||
c.x /= nr_list.size();
|
||||
c.y /= nr_list.size();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void node(const osmium::Node& node) {
|
||||
// Getting a tag value can be expensive, because a list of tags has
|
||||
// to be gone through and each tag has to be checked. So we store the
|
||||
// result and reuse it.
|
||||
const char* amenity = node.tags()["amenity"];
|
||||
if (amenity) {
|
||||
print_amenity(amenity, node.tags()["name"], node.location());
|
||||
}
|
||||
}
|
||||
|
||||
void area(const osmium::Area& area) {
|
||||
const char* amenity = area.tags()["amenity"];
|
||||
if (amenity) {
|
||||
// Use the center of the first outer ring. Because we set
|
||||
// create_empty_areas = false in the assembler config, we can
|
||||
// be sure there will always be at least one outer ring.
|
||||
const auto center = calc_center(*area.cbegin<osmium::OuterRing>());
|
||||
|
||||
print_amenity(amenity, area.tags()["name"], center);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class AmenityHandler
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The input file
|
||||
const osmium::io::File input_file{argv[1]};
|
||||
|
||||
// Configuration for the multipolygon assembler. We disable the option to
|
||||
// create empty areas when invalid multipolygons are encountered. This
|
||||
// means areas created have a valid geometry and invalid multipolygons
|
||||
// are simply ignored.
|
||||
osmium::area::Assembler::config_type assembler_config;
|
||||
assembler_config.create_empty_areas = false;
|
||||
|
||||
// Initialize the MultipolygonManager. Its job is to collect all
|
||||
// relations and member ways needed for each area. It then calls an
|
||||
// instance of the osmium::area::Assembler class (with the given config)
|
||||
// to actually assemble one area.
|
||||
osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config};
|
||||
|
||||
// We read the input file twice. In the first pass, only relations are
|
||||
// read and fed into the multipolygon manager.
|
||||
std::cerr << "Pass 1...\n";
|
||||
osmium::relations::read_relations(input_file, mp_manager);
|
||||
std::cerr << "Pass 1 done\n";
|
||||
|
||||
// The index storing all node locations.
|
||||
index_type index;
|
||||
|
||||
// The handler that stores all node locations in the index and adds them
|
||||
// to the ways.
|
||||
location_handler_type location_handler{index};
|
||||
|
||||
// If a location is not available in the index, we ignore it. It might
|
||||
// not be needed (if it is not part of a multipolygon relation), so why
|
||||
// create an error?
|
||||
location_handler.ignore_errors();
|
||||
|
||||
// Create our handler.
|
||||
AmenityHandler data_handler;
|
||||
|
||||
// On the second pass we read all objects and run them first through the
|
||||
// node location handler and then the multipolygon manager. The manager
|
||||
// will put the areas it has created into the "buffer" which are then
|
||||
// fed through our handler.
|
||||
//
|
||||
// The read_meta::no option disables reading of meta data (such as version
|
||||
// numbers, timestamps, etc.) which are not needed in this case. Disabling
|
||||
// this can speed up your program.
|
||||
std::cerr << "Pass 2...\n";
|
||||
osmium::io::Reader reader{input_file, osmium::io::read_meta::no};
|
||||
|
||||
osmium::apply(reader, location_handler, data_handler, mp_manager.handler([&data_handler](const osmium::memory::Buffer& area_buffer) {
|
||||
osmium::apply(area_buffer, data_handler);
|
||||
}));
|
||||
|
||||
reader.close();
|
||||
std::cerr << "Pass 2 done\n";
|
||||
}
|
||||
|
210
third_party/libosmium/examples/osmium_area_test.cpp
vendored
Normal file
210
third_party/libosmium/examples/osmium_area_test.cpp
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_area_test
|
||||
|
||||
Create multipolygons from OSM data and dump them to stdout in one of two
|
||||
formats: WKT or using the built-in Dump format.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* the MultipolygonManager and Assembler to assemble areas (multipolygons)
|
||||
* your own handler that works with areas (multipolygons)
|
||||
* the WKTFactory to write geometries in WKT format
|
||||
* the Dump handler
|
||||
* the DynamicHandler
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_debug
|
||||
* osmium_amenity_list
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <getopt.h> // for getopt_long
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
|
||||
// For assembling multipolygons
|
||||
#include <osmium/area/assembler.hpp>
|
||||
#include <osmium/area/multipolygon_manager.hpp>
|
||||
|
||||
// For the DynamicHandler class
|
||||
#include <osmium/dynamic_handler.hpp>
|
||||
|
||||
// For the WKT factory
|
||||
#include <osmium/geom/wkt.hpp>
|
||||
|
||||
// For the Dump handler
|
||||
#include <osmium/handler/dump.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
// This handler writes all area geometries out in WKT (Well Known Text) format.
|
||||
class WKTDump : public osmium::handler::Handler {
|
||||
|
||||
// This factory is used to create a geometry in WKT format from OSM
|
||||
// objects. The template parameter is empty here, because we output WGS84
|
||||
// coordinates, but could be used for a projection.
|
||||
osmium::geom::WKTFactory<> m_factory;
|
||||
|
||||
public:
|
||||
|
||||
// This callback is called by osmium::apply for each area in the data.
|
||||
void area(const osmium::Area& area) {
|
||||
try {
|
||||
std::cout << m_factory.create_multipolygon(area) << "\n";
|
||||
} catch (const osmium::geometry_error& e) {
|
||||
std::cout << "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, nullptr, 'h'},
|
||||
{"dump-wkt", no_argument, nullptr, 'w'},
|
||||
{"dump-objects", no_argument, nullptr, 'o'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
// Initialize an empty DynamicHandler. Later it will be associated
|
||||
// with one of the handlers. You can think of the DynamicHandler as
|
||||
// a kind of "variant handler" or a "pointer handler" pointing to the
|
||||
// real handler.
|
||||
osmium::handler::DynamicHandler handler;
|
||||
|
||||
// Read options from command line.
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "hwo", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_help();
|
||||
std::exit(0);
|
||||
case 'w':
|
||||
handler.set<WKTDump>();
|
||||
break;
|
||||
case 'o':
|
||||
handler.set<osmium::handler::Dump>(std::cout);
|
||||
break;
|
||||
default:
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const int remaining_args = argc - optind;
|
||||
if (remaining_args != 1) {
|
||||
std::cerr << "Usage: " << argv[0] << " [OPTIONS] OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
osmium::io::File input_file{argv[optind]};
|
||||
|
||||
// Configuration for the multipolygon assembler. Here the default settings
|
||||
// are used, but you could change multiple settings.
|
||||
osmium::area::Assembler::config_type assembler_config;
|
||||
|
||||
// Set up a filter matching only forests. This will be used to only build
|
||||
// areas with matching tags.
|
||||
osmium::TagsFilter filter{false};
|
||||
filter.add_rule(true, "landuse", "forest");
|
||||
filter.add_rule(true, "natural", "wood");
|
||||
|
||||
// Initialize the MultipolygonManager. Its job is to collect all
|
||||
// relations and member ways needed for each area. It then calls an
|
||||
// instance of the osmium::area::Assembler class (with the given config)
|
||||
// to actually assemble one area. The filter parameter is optional, if
|
||||
// it is not set, all areas will be built.
|
||||
osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config, filter};
|
||||
|
||||
// We read the input file twice. In the first pass, only relations are
|
||||
// read and fed into the multipolygon manager.
|
||||
std::cerr << "Pass 1...\n";
|
||||
osmium::relations::read_relations(input_file, mp_manager);
|
||||
std::cerr << "Pass 1 done\n";
|
||||
|
||||
// Output the amount of main memory used so far. All multipolygon relations
|
||||
// are in memory now.
|
||||
std::cerr << "Memory:\n";
|
||||
osmium::relations::print_used_memory(std::cerr, mp_manager.used_memory());
|
||||
|
||||
// The index storing all node locations.
|
||||
index_type index;
|
||||
|
||||
// The handler that stores all node locations in the index and adds them
|
||||
// to the ways.
|
||||
location_handler_type location_handler{index};
|
||||
|
||||
// If a location is not available in the index, we ignore it. It might
|
||||
// not be needed (if it is not part of a multipolygon relation), so why
|
||||
// create an error?
|
||||
location_handler.ignore_errors();
|
||||
|
||||
// On the second pass we read all objects and run them first through the
|
||||
// node location handler and then the multipolygon collector. The collector
|
||||
// will put the areas it has created into the "buffer" which are then
|
||||
// fed through our "handler".
|
||||
std::cerr << "Pass 2...\n";
|
||||
osmium::io::Reader reader{input_file};
|
||||
osmium::apply(reader, location_handler, mp_manager.handler([&handler](osmium::memory::Buffer&& buffer) {
|
||||
osmium::apply(buffer, handler);
|
||||
}));
|
||||
reader.close();
|
||||
std::cerr << "Pass 2 done\n";
|
||||
|
||||
// Output the amount of main memory used so far. All complete multipolygon
|
||||
// relations have been cleaned up.
|
||||
std::cerr << "Memory:\n";
|
||||
osmium::relations::print_used_memory(std::cerr, mp_manager.used_memory());
|
||||
|
||||
// If there were multipolgyon relations in the input, but some of their
|
||||
// members are not in the input file (which often happens for extracts)
|
||||
// this will write the IDs of the incomplete relations to stderr.
|
||||
std::vector<osmium::object_id_type> incomplete_relations_ids;
|
||||
mp_manager.for_each_incomplete_relation([&](const osmium::relations::RelationHandle& handle){
|
||||
incomplete_relations_ids.push_back(handle->id());
|
||||
});
|
||||
if (!incomplete_relations_ids.empty()) {
|
||||
std::cerr << "Warning! Some member ways missing for these multipolygon relations:";
|
||||
for (const auto id : incomplete_relations_ids) {
|
||||
std::cerr << " " << id;
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
|
203
third_party/libosmium/examples/osmium_change_tags.cpp
vendored
Normal file
203
third_party/libosmium/examples/osmium_change_tags.cpp
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_change_tags
|
||||
|
||||
An example how tags in OSM files can be removed or changed. Removes
|
||||
"created_by" tags and changes tag "landuse=forest" into "natural_wood".
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input and output
|
||||
* Osmium buffers
|
||||
* your own handler
|
||||
* access to tags
|
||||
* using builders to write data
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_pub_names
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <cstring> // for std::strcmp
|
||||
#include <exception> // for std::exception
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
#include <utility> // for std::move
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// Allow any format of output files (XML, PBF, ...)
|
||||
#include <osmium/io/any_output.hpp>
|
||||
|
||||
// We want to use the builder interface
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
|
||||
// We want to use the handler interface
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// The functions in this class will be called for each object in the input
|
||||
// and will write a (changed) copy of those objects to the given buffer.
|
||||
class RewriteHandler : public osmium::handler::Handler {
|
||||
|
||||
osmium::memory::Buffer& m_buffer;
|
||||
|
||||
// Copy attributes common to all OSM objects (nodes, ways, and relations).
|
||||
template <typename T>
|
||||
void copy_attributes(T& builder, const osmium::OSMObject& object) {
|
||||
// The setter functions on the builder object all return the same
|
||||
// builder object so they can be chained.
|
||||
builder.set_id(object.id())
|
||||
.set_version(object.version())
|
||||
.set_changeset(object.changeset())
|
||||
.set_timestamp(object.timestamp())
|
||||
.set_uid(object.uid())
|
||||
.set_user(object.user());
|
||||
}
|
||||
|
||||
// Copy all tags with two changes:
|
||||
// * Do not copy "created_by" tags
|
||||
// * Change "landuse=forest" into "natural=wood"
|
||||
void copy_tags(osmium::builder::Builder& parent, const osmium::TagList& tags) {
|
||||
|
||||
// The TagListBuilder is used to create a list of tags. The parameter
|
||||
// to create it is a reference to the builder of the object that
|
||||
// should have those tags.
|
||||
osmium::builder::TagListBuilder builder{parent};
|
||||
|
||||
// Iterate over all tags and build new tags using the new builder
|
||||
// based on the old ones.
|
||||
for (const auto& tag : tags) {
|
||||
if (std::strcmp(tag.key(), "created_by")) {
|
||||
if (!std::strcmp(tag.key(), "landuse") && !std::strcmp(tag.value(), "forest")) {
|
||||
// add_tag() can be called with key and value C strings
|
||||
builder.add_tag("natural", "wood");
|
||||
} else {
|
||||
// add_tag() can also be called with an osmium::Tag
|
||||
builder.add_tag(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Constructor. New data will be added to the given buffer.
|
||||
explicit RewriteHandler(osmium::memory::Buffer& buffer) :
|
||||
m_buffer(buffer) {
|
||||
}
|
||||
|
||||
// The node handler is called for each node in the input data.
|
||||
void node(const osmium::Node& node) {
|
||||
// Open a new scope, because the NodeBuilder we are creating has to
|
||||
// be destructed, before we can call commit() below.
|
||||
{
|
||||
// To create a node, we need a NodeBuilder object. It will create
|
||||
// the node in the given buffer.
|
||||
osmium::builder::NodeBuilder builder{m_buffer};
|
||||
|
||||
// Copy common object attributes over to the new node.
|
||||
copy_attributes(builder, node);
|
||||
|
||||
// Copy the location over to the new node.
|
||||
builder.set_location(node.location());
|
||||
|
||||
// Copy (changed) tags.
|
||||
copy_tags(builder, node.tags());
|
||||
}
|
||||
|
||||
// Once the object is written to the buffer completely, we have to call
|
||||
// commit().
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
// The way handler is called for each way in the input data.
|
||||
void way(const osmium::Way& way) {
|
||||
{
|
||||
osmium::builder::WayBuilder builder{m_buffer};
|
||||
copy_attributes(builder, way);
|
||||
copy_tags(builder, way.tags());
|
||||
|
||||
// Copy the node list over to the new way.
|
||||
builder.add_item(way.nodes());
|
||||
}
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
// The relation handler is called for each relation in the input data.
|
||||
void relation(const osmium::Relation& relation) {
|
||||
{
|
||||
osmium::builder::RelationBuilder builder{m_buffer};
|
||||
copy_attributes(builder, relation);
|
||||
copy_tags(builder, relation.tags());
|
||||
|
||||
// Copy the relation member list over to the new way.
|
||||
builder.add_item(relation.members());
|
||||
}
|
||||
m_buffer.commit();
|
||||
}
|
||||
|
||||
}; // class RewriteHandler
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " INFILE OUTFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Get input and output file names from command line.
|
||||
std::string input_file_name{argv[1]};
|
||||
std::string output_file_name{argv[2]};
|
||||
|
||||
try {
|
||||
// Initialize Reader
|
||||
osmium::io::Reader reader{input_file_name};
|
||||
|
||||
// Get header from input file and change the "generator" setting to
|
||||
// ourselves.
|
||||
osmium::io::Header header = reader.header();
|
||||
header.set("generator", "osmium_change_tags");
|
||||
|
||||
// Initialize Writer using the header from above and tell it that it
|
||||
// is allowed to overwrite a possibly existing file.
|
||||
osmium::io::Writer writer{output_file_name, header, osmium::io::overwrite::allow};
|
||||
|
||||
// Read in buffers with OSM objects until there are no more.
|
||||
while (osmium::memory::Buffer input_buffer = reader.read()) {
|
||||
// Create an empty buffer with the same size as the input buffer.
|
||||
// We'll copy the changed data into output buffer, the changes
|
||||
// are small, so the output buffer needs to be about the same size.
|
||||
// In case it has to be bigger, we allow it to grow automatically
|
||||
// by adding the auto_grow::yes parameter.
|
||||
osmium::memory::Buffer output_buffer{input_buffer.committed(), osmium::memory::Buffer::auto_grow::yes};
|
||||
|
||||
// Construct a handler as defined above and feed the input buffer
|
||||
// to it.
|
||||
RewriteHandler handler{output_buffer};
|
||||
osmium::apply(input_buffer, handler);
|
||||
|
||||
// Write out the contents of the output buffer.
|
||||
writer(std::move(output_buffer));
|
||||
}
|
||||
|
||||
// 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();
|
||||
} catch (const std::exception& e) {
|
||||
// All exceptions used by the Osmium library derive from std::exception.
|
||||
std::cerr << e.what() << "\n";
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
155
third_party/libosmium/examples/osmium_convert.cpp
vendored
Normal file
155
third_party/libosmium/examples/osmium_convert.cpp
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_convert
|
||||
|
||||
Convert OSM files from one format into another.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input and output
|
||||
* file types
|
||||
* Osmium buffers
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <exception> // for std::exception
|
||||
#include <getopt.h> // for getopt_long
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// Allow any format of output files (XML, PBF, ...)
|
||||
#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, nullptr, 'h'},
|
||||
{"from-format", required_argument, nullptr, 'f'},
|
||||
{"to-format", required_argument, nullptr, 't'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
// Input and output format are empty by default. Later this will mean that
|
||||
// the format should be taken from the input and output file suffix,
|
||||
// respectively.
|
||||
std::string input_format;
|
||||
std::string output_format;
|
||||
|
||||
// Read options from command line.
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "dhf:t:", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_help();
|
||||
std::exit(0);
|
||||
case 'f':
|
||||
input_format = optarg;
|
||||
break;
|
||||
case 't':
|
||||
output_format = optarg;
|
||||
break;
|
||||
default:
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const int remaining_args = argc - optind;
|
||||
if (remaining_args == 0 || remaining_args > 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Get input file name from command line.
|
||||
std::string input_file_name;
|
||||
if (remaining_args >= 1) {
|
||||
input_file_name = argv[optind];
|
||||
}
|
||||
|
||||
// Get output file name from command line.
|
||||
std::string output_file_name;
|
||||
if (remaining_args == 2) {
|
||||
output_file_name = argv[optind+1];
|
||||
}
|
||||
|
||||
// This declares the input and output files using either the suffix of
|
||||
// the file names or the format in the 2nd argument. It does not yet open
|
||||
// the files.
|
||||
const osmium::io::File input_file{input_file_name, input_format};
|
||||
const osmium::io::File output_file{output_file_name, output_format};
|
||||
|
||||
// Input and output files can be OSM data files (without history) or
|
||||
// OSM history files. History files are detected if they use the '.osh'
|
||||
// file suffix.
|
||||
if ( input_file.has_multiple_object_versions() &&
|
||||
!output_file.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";
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize Reader
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// Get header from input file and change the "generator" setting to
|
||||
// ourselves.
|
||||
osmium::io::Header header = reader.header();
|
||||
header.set("generator", "osmium_convert");
|
||||
|
||||
// Initialize Writer using the header from above and tell it that it
|
||||
// is allowed to overwrite a possibly existing file.
|
||||
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||
|
||||
// Copy the contents from the input to the output file one buffer at
|
||||
// a time. This is much easier and faster than copying each object
|
||||
// in the file. Buffers are moved around, so there is no cost for
|
||||
// copying in memory.
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
writer(std::move(buffer));
|
||||
}
|
||||
|
||||
// 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();
|
||||
} catch (const std::exception& e) {
|
||||
// All exceptions used by the Osmium library derive from std::exception.
|
||||
std::cerr << e.what() << "\n";
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
95
third_party/libosmium/examples/osmium_count.cpp
vendored
Normal file
95
third_party/libosmium/examples/osmium_count.cpp
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_count
|
||||
|
||||
Counts the number of nodes, ways, and relations in the input file.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* OSM file input
|
||||
* your own handler
|
||||
* the memory usage utility class
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdint> // for std::uint64_t
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// We want to use the handler interface
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
// Utility class gives us access to memory usage information
|
||||
#include <osmium/util/memory.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// Handler derive from the osmium::handler::Handler base class. Usually you
|
||||
// overwrite functions node(), way(), and relation(). Other functions are
|
||||
// available, too. Read the API documentation for details.
|
||||
struct CountHandler : public osmium::handler::Handler {
|
||||
|
||||
std::uint64_t nodes = 0;
|
||||
std::uint64_t ways = 0;
|
||||
std::uint64_t relations = 0;
|
||||
|
||||
// This callback is called by osmium::apply for each node in the data.
|
||||
void node(const osmium::Node&) noexcept {
|
||||
++nodes;
|
||||
}
|
||||
|
||||
// This callback is called by osmium::apply for each way in the data.
|
||||
void way(const osmium::Way&) noexcept {
|
||||
++ways;
|
||||
}
|
||||
|
||||
// This callback is called by osmium::apply for each relation in the data.
|
||||
void relation(const osmium::Relation&) noexcept {
|
||||
++relations;
|
||||
}
|
||||
|
||||
}; // struct CountHandler
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// Create an instance of our own CountHandler and push the data from the
|
||||
// input file through it.
|
||||
CountHandler handler;
|
||||
osmium::apply(reader, handler);
|
||||
|
||||
// You do not have to close the Reader explicitly, but because the
|
||||
// destructor can't throw, you will not see any errors otherwise.
|
||||
reader.close();
|
||||
|
||||
std::cout << "Nodes: " << handler.nodes << "\n";
|
||||
std::cout << "Ways: " << handler.ways << "\n";
|
||||
std::cout << "Relations: " << handler.relations << "\n";
|
||||
|
||||
// Because of the huge amount of OSM data, some Osmium-based programs
|
||||
// (though not this one) can use huge amounts of data. So checking actual
|
||||
// memore usage is often useful and can be done easily with this class.
|
||||
// (Currently only works on Linux, not OSX and Windows.)
|
||||
osmium::MemoryUsage memory;
|
||||
|
||||
std::cout << "\nMemory used: " << memory.peak() << " MBytes\n";
|
||||
}
|
||||
|
100
third_party/libosmium/examples/osmium_create_pois.cpp
vendored
Normal file
100
third_party/libosmium/examples/osmium_create_pois.cpp
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_create_pois
|
||||
|
||||
Showing how to create nodes for points of interest out of thin air.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file output
|
||||
* Osmium buffers
|
||||
* using builders to write data
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_pub_names
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <cstring> // for std::strcmp
|
||||
#include <ctime> // for std::time
|
||||
#include <exception> // for std::exception
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
#include <utility> // for std::move
|
||||
|
||||
// Allow any format of output files (XML, PBF, ...)
|
||||
#include <osmium/io/any_output.hpp>
|
||||
|
||||
// We want to use the builder interface
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/builder/attr.hpp>
|
||||
|
||||
// Declare this to use the functions starting with the underscore (_) below.
|
||||
using namespace osmium::builder::attr;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OUTFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Get output file name from command line.
|
||||
std::string output_file_name{argv[1]};
|
||||
|
||||
// If output file name is "-", this means STDOUT. Set the OPL file type
|
||||
// in this case. Otherwise take the file type from the file name suffix.
|
||||
osmium::io::File output_file{output_file_name, output_file_name == "-" ? ".opl" : ""};
|
||||
|
||||
try {
|
||||
// Create a buffer where all objects will live. Use a sensible initial
|
||||
// buffer size and set the buffer to automatically grow if needed.
|
||||
const size_t initial_buffer_size = 10000;
|
||||
osmium::memory::Buffer buffer{initial_buffer_size, osmium::memory::Buffer::auto_grow::yes};
|
||||
|
||||
// Add nodes to the buffer. This is, of course, only an example.
|
||||
// You can set any of the attributes and more tags, etc. Ways and
|
||||
// relations can be added in a similar way.
|
||||
osmium::builder::add_node(buffer,
|
||||
_id(-1),
|
||||
_version(1),
|
||||
_timestamp(std::time(nullptr)),
|
||||
_location(osmium::Location{1.23, 3.45}),
|
||||
_tag("amenity", "post_box")
|
||||
);
|
||||
|
||||
osmium::builder::add_node(buffer,
|
||||
_id(-2),
|
||||
_version(1),
|
||||
_timestamp(std::time(nullptr)),
|
||||
_location(1.24, 3.46),
|
||||
_tags({{"amenity", "restaurant"},
|
||||
{"name", "Chez OSM"}})
|
||||
);
|
||||
|
||||
// Create header and set generator.
|
||||
osmium::io::Header header;
|
||||
header.set("generator", "osmium_create_pois");
|
||||
|
||||
// Initialize Writer using the header from above and tell it that it
|
||||
// is allowed to overwrite a possibly existing file.
|
||||
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
|
||||
|
||||
// Write out the contents of the output buffer.
|
||||
writer(std::move(buffer));
|
||||
|
||||
// Explicitly close the writer. Will throw an exception if there is
|
||||
// a problem. If you wait for the destructor to close the writer, you
|
||||
// will not notice the problem, because destructors must not throw.
|
||||
writer.close();
|
||||
} catch (const std::exception& e) {
|
||||
// All exceptions used by the Osmium library derive from std::exception.
|
||||
std::cerr << e.what() << "\n";
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
84
third_party/libosmium/examples/osmium_debug.cpp
vendored
Normal file
84
third_party/libosmium/examples/osmium_debug.cpp
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_debug
|
||||
|
||||
Dump the contents of the input file in a debug format.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input reading only some types
|
||||
* the dump handler
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
|
||||
// The Dump handler
|
||||
#include <osmium/handler/dump.hpp>
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Speed up output (not Osmium-specific)
|
||||
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";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Default is all entity types: nodes, ways, relations, and changesets
|
||||
osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all;
|
||||
|
||||
// Get entity types from command line if there is a 2nd argument.
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize Reader with file name and the types of entities we want to
|
||||
// read.
|
||||
osmium::io::Reader reader{argv[1], read_types};
|
||||
|
||||
// The file header can contain metadata such as the program that generated
|
||||
// the file and the bounding box of the data.
|
||||
osmium::io::Header header = reader.header();
|
||||
std::cout << "HEADER:\n generator=" << header.get("generator") << "\n";
|
||||
|
||||
for (const auto& bbox : header.boxes()) {
|
||||
std::cout << " bbox=" << bbox << "\n";
|
||||
}
|
||||
|
||||
// Initialize Dump handler.
|
||||
osmium::handler::Dump dump{std::cout};
|
||||
|
||||
// Read from input and send everything to Dump handler.
|
||||
osmium::apply(reader, dump);
|
||||
|
||||
// You do not have to close the Reader explicitly, but because the
|
||||
// destructor can't throw, you will not see any errors otherwise.
|
||||
reader.close();
|
||||
}
|
||||
|
190
third_party/libosmium/examples/osmium_dump_internal.cpp
vendored
Normal file
190
third_party/libosmium/examples/osmium_dump_internal.cpp
vendored
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_dump_internal
|
||||
|
||||
Reads an OSM file and dumps the internal datastructure to disk including
|
||||
indexes to find objects and object relations.
|
||||
|
||||
Note that this example programm will only work with small and medium sized
|
||||
OSM files, not with the planet.
|
||||
|
||||
You can use the osmium_index example program to inspect the indexes.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* indexes and maps
|
||||
* use of the DiskStore handler
|
||||
* use of the ObjectRelations handler
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_road_length
|
||||
* osmium_location_cache_create
|
||||
* osmium_location_cache_use
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno> // for errno
|
||||
#include <cstring> // for std::strerror
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <direct.h>
|
||||
#endif
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// The DiskStore handler
|
||||
#include <osmium/handler/disk_store.hpp>
|
||||
|
||||
// The ObjectRelations handler
|
||||
#include <osmium/handler/object_relations.hpp>
|
||||
|
||||
// The indexes
|
||||
#include <osmium/index/map/sparse_mem_array.hpp>
|
||||
#include <osmium/index/multimap/sparse_mem_array.hpp>
|
||||
|
||||
using offset_index_type = osmium::index::map::SparseMemArray<osmium::unsigned_object_id_type, size_t>;
|
||||
using map_type = osmium::index::multimap::SparseMemArray<osmium::unsigned_object_id_type, osmium::unsigned_object_id_type>;
|
||||
|
||||
/**
|
||||
* Small class wrapping index files, basically making sure errors are handled
|
||||
* and the files are closed on destruction.
|
||||
*/
|
||||
class IndexFile {
|
||||
|
||||
int m_fd;
|
||||
|
||||
public:
|
||||
|
||||
explicit IndexFile(const std::string& filename) :
|
||||
m_fd(::open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666)) {
|
||||
if (m_fd < 0) {
|
||||
std::cerr << "Can't open index file '" << filename << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(m_fd, _O_BINARY);
|
||||
#endif
|
||||
}
|
||||
|
||||
~IndexFile() {
|
||||
if (m_fd >= 0) {
|
||||
close(m_fd);
|
||||
}
|
||||
}
|
||||
|
||||
int fd() const noexcept {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
}; // class IndexFile
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE DIR\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
const std::string input_file_name{argv[1]};
|
||||
const std::string output_dir{argv[2]};
|
||||
|
||||
// Create output directory. Ignore the error if it already exists.
|
||||
#ifndef _WIN32
|
||||
const int result = ::mkdir(output_dir.c_str(), 0777);
|
||||
#else
|
||||
const int result = mkdir(output_dir.c_str());
|
||||
#endif
|
||||
if (result == -1 && errno != EEXIST) {
|
||||
std::cerr << "Problem creating directory '" << output_dir << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
// Create the output file which will contain our serialized OSM data
|
||||
const std::string data_file{output_dir + "/data.osm.ser"};
|
||||
const 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 << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_setmode(data_fd, _O_BINARY);
|
||||
#endif
|
||||
|
||||
// These indexes store the offset in the data file where each node, way,
|
||||
// or relation is stored.
|
||||
offset_index_type node_index;
|
||||
offset_index_type way_index;
|
||||
offset_index_type relation_index;
|
||||
|
||||
// This handler will dump the internal data to disk using the given file
|
||||
// descriptor while updating the indexes.
|
||||
osmium::handler::DiskStore disk_store_handler{data_fd, node_index, way_index, relation_index};
|
||||
|
||||
// These indexes store the mapping from node id to the ids of the ways
|
||||
// containing this node, and from node/way/relation ids to the ids of the
|
||||
// relations containing those objects.
|
||||
map_type map_node2way;
|
||||
map_type map_node2relation;
|
||||
map_type map_way2relation;
|
||||
map_type map_relation2relation;
|
||||
|
||||
// This handler will update the map indexes.
|
||||
osmium::handler::ObjectRelations object_relations_handler{map_node2way, map_node2relation, map_way2relation, map_relation2relation};
|
||||
|
||||
// Read OSM data buffer by buffer.
|
||||
osmium::io::Reader reader{input_file_name};
|
||||
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
// Write buffer to disk and update indexes.
|
||||
disk_store_handler(buffer);
|
||||
|
||||
// Update object relation index maps.
|
||||
osmium::apply(buffer, object_relations_handler);
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
// Write out node, way, and relation offset indexes to disk.
|
||||
IndexFile nodes_idx{output_dir + "/nodes.idx"};
|
||||
node_index.dump_as_list(nodes_idx.fd());
|
||||
|
||||
IndexFile ways_idx{output_dir + "/ways.idx"};
|
||||
way_index.dump_as_list(ways_idx.fd());
|
||||
|
||||
IndexFile relations_idx{output_dir + "/relations.idx"};
|
||||
relation_index.dump_as_list(relations_idx.fd());
|
||||
|
||||
// Sort the maps (so later binary search will work on them) and write
|
||||
// them to disk.
|
||||
map_node2way.sort();
|
||||
IndexFile node2way_idx{output_dir + "/node2way.map"};
|
||||
map_node2way.dump_as_list(node2way_idx.fd());
|
||||
|
||||
map_node2relation.sort();
|
||||
IndexFile node2relation_idx{output_dir + "/node2rel.map"};
|
||||
map_node2relation.dump_as_list(node2relation_idx.fd());
|
||||
|
||||
map_way2relation.sort();
|
||||
IndexFile way2relation_idx{output_dir + "/way2rel.map"};
|
||||
map_way2relation.dump_as_list(way2relation_idx.fd());
|
||||
|
||||
map_relation2relation.sort();
|
||||
IndexFile relation2relation_idx{output_dir + "/rel2rel.map"};
|
||||
map_relation2relation.dump_as_list(relation2relation_idx.fd());
|
||||
}
|
||||
|
92
third_party/libosmium/examples/osmium_filter_discussions.cpp
vendored
Normal file
92
third_party/libosmium/examples/osmium_filter_discussions.cpp
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_filter_discussions
|
||||
|
||||
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).
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input and output
|
||||
* setting file formats using the osmium::io::File class
|
||||
* OSM file headers
|
||||
* input and output iterators
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm> // for std::copy_if
|
||||
#include <cstdlib> // for std::exit
|
||||
#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>
|
||||
|
||||
// We want to write OSM files in XML format.
|
||||
#include <osmium/io/xml_output.hpp>
|
||||
|
||||
// We want to use input and output iterators for easy integration with the
|
||||
// algorithms of the standard library.
|
||||
#include <osmium/io/input_iterator.hpp>
|
||||
#include <osmium/io/output_iterator.hpp>
|
||||
|
||||
// We want to support any compression (none, gzip, and bzip2).
|
||||
#include <osmium/io/any_compression.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cout << "Usage: " << argv[0] << " INFILE OUTFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The input file, deduce file format from file suffix.
|
||||
osmium::io::File input_file{argv[1]};
|
||||
|
||||
// The output file, force XML OSM file format.
|
||||
osmium::io::File output_file{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{input_file, osmium::osm_entity_bits::changeset};
|
||||
|
||||
// Get the header from the input file.
|
||||
osmium::io::Header header = reader.header();
|
||||
|
||||
// Set the "generator" on the header to ourselves.
|
||||
header.set("generator", "osmium_filter_discussions");
|
||||
|
||||
// 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{output_file, 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();
|
||||
}
|
||||
|
346
third_party/libosmium/examples/osmium_index_lookup.cpp
vendored
Normal file
346
third_party/libosmium/examples/osmium_index_lookup.cpp
vendored
Normal file
@ -0,0 +1,346 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_index
|
||||
|
||||
Example program to look at Osmium indexes on disk.
|
||||
|
||||
You can use the osmium_dump_internal example program to create the offset
|
||||
indexes or osmium_location_cache_create to create a node location index.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* access to indexes on disk
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_road_length
|
||||
* osmium_location_cache_create
|
||||
* osmium_location_cache_use
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <algorithm> // for std::all_of, std::equal_range
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <fcntl.h> // for open
|
||||
#include <getopt.h> // for getopt_long
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <memory> // for std::unique_ptr
|
||||
#include <string> // for std::string
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
#include <vector> // for std::vector
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Disk-based indexes
|
||||
#include <osmium/index/map/dense_file_array.hpp>
|
||||
#include <osmium/index/map/sparse_file_array.hpp>
|
||||
|
||||
// osmium::Location
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
// Basic Osmium types
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
// Virtual class for disk index access. If offers functions to dump the
|
||||
// indexes and to search for ids in the index.
|
||||
template <typename TValue>
|
||||
class IndexAccess {
|
||||
|
||||
int m_fd;
|
||||
|
||||
public:
|
||||
|
||||
explicit IndexAccess(int fd) :
|
||||
m_fd(fd) {
|
||||
}
|
||||
|
||||
int fd() const noexcept {
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
virtual ~IndexAccess() = default;
|
||||
|
||||
virtual void dump() const = 0;
|
||||
|
||||
virtual bool search(const osmium::unsigned_object_id_type& key) const = 0;
|
||||
|
||||
bool search(const std::vector<osmium::unsigned_object_id_type>& keys) const {
|
||||
return std::all_of(keys.cbegin(), keys.cend(), [this](const osmium::unsigned_object_id_type& key) {
|
||||
return search(key);
|
||||
});
|
||||
}
|
||||
|
||||
}; // class IndexAccess
|
||||
|
||||
// Implementation of IndexAccess for dense indexes usually used for very large
|
||||
// extracts or the planet.
|
||||
template <typename TValue>
|
||||
class IndexAccessDense : public IndexAccess<TValue> {
|
||||
|
||||
using index_type = typename osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, TValue>;
|
||||
|
||||
public:
|
||||
|
||||
explicit IndexAccessDense(int fd) :
|
||||
IndexAccess<TValue>(fd) {
|
||||
}
|
||||
|
||||
void dump() const override {
|
||||
index_type index{this->fd()};
|
||||
|
||||
for (std::size_t i = 0; i < index.size(); ++i) {
|
||||
if (index.get(i) != TValue{}) {
|
||||
std::cout << i << " " << index.get(i) << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool search(const osmium::unsigned_object_id_type& key) const override {
|
||||
index_type index{this->fd()};
|
||||
|
||||
try {
|
||||
TValue value = index.get(key);
|
||||
std::cout << key << " " << value << "\n";
|
||||
} catch (...) {
|
||||
std::cout << key << " not found\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class IndexAccessDense
|
||||
|
||||
// Implementation of IndexAccess for sparse indexes usually used for small or
|
||||
// medium sized extracts or for "multimap" type indexes.
|
||||
template <typename TValue>
|
||||
class IndexAccessSparse : public IndexAccess<TValue> {
|
||||
|
||||
using index_type = typename osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, TValue>;
|
||||
|
||||
public:
|
||||
|
||||
explicit IndexAccessSparse(int fd) :
|
||||
IndexAccess<TValue>(fd) {
|
||||
}
|
||||
|
||||
void dump() const override {
|
||||
index_type index{this->fd()};
|
||||
|
||||
for (const auto& element : index) {
|
||||
std::cout << element.first << " " << element.second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
bool search(const osmium::unsigned_object_id_type& key) const override {
|
||||
using element_type = typename index_type::element_type;
|
||||
index_type index{this->fd()};
|
||||
|
||||
element_type elem{key, TValue{}};
|
||||
const 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\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto it = positions.first; it != positions.second; ++it) {
|
||||
std::cout << it->first << " " << it->second << "\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class IndexAccessSparse
|
||||
|
||||
// This class contains the code to parse the command line arguments, check
|
||||
// them and present the results to the rest of the program in an easy-to-use
|
||||
// way.
|
||||
class Options {
|
||||
|
||||
std::vector<osmium::unsigned_object_id_type> m_ids;
|
||||
std::string m_type;
|
||||
std::string m_filename;
|
||||
bool m_dump = false;
|
||||
bool m_array_format = false;
|
||||
bool m_list_format = false;
|
||||
|
||||
void print_help() {
|
||||
std::cout << "Usage: osmium_index_lookup [OPTIONS]\n\n"
|
||||
<< "-h, --help Print this help message\n"
|
||||
<< "-a, --array=FILE Read given index file in array format\n"
|
||||
<< "-l, --list=FILE Read given index file in list format\n"
|
||||
<< "-d, --dump Dump contents of index file to STDOUT\n"
|
||||
<< "-s, --search=ID Search for given id (Option can appear multiple times)\n"
|
||||
<< "-t, --type=TYPE Type of value ('location', 'id', or 'offset')\n"
|
||||
;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Options(int argc, char* argv[]) {
|
||||
if (argc == 1) {
|
||||
print_help();
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"array", required_argument, nullptr, 'a'},
|
||||
{"dump", no_argument, nullptr, 'd'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"list", required_argument, nullptr, 'l'},
|
||||
{"search", required_argument, nullptr, 's'},
|
||||
{"type", required_argument, nullptr, 't'},
|
||||
{nullptr, 0, nullptr, 0}
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const int c = getopt_long(argc, argv, "a:dhl:s:t:", long_options, nullptr);
|
||||
if (c == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'a':
|
||||
m_array_format = true;
|
||||
m_filename = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
m_dump = true;
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
std::exit(0);
|
||||
case 'l':
|
||||
m_list_format = true;
|
||||
m_filename = optarg;
|
||||
break;
|
||||
case 's':
|
||||
m_ids.push_back(std::atoll(optarg));
|
||||
break;
|
||||
case 't':
|
||||
m_type = optarg;
|
||||
if (m_type != "location" && m_type != "id" && m_type != "offset") {
|
||||
std::cerr << "Unknown type '" << m_type
|
||||
<< "'. Must be 'location', 'id', or 'offset'.\n";
|
||||
std::exit(2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
std::exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_array_format == m_list_format) {
|
||||
std::cerr << "Need option --array or --list, but not both\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
if (m_dump == !m_ids.empty()) {
|
||||
std::cerr << "Need option --dump or --search, but not both\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
if (m_type.empty()) {
|
||||
std::cerr << "Need --type argument.\n";
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char* filename() const noexcept {
|
||||
return m_filename.c_str();
|
||||
}
|
||||
|
||||
bool dense_format() const noexcept {
|
||||
return m_array_format;
|
||||
}
|
||||
|
||||
bool do_dump() const noexcept {
|
||||
return m_dump;
|
||||
}
|
||||
|
||||
const std::vector<osmium::unsigned_object_id_type>& search_keys() const noexcept {
|
||||
return m_ids;
|
||||
}
|
||||
|
||||
bool type_is(const char* type) const noexcept {
|
||||
return m_type == type;
|
||||
}
|
||||
|
||||
}; // class Options
|
||||
|
||||
|
||||
// Factory function to create the right IndexAccess-derived class.
|
||||
template <typename TValue>
|
||||
std::unique_ptr<IndexAccess<TValue>> create(bool dense, int fd) {
|
||||
std::unique_ptr<IndexAccess<TValue>> ptr;
|
||||
|
||||
if (dense) {
|
||||
ptr.reset(new IndexAccessDense<TValue>{fd});
|
||||
} else {
|
||||
ptr.reset(new IndexAccessSparse<TValue>{fd});
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// Do the actual work: Either dump the index or search in the index.
|
||||
template <typename TValue>
|
||||
int run(const IndexAccess<TValue>& index, const Options& options) {
|
||||
if (options.do_dump()) {
|
||||
index.dump();
|
||||
return 0;
|
||||
} else {
|
||||
return index.search(options.search_keys()) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Parse command line options.
|
||||
Options options{argc, argv};
|
||||
|
||||
// Open the index file.
|
||||
const int fd = ::open(options.filename(), O_RDWR);
|
||||
if (fd < 0) {
|
||||
std::cerr << "Can not open file '" << options.filename()
|
||||
<< "': " << std::strerror(errno) << '\n';
|
||||
std::exit(2);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
|
||||
try {
|
||||
// Depending on the type of index, we have different implementations.
|
||||
if (options.type_is("location")) {
|
||||
// index id -> location
|
||||
const auto index = create<osmium::Location>(options.dense_format(), fd);
|
||||
return run(*index, options);
|
||||
} else if (options.type_is("id")) {
|
||||
// index id -> id
|
||||
const auto index = create<osmium::unsigned_object_id_type>(options.dense_format(), fd);
|
||||
return run(*index, options);
|
||||
} else {
|
||||
// index id -> offset
|
||||
const auto index = create<std::size_t>(options.dense_format(), fd);
|
||||
return run(*index, options);
|
||||
}
|
||||
} catch(const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << '\n';
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
94
third_party/libosmium/examples/osmium_location_cache_create.cpp
vendored
Normal file
94
third_party/libosmium/examples/osmium_location_cache_create.cpp
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_location_cache_create
|
||||
|
||||
Reads nodes from an OSM file and writes out their locations to a cache
|
||||
file. The cache file can then be read with osmium_location_cache_use.
|
||||
|
||||
Warning: The locations cache file will get huge (>32GB) if you are using
|
||||
the DenseFileArray index even if the input file is small, because
|
||||
it depends on the *largest* node ID, not the number of nodes.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* location indexes on disk
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_road_length
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno> // for errno
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <cstring> // for strerror
|
||||
#include <fcntl.h> // for open
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// For the location index. There are different types of index implementation
|
||||
// available. These implementations put the index on disk. See below.
|
||||
#include <osmium/index/map/sparse_file_array.hpp>
|
||||
#include <osmium/index/map/dense_file_array.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// Chose one of these two. "sparse" is best used for small and medium extracts,
|
||||
// the "dense" index for large extracts or the whole planet.
|
||||
using index_type = osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
//using index_type = osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const std::string input_filename{argv[1]};
|
||||
const std::string cache_filename{argv[2]};
|
||||
|
||||
// Construct Reader reading only nodes
|
||||
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::node};
|
||||
|
||||
// Initialize location index on disk creating a new file.
|
||||
const int fd = ::open(cache_filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
|
||||
std::exit(1);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
index_type index{fd};
|
||||
|
||||
// The handler that stores all node locations in the index.
|
||||
location_handler_type location_handler{index};
|
||||
|
||||
// Feed all nodes through the location handler.
|
||||
osmium::apply(reader, location_handler);
|
||||
|
||||
// Explicitly close input so we get notified of any errors.
|
||||
reader.close();
|
||||
}
|
||||
|
108
third_party/libosmium/examples/osmium_location_cache_use.cpp
vendored
Normal file
108
third_party/libosmium/examples/osmium_location_cache_use.cpp
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_location_cache_use
|
||||
|
||||
This reads ways from an OSM file and writes out the way node locations
|
||||
it got from a location cache generated with osmium_location_cache_create.
|
||||
|
||||
Warning: The locations cache file will get huge (>32GB) if you are using
|
||||
the DenseFileArray index even if the input file is small, because
|
||||
it depends on the *largest* node ID, not the number of nodes.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* location indexes on disk
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_road_length
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cerrno> // for errno
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <cstring> // for strerror
|
||||
#include <fcntl.h> // for open
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
#include <string> // for std::string
|
||||
#include <sys/stat.h> // for open
|
||||
#include <sys/types.h> // for open
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <io.h> // for _setmode
|
||||
#endif
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// For the location index. There are different types of index implementation
|
||||
// available. These implementations put the index on disk. See below.
|
||||
#include <osmium/index/map/dense_file_array.hpp>
|
||||
#include <osmium/index/map/sparse_file_array.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// Chose one of these two. "sparse" is best used for small and medium extracts,
|
||||
// the "dense" index for large extracts or the whole planet.
|
||||
using index_type = osmium::index::map::SparseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
//using index_type = osmium::index::map::DenseFileArray<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
// This handler only implements the way() function which prints out the way
|
||||
// ID and all nodes IDs and locations in those ways.
|
||||
struct MyHandler : public osmium::handler::Handler {
|
||||
|
||||
void way(const osmium::Way& way) {
|
||||
std::cout << "way " << way.id() << "\n";
|
||||
for (const auto& nr : way.nodes()) {
|
||||
std::cout << " node " << nr.ref() << " " << nr.location() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}; // struct MyHandler
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 3) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSM_FILE CACHE_FILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const std::string input_filename{argv[1]};
|
||||
const std::string cache_filename{argv[2]};
|
||||
|
||||
// Construct Reader reading only ways
|
||||
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::way};
|
||||
|
||||
// Initialize location index on disk using an existing file
|
||||
const int fd = ::open(cache_filename.c_str(), O_RDWR);
|
||||
if (fd == -1) {
|
||||
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
|
||||
return 1;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_setmode(fd, _O_BINARY);
|
||||
#endif
|
||||
index_type index{fd};
|
||||
|
||||
// The handler that adds node locations from the index to the ways.
|
||||
location_handler_type location_handler{index};
|
||||
|
||||
// Feed all ways through the location handler and then our own handler.
|
||||
MyHandler handler;
|
||||
osmium::apply(reader, location_handler, handler);
|
||||
|
||||
// Explicitly close input so we get notified of any errors.
|
||||
reader.close();
|
||||
}
|
||||
|
89
third_party/libosmium/examples/osmium_pub_names.cpp
vendored
Normal file
89
third_party/libosmium/examples/osmium_pub_names.cpp
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_pub_names
|
||||
|
||||
Show the names and addresses of all pubs found in an OSM file.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* your own handler
|
||||
* access to tags
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <cstring> // for std::strncmp
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// We want to use the handler interface
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
class NamesHandler : public osmium::handler::Handler {
|
||||
|
||||
void output_pubs(const osmium::OSMObject& object) {
|
||||
const osmium::TagList& tags = object.tags();
|
||||
if (tags.has_tag("amenity", "pub")) {
|
||||
|
||||
// Print name of the pub if it is set.
|
||||
const char* name = tags["name"];
|
||||
if (name) {
|
||||
std::cout << name << "\n";
|
||||
} else {
|
||||
std::cout << "pub with unknown name\n";
|
||||
}
|
||||
|
||||
// Iterate over all tags finding those which start with "addr:"
|
||||
// and print them.
|
||||
for (const osmium::Tag& tag : tags) {
|
||||
if (!std::strncmp(tag.key(), "addr:", 5)) {
|
||||
std::cout << " " << tag.key() << ": " << tag.value() << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Nodes can be tagged amenity=pub.
|
||||
void node(const osmium::Node& node) {
|
||||
output_pubs(node);
|
||||
}
|
||||
|
||||
// Ways can be tagged amenity=pub, too (typically buildings).
|
||||
void way(const osmium::Way& way) {
|
||||
output_pubs(way);
|
||||
}
|
||||
|
||||
}; // class NamesHandler
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Construct the handler defined above
|
||||
NamesHandler names_handler;
|
||||
|
||||
// Initialize the reader with the filename from the command line and
|
||||
// tell it to only read nodes and ways. We are ignoring multipolygon
|
||||
// relations in this simple example.
|
||||
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way};
|
||||
|
||||
// Apply input data to our own handler
|
||||
osmium::apply(reader, names_handler);
|
||||
}
|
||||
|
42
third_party/libosmium/examples/osmium_read.cpp
vendored
Normal file
42
third_party/libosmium/examples/osmium_read.cpp
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_read
|
||||
|
||||
Reads and discards the contents of the input file.
|
||||
(It can be used for timing.)
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cerr
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// OSM data comes in buffers, read until there are no more.
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// You do not have to close the Reader explicitly, but because the
|
||||
// destructor can't throw, you will not see any errors otherwise.
|
||||
reader.close();
|
||||
}
|
||||
|
56
third_party/libosmium/examples/osmium_read_with_progress.cpp
vendored
Normal file
56
third_party/libosmium/examples/osmium_read_with_progress.cpp
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_read_with_progress
|
||||
|
||||
Reads the contents of the input file showing a progress bar.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* ProgressBar utility function
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cerr
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// Get access to isatty utility function and progress bar utility class.
|
||||
#include <osmium/util/file.hpp>
|
||||
#include <osmium/util/progress_bar.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// The Reader is initialized here with an osmium::io::File, but could
|
||||
// also be directly initialized with a file name.
|
||||
osmium::io::File input_file{argv[1]};
|
||||
osmium::io::Reader reader{input_file};
|
||||
|
||||
// Initialize progress bar, enable it only if STDERR is a TTY.
|
||||
osmium::ProgressBar progress{reader.file_size(), osmium::util::isatty(2)};
|
||||
|
||||
// OSM data comes in buffers, read until there are no more.
|
||||
while (osmium::memory::Buffer buffer = reader.read()) {
|
||||
// Update progress bar for each buffer.
|
||||
progress.update(reader.offset());
|
||||
}
|
||||
|
||||
// Progress bar is done.
|
||||
progress.done();
|
||||
|
||||
// You do not have to close the Reader explicitly, but because the
|
||||
// destructor can't throw, you will not see any errors otherwise.
|
||||
reader.close();
|
||||
}
|
||||
|
92
third_party/libosmium/examples/osmium_road_length.cpp
vendored
Normal file
92
third_party/libosmium/examples/osmium_road_length.cpp
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_road_length
|
||||
|
||||
Calculate the length of the road network (everything tagged `highway=*`)
|
||||
from the given OSM file.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* file input
|
||||
* location indexes and the NodeLocationsForWays handler
|
||||
* length calculation on the earth using the haversine function
|
||||
|
||||
SIMPLER EXAMPLES you might want to understand first:
|
||||
* osmium_read
|
||||
* osmium_count
|
||||
* osmium_pub_names
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
|
||||
// Allow any format of input files (XML, PBF, ...)
|
||||
#include <osmium/io/any_input.hpp>
|
||||
|
||||
// For the osmium::geom::haversine::distance() function
|
||||
#include <osmium/geom/haversine.hpp>
|
||||
|
||||
// For osmium::apply()
|
||||
#include <osmium/visitor.hpp>
|
||||
|
||||
// For the location index. There are different types of indexes available.
|
||||
// This will work for all input files keeping the index in memory.
|
||||
#include <osmium/index/map/flex_mem.hpp>
|
||||
|
||||
// For the NodeLocationForWays handler
|
||||
#include <osmium/handler/node_locations_for_ways.hpp>
|
||||
|
||||
// The type of index used. This must match the include file above
|
||||
using index_type = osmium::index::map::FlexMem<osmium::unsigned_object_id_type, osmium::Location>;
|
||||
|
||||
// The location handler always depends on the index type
|
||||
using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
|
||||
|
||||
// This handler only implements the way() function, we are not interested in
|
||||
// any other objects.
|
||||
struct RoadLengthHandler : public osmium::handler::Handler {
|
||||
|
||||
double length = 0;
|
||||
|
||||
// If the way has a "highway" tag, find its length and add it to the
|
||||
// overall length.
|
||||
void way(const osmium::Way& way) {
|
||||
const char* highway = way.tags()["highway"];
|
||||
if (highway) {
|
||||
length += osmium::geom::haversine::distance(way.nodes());
|
||||
}
|
||||
}
|
||||
|
||||
}; // struct RoadLengthHandler
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " OSMFILE\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Initialize the reader with the filename from the command line and
|
||||
// tell it to only read nodes and ways.
|
||||
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way};
|
||||
|
||||
// The index to hold node locations.
|
||||
index_type index;
|
||||
|
||||
// The location handler will add the node locations to the index and then
|
||||
// to the ways
|
||||
location_handler_type location_handler{index};
|
||||
|
||||
// Our handler defined above
|
||||
RoadLengthHandler road_length_handler;
|
||||
|
||||
// Apply input data to first the location handler and then our own handler
|
||||
osmium::apply(reader, location_handler, road_length_handler);
|
||||
|
||||
// Output the length. The haversine function calculates it in meters,
|
||||
// so we first devide by 1000 to get kilometers.
|
||||
std::cout << "Length: " << road_length_handler.length / 1000 << " km\n";
|
||||
}
|
||||
|
72
third_party/libosmium/examples/osmium_tiles.cpp
vendored
Normal file
72
third_party/libosmium/examples/osmium_tiles.cpp
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
EXAMPLE osmium_tiles
|
||||
|
||||
Convert WGS84 longitude and latitude to Mercator coordinates and tile
|
||||
coordinates.
|
||||
|
||||
DEMONSTRATES USE OF:
|
||||
* the Location and Coordinates classes
|
||||
* the Mercator projection function
|
||||
* the Tile class
|
||||
|
||||
LICENSE
|
||||
The code in this example file is released into the Public Domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <cstdlib> // for std::exit, std::atoi, std::atof
|
||||
#include <iostream> // for std::cout, std::cerr
|
||||
|
||||
// The Location contains a longitude and latitude and is usually used inside
|
||||
// a node to store its location in the world.
|
||||
#include <osmium/osm/location.hpp>
|
||||
|
||||
// Needed for the Mercator projection function. Osmium supports the Mercator
|
||||
// projection out of the box, or pretty much any projection using the Proj.4
|
||||
// library (with the osmium::geom::Projection class).
|
||||
#include <osmium/geom/mercator_projection.hpp>
|
||||
|
||||
// The Tile class handles tile coordinates and zoom levels.
|
||||
#include <osmium/geom/tile.hpp>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " ZOOM LON LAT\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const int zoom = std::atoi(argv[1]);
|
||||
|
||||
if (zoom < 0 || zoom > 30) {
|
||||
std::cerr << "ERROR: Zoom must be between 0 and 30\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
const double lon = std::atof(argv[2]);
|
||||
const double lat = std::atof(argv[3]);
|
||||
|
||||
// Create location from WGS84 coordinates. In Osmium the order of
|
||||
// coordinate values is always x/longitude first, then y/latitude.
|
||||
const osmium::Location location{lon, lat};
|
||||
|
||||
std::cout << "WGS84: lon=" << lon << " lat=" << lat << "\n";
|
||||
|
||||
// A location can store some invalid locations, ie locations outside the
|
||||
// -180 to 180 and -90 to 90 degree range. This function checks for that.
|
||||
if (!location.valid()) {
|
||||
std::cerr << "ERROR: Location is invalid\n";
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
// Project the coordinates using a helper function. You can also use the
|
||||
// osmium::geom::MercatorProjection class.
|
||||
const osmium::geom::Coordinates c = osmium::geom::lonlat_to_mercator(location);
|
||||
std::cout << "Mercator: x=" << c.x << " y=" << c.y << "\n";
|
||||
|
||||
// Create a tile at this location. This will also internally use the
|
||||
// Mercator projection and then calculate the tile coordinates.
|
||||
const osmium::geom::Tile tile{uint32_t(zoom), location};
|
||||
std::cout << "Tile: zoom=" << tile.z << " x=" << tile.x << " y=" << tile.y << "\n";
|
||||
}
|
||||
|
477
third_party/libosmium/include/gdalcpp.hpp
vendored
Normal file
477
third_party/libosmium/include/gdalcpp.hpp
vendored
Normal file
@ -0,0 +1,477 @@
|
||||
#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 {
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
init_wrapper() { GDALAllRegister(); }
|
||||
#else
|
||||
init_wrapper() { OGRRegisterAll(); }
|
||||
~init_wrapper() { OGRCleanupAll(); }
|
||||
#endif
|
||||
};
|
||||
|
||||
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;
|
||||
uint64_t m_edit_count = 0;
|
||||
uint64_t m_max_edit_count = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
~Dataset() {
|
||||
try {
|
||||
if (m_edit_count > 0) {
|
||||
commit_transaction();
|
||||
}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
#else
|
||||
OGRLayer* layer = m_dataset->GetLayer(0);
|
||||
if (layer) {
|
||||
layer->StartTransaction();
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
Dataset& commit_transaction() {
|
||||
#if GDAL_VERSION_MAJOR >= 2
|
||||
m_dataset->CommitTransaction();
|
||||
#else
|
||||
OGRLayer* layer = m_dataset->GetLayer(0);
|
||||
if (layer) {
|
||||
layer->CommitTransaction();
|
||||
}
|
||||
#endif
|
||||
m_edit_count = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void prepare_edit() {
|
||||
if (m_max_edit_count != 0 && m_edit_count == 0) {
|
||||
start_transaction();
|
||||
}
|
||||
}
|
||||
|
||||
void finalize_edit() {
|
||||
if (m_max_edit_count != 0 && ++m_edit_count > m_max_edit_count) {
|
||||
commit_transaction();
|
||||
}
|
||||
}
|
||||
|
||||
Dataset& enable_auto_transactions(uint64_t edits = 100000) {
|
||||
m_max_edit_count = edits;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Dataset& disable_auto_transactions() {
|
||||
if (m_max_edit_count != 0 && m_edit_count > 0) {
|
||||
commit_transaction();
|
||||
}
|
||||
m_max_edit_count = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
void create_feature(OGRFeature* feature) {
|
||||
dataset().prepare_edit();
|
||||
OGRErr result = m_layer->CreateFeature(feature);
|
||||
if (result != OGRERR_NONE) {
|
||||
throw gdal_error(std::string("creating feature in layer '") + name() + "' failed", result, dataset().driver_name(), dataset().dataset_name());
|
||||
}
|
||||
dataset().finalize_edit();
|
||||
}
|
||||
|
||||
Layer& start_transaction() {
|
||||
#if GDAL_VERSION_MAJOR < 2
|
||||
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());
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
Layer& commit_transaction() {
|
||||
#if GDAL_VERSION_MAJOR < 2
|
||||
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());
|
||||
}
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
}; // class Layer
|
||||
|
||||
class Feature {
|
||||
|
||||
struct ogr_feature_deleter {
|
||||
|
||||
void operator()(OGRFeature* feature) {
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
|
||||
}; // struct ogr_feature_deleter
|
||||
|
||||
Layer& m_layer;
|
||||
std::unique_ptr<OGRFeature, ogr_feature_deleter> m_feature;
|
||||
|
||||
public:
|
||||
|
||||
Feature(Layer& layer, std::unique_ptr<OGRGeometry>&& geometry) :
|
||||
m_layer(layer),
|
||||
m_feature(OGRFeature::CreateFeature(m_layer.get().GetLayerDefn())) {
|
||||
if (!m_feature) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
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() {
|
||||
m_layer.create_feature(m_feature.get());
|
||||
}
|
||||
|
||||
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
|
234
third_party/libosmium/include/osmium/area/assembler.hpp
vendored
Normal file
234
third_party/libosmium/include/osmium/area/assembler.hpp
vendored
Normal file
@ -0,0 +1,234 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler_with_tags.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Assembles area objects from closed ways or multipolygon relations
|
||||
* and their members.
|
||||
*/
|
||||
class Assembler : public detail::BasicAssemblerWithTags {
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Way& way) {
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(way);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
builder.add_item(way.tags());
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
config().problem_reporter->report_way(way);
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
||||
set_num_members(members.size());
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(relation);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
if (config().keep_type_tag) {
|
||||
builder.add_item(relation.tags());
|
||||
} else {
|
||||
copy_tags_without_type(builder, relation.tags());
|
||||
}
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
for (const osmium::Way* way : members) {
|
||||
config().problem_reporter->report_way(*way);
|
||||
}
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit Assembler(const config_type& config) :
|
||||
detail::BasicAssemblerWithTags(config) {
|
||||
}
|
||||
|
||||
~Assembler() noexcept = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
if (!config().create_way_polygons) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::way, way.id());
|
||||
config().problem_reporter->set_nodes(way.nodes().size());
|
||||
}
|
||||
|
||||
// Ignore (but count) ways without segments.
|
||||
if (way.nodes().size() < 2) {
|
||||
++stats().short_ways;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!way.ends_have_same_id()) {
|
||||
++stats().duplicate_nodes;
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
|
||||
}
|
||||
}
|
||||
|
||||
++stats().from_ways;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_way(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
way);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling way " << way.id() << " containing " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the way.
|
||||
const bool okay = create_area(out_buffer, way);
|
||||
if (okay) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "Done: " << stats() << "\n";
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its members.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area(s), true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Relation& relation, const std::vector<const osmium::Way*>& members, osmium::memory::Buffer& out_buffer) {
|
||||
if (!config().create_new_style_polygons) {
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(relation.cmembers().size() >= members.size());
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::relation, relation.id());
|
||||
}
|
||||
|
||||
if (relation.members().empty()) {
|
||||
++stats().no_way_in_mp_relation;
|
||||
return false;
|
||||
}
|
||||
|
||||
++stats().from_relations;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_ways(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
stats().duplicate_ways,
|
||||
relation,
|
||||
members);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
stats().member_ways = members.size();
|
||||
|
||||
if (stats().member_ways == 1) {
|
||||
++stats().single_way_in_mp_relation;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling relation " << relation.id() << " containing " << members.size() << " way members with " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
bool okay = create_area(out_buffer, relation, members);
|
||||
if (okay) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
}; // class Assembler
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_HPP
|
154
third_party/libosmium/include/osmium/area/assembler_config.hpp
vendored
Normal file
154
third_party/libosmium/include/osmium/area/assembler_config.hpp
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
class ProblemReporter;
|
||||
|
||||
/**
|
||||
* Configuration for osmium::area::Assembler objects. Create this
|
||||
* once, set the options you want and then re-use it every time you
|
||||
* create an Assembler object.
|
||||
*/
|
||||
struct AssemblerConfig {
|
||||
|
||||
/**
|
||||
* Optional pointer to problem reporter.
|
||||
*/
|
||||
ProblemReporter* problem_reporter = nullptr;
|
||||
|
||||
/**
|
||||
* Debug level. If this is greater than zero, debug messages will
|
||||
* be printed to stderr. Available levels are 1 to 3. Note that
|
||||
* level 2 and above will generate a lot of messages!
|
||||
*/
|
||||
int debug_level = 0;
|
||||
|
||||
/**
|
||||
* The roles of multipolygon members are ignored when assembling
|
||||
* multipolygons, because they are often missing or wrong. If this
|
||||
* is set, the roles are checked after the multipolygons are built
|
||||
* against what the assembly process decided where the inner and
|
||||
* outer rings are. This slows down the processing, so it only
|
||||
* makes sense if you want to get the problem reports.
|
||||
*/
|
||||
bool check_roles = false;
|
||||
|
||||
/**
|
||||
* When the assembler can't create an area, usually because its
|
||||
* geometry would be invalid, it will create an "empty" area object
|
||||
* without rings. This allows you to detect where an area was
|
||||
* invalid.
|
||||
*
|
||||
* If this is set to false, invalid areas will simply be discarded.
|
||||
*/
|
||||
bool create_empty_areas = true;
|
||||
|
||||
/**
|
||||
* Create areas for (multi)polygons where the tags are on the
|
||||
* relation.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_new_style_polygons = true;
|
||||
|
||||
/**
|
||||
* Create areas for (multi)polygons where the tags are on the
|
||||
* outer way(s). This is ignored by the area::Assembler which
|
||||
* doesn't support old-style multipolygons any more. Use the
|
||||
* area::AssemblerLegacy if you need this.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_old_style_polygons = true;
|
||||
|
||||
/**
|
||||
* Create areas for polygons created from ways.
|
||||
*
|
||||
* If this is set to false, those areas will simply be discarded.
|
||||
*/
|
||||
bool create_way_polygons = true;
|
||||
|
||||
/**
|
||||
* Keep the type tag from multipolygon relations on the area
|
||||
* object. By default this is false, and the type tag will be
|
||||
* removed.
|
||||
*/
|
||||
bool keep_type_tag = false;
|
||||
|
||||
/**
|
||||
* If there is an invalid location in any of the ways needed for
|
||||
* assembling the multipolygon, the assembler will normally fail.
|
||||
* If this is set, the assembler will silently ignore the invalid
|
||||
* locations pretending them to be not referenced from the ways.
|
||||
* This will allow some areas to be built, others will now be
|
||||
* incorrect. This can sometimes be useful to assemble areas
|
||||
* crossing the boundary of an extract, but you will also get
|
||||
* geometrically valid but wrong (multi)polygons.
|
||||
*/
|
||||
bool ignore_invalid_locations = false;
|
||||
|
||||
AssemblerConfig() noexcept = default;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @deprecated Use default constructor and set values afterwards.
|
||||
*/
|
||||
explicit AssemblerConfig(ProblemReporter* pr, bool d = false) :
|
||||
problem_reporter(pr),
|
||||
debug_level(d) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable debug output to stderr. This is for Osmium
|
||||
* developers only.
|
||||
*
|
||||
* @deprecated Set debug_level directly.
|
||||
*/
|
||||
OSMIUM_DEPRECATED void enable_debug_output(bool d = true) {
|
||||
debug_level = d;
|
||||
}
|
||||
|
||||
}; // struct AssemblerConfig
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_CONFIG_HPP
|
382
third_party/libosmium/include/osmium/area/assembler_legacy.hpp
vendored
Normal file
382
third_party/libosmium/include/osmium/area/assembler_legacy.hpp
vendored
Normal file
@ -0,0 +1,382 @@
|
||||
#ifndef OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
||||
#define OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler_with_tags.hpp>
|
||||
#include <osmium/area/detail/proto_ring.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/problem_reporter.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/collection.hpp>
|
||||
#include <osmium/osm/area.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/tags/filter.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Assembles area objects from closed ways or multipolygon relations
|
||||
* and their members.
|
||||
*/
|
||||
class AssemblerLegacy : public detail::BasicAssemblerWithTags {
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
|
||||
builder.add_item(way.tags());
|
||||
}
|
||||
|
||||
void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
|
||||
std::map<std::string, std::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];
|
||||
}
|
||||
}
|
||||
|
||||
const std::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) {
|
||||
const std::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 const MPFilter& filter() noexcept {
|
||||
static const MPFilter filter;
|
||||
return filter;
|
||||
}
|
||||
|
||||
void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) {
|
||||
const auto count = std::count_if(relation.tags().cbegin(), relation.tags().cend(), std::cref(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";
|
||||
}
|
||||
|
||||
if (config().keep_type_tag) {
|
||||
builder.add_item(relation.tags());
|
||||
} else {
|
||||
copy_tags_without_type(builder, relation.tags());
|
||||
}
|
||||
} else {
|
||||
++stats().no_tags_on_relation;
|
||||
if (debug()) {
|
||||
std::cerr << " use tags from outer ways\n";
|
||||
}
|
||||
std::set<const osmium::Way*> ways;
|
||||
for (const auto& ring : rings()) {
|
||||
if (ring.is_outer()) {
|
||||
ring.get_ways(ways);
|
||||
}
|
||||
}
|
||||
if (ways.size() == 1) {
|
||||
if (debug()) {
|
||||
std::cerr << " only one outer way\n";
|
||||
}
|
||||
builder.add_item((*ways.cbegin())->tags());
|
||||
} else {
|
||||
if (debug()) {
|
||||
std::cerr << " multiple outer ways, get common tags\n";
|
||||
}
|
||||
osmium::builder::TagListBuilder tl_builder{builder};
|
||||
add_common_tags(tl_builder, ways);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Way& way) {
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(way);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
add_tags_to_area(builder, way);
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
config().problem_reporter->report_way(way);
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
bool create_area(osmium::memory::Buffer& out_buffer, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
|
||||
set_num_members(members.size());
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(relation);
|
||||
|
||||
const bool area_okay = create_rings();
|
||||
if (area_okay || config().create_empty_areas) {
|
||||
add_tags_to_area(builder, relation);
|
||||
}
|
||||
if (area_okay) {
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
|
||||
if (report_ways()) {
|
||||
for (const osmium::Way* way : members) {
|
||||
config().problem_reporter->report_way(*way);
|
||||
}
|
||||
}
|
||||
|
||||
return area_okay || config().create_empty_areas;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit AssemblerLegacy(const config_type& config) :
|
||||
detail::BasicAssemblerWithTags(config) {
|
||||
}
|
||||
|
||||
~AssemblerLegacy() noexcept = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
if (!config().create_way_polygons) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (way.tags().has_tag("area", "no")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::way, way.id());
|
||||
config().problem_reporter->set_nodes(way.nodes().size());
|
||||
}
|
||||
|
||||
// Ignore (but count) ways without segments.
|
||||
if (way.nodes().size() < 2) {
|
||||
++stats().short_ways;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!way.ends_have_same_id()) {
|
||||
++stats().duplicate_nodes;
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
|
||||
}
|
||||
}
|
||||
|
||||
++stats().from_ways;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_way(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
way);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling way " << way.id() << " containing " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the way.
|
||||
const bool okay = create_area(out_buffer, way);
|
||||
if (okay) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "Done: " << stats() << "\n";
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its members.
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area(s), true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Relation& relation, const std::vector<const osmium::Way*>& members, osmium::memory::Buffer& out_buffer) {
|
||||
assert(relation.members().size() >= members.size());
|
||||
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->set_object(osmium::item_type::relation, relation.id());
|
||||
}
|
||||
|
||||
if (relation.members().empty()) {
|
||||
++stats().no_way_in_mp_relation;
|
||||
return false;
|
||||
}
|
||||
|
||||
++stats().from_relations;
|
||||
stats().invalid_locations = segment_list().extract_segments_from_ways(config().problem_reporter,
|
||||
stats().duplicate_nodes,
|
||||
stats().duplicate_ways,
|
||||
relation,
|
||||
members);
|
||||
if (!config().ignore_invalid_locations && stats().invalid_locations > 0) {
|
||||
return false;
|
||||
}
|
||||
stats().member_ways = members.size();
|
||||
|
||||
if (stats().member_ways == 1) {
|
||||
++stats().single_way_in_mp_relation;
|
||||
}
|
||||
|
||||
if (config().debug_level > 0) {
|
||||
std::cerr << "\nAssembling relation " << relation.id() << " containing " << members.size() << " way members with " << segment_list().size() << " nodes\n";
|
||||
}
|
||||
|
||||
const std::size_t area_offset = out_buffer.committed();
|
||||
|
||||
// Now create the Area object and add the attributes and tags
|
||||
// from the relation.
|
||||
bool okay = create_area(out_buffer, relation, members);
|
||||
if (okay) {
|
||||
if ((config().create_new_style_polygons && stats().no_tags_on_relation == 0) ||
|
||||
(config().create_old_style_polygons && stats().no_tags_on_relation != 0)) {
|
||||
out_buffer.commit();
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
} else {
|
||||
out_buffer.rollback();
|
||||
}
|
||||
|
||||
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 (stats().wrong_role == 0) {
|
||||
detail::for_each_member(relation, members, [this, &ways_that_should_be_areas, &area_tags](const osmium::RelationMember& member, const osmium::Way& way) {
|
||||
if (!std::strcmp(member.role(), "inner")) {
|
||||
if (!way.nodes().empty() && way.is_closed() && way.tags().size() > 0) {
|
||||
const auto d = std::count_if(way.tags().cbegin(), way.tags().cend(), std::cref(filter()));
|
||||
if (d > 0) {
|
||||
osmium::tags::KeyFilter::iterator way_fi_begin(std::cref(filter()), way.tags().cbegin(), way.tags().cend());
|
||||
osmium::tags::KeyFilter::iterator way_fi_end(std::cref(filter()), way.tags().cend(), way.tags().cend());
|
||||
osmium::tags::KeyFilter::iterator area_fi_begin(std::cref(filter()), area_tags.cbegin(), area_tags.cend());
|
||||
osmium::tags::KeyFilter::iterator area_fi_end(std::cref(filter()), area_tags.cend(), area_tags.cend());
|
||||
|
||||
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);
|
||||
} else {
|
||||
++stats().inner_with_same_tags;
|
||||
if (config().problem_reporter) {
|
||||
config().problem_reporter->report_inner_with_same_tags(way);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (debug()) {
|
||||
std::cerr << "Done: " << stats() << "\n";
|
||||
}
|
||||
|
||||
// Now build areas for all ways found in the last step.
|
||||
for (const osmium::Way* way : ways_that_should_be_areas) {
|
||||
AssemblerLegacy assembler{config()};
|
||||
if (!assembler(*way, out_buffer)) {
|
||||
okay = false;
|
||||
}
|
||||
stats() += assembler.stats();
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
}; // class AssemblerLegacy
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_ASSEMBLER_LEGACY_HPP
|
1203
third_party/libosmium/include/osmium/area/detail/basic_assembler.hpp
vendored
Normal file
1203
third_party/libosmium/include/osmium/area/detail/basic_assembler.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
93
third_party/libosmium/include/osmium/area/detail/basic_assembler_with_tags.hpp
vendored
Normal file
93
third_party/libosmium/include/osmium/area/detail/basic_assembler_with_tags.hpp
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
||||
#define OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <cstring>
|
||||
|
||||
#include <osmium/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class BasicAssemblerWithTags : public detail::BasicAssembler {
|
||||
|
||||
protected:
|
||||
|
||||
bool report_ways() const noexcept {
|
||||
if (!config().problem_reporter) {
|
||||
return false;
|
||||
}
|
||||
return stats().duplicate_nodes ||
|
||||
stats().duplicate_segments ||
|
||||
stats().intersections ||
|
||||
stats().open_rings ||
|
||||
stats().short_ways ||
|
||||
stats().touching_rings ||
|
||||
stats().ways_in_multiple_rings ||
|
||||
stats().wrong_role;
|
||||
}
|
||||
|
||||
static void copy_tags_without_type(osmium::builder::AreaBuilder& builder, const osmium::TagList& tags) {
|
||||
osmium::builder::TagListBuilder tl_builder{builder};
|
||||
for (const osmium::Tag& tag : tags) {
|
||||
if (std::strcmp(tag.key(), "type")) {
|
||||
tl_builder.add_tag(tag.key(), tag.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
using config_type = osmium::area::AssemblerConfig;
|
||||
|
||||
explicit BasicAssemblerWithTags(const config_type& config) :
|
||||
BasicAssembler(config) {
|
||||
}
|
||||
|
||||
}; // class BasicAssemblerWithTags
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_BASIC_ASSEMBLER_WITH_TAGS_HPP
|
389
third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp
vendored
Normal file
389
third_party/libosmium/include/osmium/area/detail/node_ref_segment.hpp
vendored
Normal file
@ -0,0 +1,389 @@
|
||||
#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-2017 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 <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/area/detail/vector.hpp>
|
||||
#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 {
|
||||
|
||||
class ProtoRing;
|
||||
|
||||
enum class role_type : uint8_t {
|
||||
unknown = 0,
|
||||
outer = 1,
|
||||
inner = 2,
|
||||
empty = 3
|
||||
};
|
||||
|
||||
/**
|
||||
* This helper class for the Assembler class models a segment,
|
||||
* the connection between two nodes.
|
||||
*
|
||||
* Internally segments 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 {
|
||||
|
||||
// First node in order described above.
|
||||
osmium::NodeRef m_first;
|
||||
|
||||
// Second node in order described above.
|
||||
osmium::NodeRef m_second;
|
||||
|
||||
// Way this segment was from.
|
||||
const osmium::Way* m_way;
|
||||
|
||||
// The ring this segment is part of. Initially nullptr, this
|
||||
// will be filled in once we know which ring the segment is in.
|
||||
ProtoRing* m_ring;
|
||||
|
||||
// The role of this segment from the member role.
|
||||
role_type m_role;
|
||||
|
||||
// Nodes have to be reversed to get the intended order.
|
||||
bool m_reverse = false;
|
||||
|
||||
// We found the right direction for this segment in the ring.
|
||||
// (This depends on whether it is an inner or outer ring.)
|
||||
bool m_direction_done = false;
|
||||
|
||||
public:
|
||||
|
||||
NodeRefSegment() noexcept :
|
||||
m_first(),
|
||||
m_second(),
|
||||
m_way(nullptr),
|
||||
m_ring(nullptr),
|
||||
m_role(role_type::unknown) {
|
||||
}
|
||||
|
||||
NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, role_type role, const osmium::Way* way) noexcept :
|
||||
m_first(nr1),
|
||||
m_second(nr2),
|
||||
m_way(way),
|
||||
m_ring(nullptr),
|
||||
m_role(role) {
|
||||
if (nr2.location() < nr1.location()) {
|
||||
using std::swap;
|
||||
swap(m_first, m_second);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The ring this segment is a part of. nullptr if we don't
|
||||
* have the ring yet.
|
||||
*/
|
||||
ProtoRing* ring() const noexcept {
|
||||
return m_ring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the segment has already been placed in a
|
||||
* ring.
|
||||
*/
|
||||
bool is_done() const noexcept {
|
||||
return m_ring != nullptr;
|
||||
}
|
||||
|
||||
void set_ring(ProtoRing* ring) noexcept {
|
||||
assert(ring);
|
||||
m_ring = ring;
|
||||
}
|
||||
|
||||
bool is_reverse() const noexcept {
|
||||
return m_reverse;
|
||||
}
|
||||
|
||||
void reverse() noexcept {
|
||||
m_reverse = !m_reverse;
|
||||
}
|
||||
|
||||
bool is_direction_done() const noexcept {
|
||||
return m_direction_done;
|
||||
}
|
||||
|
||||
void mark_direction_done() noexcept {
|
||||
m_direction_done = true;
|
||||
}
|
||||
|
||||
void mark_direction_not_done() noexcept {
|
||||
m_direction_done = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return real first NodeRef of Segment.
|
||||
*/
|
||||
const osmium::NodeRef& start() const noexcept {
|
||||
return m_reverse ? m_second : m_first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return real second NodeRef of Segment.
|
||||
*/
|
||||
const osmium::NodeRef& stop() const noexcept {
|
||||
return m_reverse ? m_first : m_second;
|
||||
}
|
||||
|
||||
bool role_outer() const noexcept {
|
||||
return m_role == role_type::outer;
|
||||
}
|
||||
|
||||
bool role_inner() const noexcept {
|
||||
return m_role == role_type::inner;
|
||||
}
|
||||
|
||||
bool role_empty() const noexcept {
|
||||
return m_role == role_type::empty;
|
||||
}
|
||||
|
||||
const char* role_name() const noexcept {
|
||||
static const char* names[] = { "unknown", "outer", "inner", "empty" };
|
||||
return names[int(m_role)];
|
||||
}
|
||||
|
||||
const osmium::Way* way() const noexcept {
|
||||
return m_way;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "determinant" of this segment. Used for calculating
|
||||
* the winding order or a ring.
|
||||
*/
|
||||
int64_t det() const noexcept {
|
||||
const vec a{start()};
|
||||
const vec b{stop()};
|
||||
return a * b;
|
||||
}
|
||||
|
||||
}; // 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* A NodeRefSegment is "smaller" if the first point is to the
|
||||
* left and down of the first point of the second segment.
|
||||
* If both first points are the same, the segment with the higher
|
||||
* slope comes first. If the slope is the same, the shorter
|
||||
* segment comes first.
|
||||
*/
|
||||
inline bool operator<(const NodeRefSegment& lhs, const NodeRefSegment& rhs) noexcept {
|
||||
if (lhs.first().location() == rhs.first().location()) {
|
||||
const vec p0{lhs.first().location()};
|
||||
const vec p1{lhs.second().location()};
|
||||
const vec q0{rhs.first().location()};
|
||||
const vec q1{rhs.second().location()};
|
||||
const vec p = p1 - p0;
|
||||
const vec q = q1 - q0;
|
||||
|
||||
if (p.x == 0 && q.x == 0) {
|
||||
return p.y < q.y;
|
||||
}
|
||||
|
||||
const auto a = p.y * q.x;
|
||||
const auto b = q.y * p.x;
|
||||
if (a == b) {
|
||||
return p.x < q.x;
|
||||
}
|
||||
return a > b;
|
||||
}
|
||||
return lhs.first().location() < rhs.first().location();
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const NodeRefSegment& segment) {
|
||||
return out << segment.start() << "--" << segment.stop()
|
||||
<< "[" << (segment.is_reverse() ? 'R' : '_')
|
||||
<< (segment.is_done() ? 'd' : '_')
|
||||
<< (segment.is_direction_done() ? 'D' : '_') << "]";
|
||||
}
|
||||
|
||||
inline bool outside_x_range(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||
return s1.first().location().x() > s2.second().location().x();
|
||||
}
|
||||
|
||||
inline bool y_range_overlap(const NodeRefSegment& s1, const NodeRefSegment& s2) noexcept {
|
||||
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());
|
||||
return !(m1.first > m2.second || m2.first > m1.second);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 arithmetic 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 or both 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 are collinear and overlap, the smallest
|
||||
* of the endpoints that is in the overlapping section is returned.
|
||||
*
|
||||
* @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) noexcept {
|
||||
// See http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
|
||||
// for some hints about how the algorithm works.
|
||||
const vec p0{s1.first()};
|
||||
const vec p1{s1.second()};
|
||||
const vec q0{s2.first()};
|
||||
const vec q1{s2.second()};
|
||||
|
||||
if ((p0 == q0 && p1 == q1) ||
|
||||
(p0 == q1 && p1 == q0)) {
|
||||
// segments are the same
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
const vec pd = p1 - p0;
|
||||
const int64_t d = pd * (q1 - q0);
|
||||
|
||||
if (d != 0) {
|
||||
// segments are not collinear
|
||||
|
||||
if (p0 == q0 || p0 == q1 || p1 == q0 || p1 == q1) {
|
||||
// touching at an end point
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
// intersection in a point
|
||||
|
||||
const int64_t na = (q1.x - q0.x) * (p0.y - q0.y) -
|
||||
(q1.y - q0.y) * (p0.x - q0.x);
|
||||
|
||||
const int64_t nb = (p1.x - p0.x) * (p0.y - q0.y) -
|
||||
(p1.y - p0.y) * (p0.x - q0.x);
|
||||
|
||||
if ((d > 0 && na >= 0 && na <= d && nb >= 0 && nb <= d) ||
|
||||
(d < 0 && na <= 0 && na >= d && nb <= 0 && nb >= d)) {
|
||||
const double ua = double(na) / d;
|
||||
const vec i = p0 + ua * (p1 - p0);
|
||||
return osmium::Location{int32_t(i.x), int32_t(i.y)};
|
||||
}
|
||||
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
// segments are collinear
|
||||
|
||||
if (pd * (q0 - p0) == 0) {
|
||||
// segments are on the same line
|
||||
|
||||
struct seg_loc {
|
||||
int segment;
|
||||
osmium::Location location;
|
||||
};
|
||||
|
||||
seg_loc sl[4];
|
||||
sl[0] = {0, s1.first().location() };
|
||||
sl[1] = {0, s1.second().location()};
|
||||
sl[2] = {1, s2.first().location() };
|
||||
sl[3] = {1, s2.second().location()};
|
||||
|
||||
std::sort(sl, sl+4, [](const seg_loc& lhs, const seg_loc& rhs) {
|
||||
return lhs.location < rhs.location;
|
||||
});
|
||||
|
||||
if (sl[1].location == sl[2].location) {
|
||||
return osmium::Location();
|
||||
}
|
||||
|
||||
if (sl[0].segment != sl[1].segment) {
|
||||
if (sl[0].location == sl[1].location) {
|
||||
return sl[2].location;
|
||||
}
|
||||
return sl[1].location;
|
||||
}
|
||||
}
|
||||
|
||||
return osmium::Location{};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_NODE_REF_SEGMENT_HPP
|
243
third_party/libosmium/include/osmium/area/detail/proto_ring.hpp
vendored
Normal file
243
third_party/libosmium/include/osmium/area/detail/proto_ring.hpp
vendored
Normal file
@ -0,0 +1,243 @@
|
||||
#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-2017 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 <cstdint>
|
||||
#include <iostream>
|
||||
#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 {
|
||||
|
||||
class Way;
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* A ring in the process of being built by the Assembler object.
|
||||
*/
|
||||
class ProtoRing {
|
||||
|
||||
public:
|
||||
|
||||
using segments_type = std::vector<NodeRefSegment*>;
|
||||
|
||||
private:
|
||||
|
||||
// Segments in this ring.
|
||||
segments_type m_segments;
|
||||
|
||||
// If this is an outer ring, these point to it's inner rings
|
||||
// (if any).
|
||||
std::vector<ProtoRing*> m_inner;
|
||||
|
||||
// The smallest segment. Will be kept current whenever a new
|
||||
// segment is added to the ring.
|
||||
NodeRefSegment* m_min_segment;
|
||||
|
||||
// If this is an inner ring, points to the outer ring.
|
||||
ProtoRing* m_outer_ring;
|
||||
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
static int64_t next_num() noexcept {
|
||||
static int64_t counter = 0;
|
||||
return ++counter;
|
||||
}
|
||||
|
||||
int64_t m_num;
|
||||
#endif
|
||||
|
||||
int64_t m_sum;
|
||||
|
||||
public:
|
||||
|
||||
explicit ProtoRing(NodeRefSegment* segment) noexcept :
|
||||
m_segments(),
|
||||
m_inner(),
|
||||
m_min_segment(segment),
|
||||
m_outer_ring(nullptr),
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
m_num(next_num()),
|
||||
#endif
|
||||
m_sum(0) {
|
||||
add_segment_back(segment);
|
||||
}
|
||||
|
||||
void add_segment_back(NodeRefSegment* segment) {
|
||||
assert(segment);
|
||||
if (*segment < *m_min_segment) {
|
||||
m_min_segment = segment;
|
||||
}
|
||||
m_segments.push_back(segment);
|
||||
segment->set_ring(this);
|
||||
m_sum += segment->det();
|
||||
}
|
||||
|
||||
NodeRefSegment* min_segment() const noexcept {
|
||||
return m_min_segment;
|
||||
}
|
||||
|
||||
ProtoRing* outer_ring() const noexcept {
|
||||
return m_outer_ring;
|
||||
}
|
||||
|
||||
void set_outer_ring(ProtoRing* outer_ring) noexcept {
|
||||
assert(outer_ring);
|
||||
assert(m_inner.empty());
|
||||
m_outer_ring = outer_ring;
|
||||
}
|
||||
|
||||
const std::vector<ProtoRing*>& inner_rings() const noexcept {
|
||||
return m_inner;
|
||||
}
|
||||
|
||||
void add_inner_ring(ProtoRing* ring) {
|
||||
assert(ring);
|
||||
assert(!m_outer_ring);
|
||||
m_inner.push_back(ring);
|
||||
}
|
||||
|
||||
bool is_outer() const noexcept {
|
||||
return !m_outer_ring;
|
||||
}
|
||||
|
||||
const segments_type& segments() const noexcept {
|
||||
return m_segments;
|
||||
}
|
||||
|
||||
const NodeRef& get_node_ref_start() const noexcept {
|
||||
return m_segments.front()->start();
|
||||
}
|
||||
|
||||
const NodeRef& get_node_ref_stop() const noexcept {
|
||||
return m_segments.back()->stop();
|
||||
}
|
||||
|
||||
bool closed() const noexcept {
|
||||
return get_node_ref_start().location() == get_node_ref_stop().location();
|
||||
}
|
||||
|
||||
void reverse() {
|
||||
std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment* segment) {
|
||||
segment->reverse();
|
||||
});
|
||||
std::reverse(m_segments.begin(), m_segments.end());
|
||||
m_sum = -m_sum;
|
||||
}
|
||||
|
||||
void mark_direction_done() {
|
||||
std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment* segment) {
|
||||
segment->mark_direction_done();
|
||||
});
|
||||
}
|
||||
|
||||
bool is_cw() const noexcept {
|
||||
return m_sum <= 0;
|
||||
}
|
||||
|
||||
int64_t sum() const noexcept {
|
||||
return m_sum;
|
||||
}
|
||||
|
||||
void fix_direction() noexcept {
|
||||
if (is_cw() == is_outer()) {
|
||||
reverse();
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_inner.clear();
|
||||
m_outer_ring = nullptr;
|
||||
std::for_each(m_segments.begin(), m_segments.end(), [](NodeRefSegment* segment) {
|
||||
segment->mark_direction_not_done();
|
||||
});
|
||||
}
|
||||
|
||||
void get_ways(std::set<const osmium::Way*>& ways) const {
|
||||
for (const auto& segment : m_segments) {
|
||||
ways.insert(segment->way());
|
||||
}
|
||||
}
|
||||
|
||||
void join_forward(ProtoRing& other) {
|
||||
for (NodeRefSegment* segment : other.m_segments) {
|
||||
add_segment_back(segment);
|
||||
}
|
||||
}
|
||||
|
||||
void join_backward(ProtoRing& other) {
|
||||
for (auto it = other.m_segments.rbegin(); it != other.m_segments.rend(); ++it) {
|
||||
(*it)->reverse();
|
||||
add_segment_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void print(std::ostream& out) const {
|
||||
#ifdef OSMIUM_DEBUG_RING_NO
|
||||
out << "Ring #" << m_num << " [";
|
||||
#else
|
||||
out << "Ring [";
|
||||
#endif
|
||||
if (!m_segments.empty()) {
|
||||
out << m_segments.front()->start().ref();
|
||||
}
|
||||
for (const auto& segment : m_segments) {
|
||||
out << ',' << segment->stop().ref();
|
||||
}
|
||||
out << "]-" << (is_outer() ? "OUTER" : "INNER");
|
||||
}
|
||||
|
||||
}; // 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
|
363
third_party/libosmium/include/osmium/area/detail/segment_list.hpp
vendored
Normal file
363
third_party/libosmium/include/osmium/area/detail/segment_list.hpp
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
#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-2017 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 <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/detail/node_ref_segment.hpp>
|
||||
#include <osmium/area/problem_reporter.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/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* Iterate over all relation members and the vector of ways at the
|
||||
* same time and call given function with the relation member and
|
||||
* way as parameter. This takes into account that there might be
|
||||
* non-way members in the relation.
|
||||
*/
|
||||
template <typename F>
|
||||
inline void for_each_member(const osmium::Relation& relation, const std::vector<const osmium::Way*>& ways, F&& func) {
|
||||
auto way_it = ways.cbegin();
|
||||
for (const osmium::RelationMember& member : relation.members()) {
|
||||
if (member.type() == osmium::item_type::way) {
|
||||
assert(way_it != ways.cend());
|
||||
func(member, **way_it);
|
||||
++way_it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
static role_type parse_role(const char* role) noexcept {
|
||||
if (role[0] == '\0') {
|
||||
return role_type::empty;
|
||||
}
|
||||
if (!std::strcmp(role, "outer")) {
|
||||
return role_type::outer;
|
||||
}
|
||||
if (!std::strcmp(role, "inner")) {
|
||||
return role_type::inner;
|
||||
}
|
||||
return role_type::unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of segments in all the ways together.
|
||||
*/
|
||||
static std::size_t get_num_segments(const std::vector<const osmium::Way*>& members) noexcept {
|
||||
return std::accumulate(members.cbegin(), members.cend(), static_cast<std::size_t>(0), [](std::size_t sum, const osmium::Way* way) {
|
||||
if (way->nodes().empty()) {
|
||||
return sum;
|
||||
}
|
||||
return sum + way->nodes().size() - 1;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t extract_segments_from_way_impl(ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way, role_type role) {
|
||||
uint32_t invalid_locations = 0;
|
||||
|
||||
osmium::NodeRef previous_nr;
|
||||
for (const osmium::NodeRef& nr : way.nodes()) {
|
||||
if (!nr.location().valid()) {
|
||||
++invalid_locations;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_invalid_location(way.id(), nr.ref());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (previous_nr.location()) {
|
||||
if (previous_nr.location() != nr.location()) {
|
||||
m_segments.emplace_back(previous_nr, nr, role, &way);
|
||||
} else {
|
||||
++duplicate_nodes;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_duplicate_node(previous_nr.ref(), nr.ref(), nr.location());
|
||||
}
|
||||
}
|
||||
}
|
||||
previous_nr = nr;
|
||||
}
|
||||
|
||||
return invalid_locations;
|
||||
}
|
||||
|
||||
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.
|
||||
std::size_t size() const noexcept {
|
||||
return m_segments.size();
|
||||
}
|
||||
|
||||
/// Is the segment list empty?
|
||||
bool empty() const noexcept {
|
||||
return m_segments.empty();
|
||||
}
|
||||
|
||||
using const_iterator = slist_type::const_iterator;
|
||||
using iterator = slist_type::iterator;
|
||||
|
||||
NodeRefSegment& front() {
|
||||
return m_segments.front();
|
||||
}
|
||||
|
||||
NodeRefSegment& back() {
|
||||
return m_segments.back();
|
||||
}
|
||||
|
||||
const NodeRefSegment& operator[](std::size_t n) const noexcept {
|
||||
assert(n < m_segments.size());
|
||||
return m_segments[n];
|
||||
}
|
||||
|
||||
NodeRefSegment& operator[](std::size_t n) noexcept {
|
||||
assert(n < m_segments.size());
|
||||
return m_segments[n];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// 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 nodes with same location) are
|
||||
* removed after reporting the duplicate node.
|
||||
*/
|
||||
uint32_t extract_segments_from_way(ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way) {
|
||||
if (way.nodes().empty()) {
|
||||
return 0;
|
||||
}
|
||||
m_segments.reserve(way.nodes().size() - 1);
|
||||
return extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role_type::outer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all segments from all ways that make up this
|
||||
* multipolygon relation and add them to the list.
|
||||
*/
|
||||
uint32_t extract_segments_from_ways(ProblemReporter* problem_reporter,
|
||||
uint64_t& duplicate_nodes,
|
||||
uint64_t& duplicate_ways,
|
||||
const osmium::Relation& relation,
|
||||
const std::vector<const osmium::Way*>& members) {
|
||||
assert(relation.cmembers().size() >= members.size());
|
||||
|
||||
const std::size_t num_segments = get_num_segments(members);
|
||||
if (problem_reporter) {
|
||||
problem_reporter->set_nodes(num_segments);
|
||||
}
|
||||
m_segments.reserve(num_segments);
|
||||
|
||||
std::unordered_set<osmium::object_id_type> ids;
|
||||
ids.reserve(members.size());
|
||||
uint32_t invalid_locations = 0;
|
||||
for_each_member(relation, members, [&](const osmium::RelationMember& member, const osmium::Way& way) {
|
||||
if (ids.count(way.id()) == 0) {
|
||||
ids.insert(way.id());
|
||||
const auto role = parse_role(member.role());
|
||||
invalid_locations += extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role);
|
||||
} else {
|
||||
++duplicate_ways;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_duplicate_way(way);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return invalid_locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(ProblemReporter* problem_reporter, uint64_t& duplicate_segments, uint64_t& overlapping_segments) {
|
||||
while (true) {
|
||||
auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
|
||||
if (it == m_segments.end()) {
|
||||
break;
|
||||
}
|
||||
if (m_debug) {
|
||||
std::cerr << " erase duplicate segment: " << *it << "\n";
|
||||
}
|
||||
|
||||
// Only count and report duplicate segments if they
|
||||
// belong to the same way or if they don't both have
|
||||
// the role "inner". Those cases are definitely wrong.
|
||||
// If the duplicate segments belong to different
|
||||
// "inner" ways, they could be touching inner rings
|
||||
// which are perfectly okay. Note that for this check
|
||||
// the role has to be correct in the member data.
|
||||
if (it->way() == std::next(it)->way() || !it->role_inner() || !std::next(it)->role_inner()) {
|
||||
++duplicate_segments;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_duplicate_segment(it->first(), it->second());
|
||||
}
|
||||
}
|
||||
|
||||
if (it+2 != m_segments.end() && *it == *(it+2)) {
|
||||
++overlapping_segments;
|
||||
if (problem_reporter) {
|
||||
problem_reporter->report_overlapping_segment(it->first(), it->second());
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
uint32_t find_intersections(ProblemReporter* problem_reporter) const {
|
||||
if (m_segments.empty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t found_intersections = 0;
|
||||
|
||||
for (auto it1 = m_segments.cbegin(); it1 != m_segments.cend() - 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;
|
||||
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
|
121
third_party/libosmium/include/osmium/area/detail/vector.hpp
vendored
Normal file
121
third_party/libosmium/include/osmium/area/detail/vector.hpp
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
#ifndef OSMIUM_AREA_DETAIL_VECTOR_HPP
|
||||
#define OSMIUM_AREA_DETAIL_VECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <iosfwd>
|
||||
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/**
|
||||
* This helper class models a 2D vector in the mathematical sense.
|
||||
* It uses 64 bit integers internally which has enough precision
|
||||
* for most operations with inputs based on 32 bit locations.
|
||||
*/
|
||||
struct vec {
|
||||
|
||||
int64_t x;
|
||||
int64_t y;
|
||||
|
||||
constexpr vec(int64_t a, int64_t b) noexcept :
|
||||
x(a),
|
||||
y(b) {
|
||||
}
|
||||
|
||||
constexpr explicit vec(const osmium::Location& l) noexcept :
|
||||
x(l.x()),
|
||||
y(l.y()) {
|
||||
}
|
||||
|
||||
constexpr explicit vec(const osmium::NodeRef& nr) noexcept :
|
||||
x(nr.x()),
|
||||
y(nr.y()) {
|
||||
}
|
||||
|
||||
}; // struct vec
|
||||
|
||||
// addition
|
||||
constexpr inline vec operator+(const vec& lhs, const vec& rhs) noexcept {
|
||||
return vec{lhs.x + rhs.x, lhs.y + rhs.y};
|
||||
}
|
||||
|
||||
// subtraction
|
||||
constexpr inline vec operator-(const vec& lhs, const vec& rhs) noexcept {
|
||||
return vec{lhs.x - rhs.x, lhs.y - rhs.y};
|
||||
}
|
||||
|
||||
// cross product
|
||||
constexpr inline int64_t operator*(const vec& lhs, const vec& rhs) noexcept {
|
||||
return lhs.x * rhs.y - lhs.y * rhs.x;
|
||||
}
|
||||
|
||||
// scale vector
|
||||
constexpr inline vec operator*(double s, const vec& v) noexcept {
|
||||
return vec{int64_t(s * v.x), int64_t(s * v.y)};
|
||||
}
|
||||
|
||||
// scale vector
|
||||
constexpr inline vec operator*(const vec& v, double s) noexcept {
|
||||
return vec{int64_t(s * v.x), int64_t(s * v.y)};
|
||||
}
|
||||
|
||||
// equality
|
||||
constexpr inline bool operator==(const vec& lhs, const vec& rhs) noexcept {
|
||||
return lhs.x == rhs.x && lhs.y == rhs.y;
|
||||
}
|
||||
|
||||
// inequality
|
||||
constexpr inline bool operator!=(const vec& lhs, const vec& rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const vec& v) {
|
||||
return out << '(' << v.x << ',' << v.y << ')';
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_DETAIL_VECTOR_HPP
|
132
third_party/libosmium/include/osmium/area/geom_assembler.hpp
vendored
Normal file
132
third_party/libosmium/include/osmium/area/geom_assembler.hpp
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
#ifndef OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
||||
#define OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/area/assembler_config.hpp>
|
||||
#include <osmium/area/detail/basic_assembler.hpp>
|
||||
#include <osmium/area/detail/segment_list.hpp>
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/builder/osm_object_builder.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* Assembles area objects from closed ways or multipolygon relations
|
||||
* and their members. Unlike the Assembler, this one doesn't take
|
||||
* tags into account at all. And it doesn't interpret all the config
|
||||
* settings and doesn't do all the checks and error reporting the
|
||||
* Assembler does.
|
||||
*
|
||||
* This class was developed specifically for the need of osm2pgsql.
|
||||
* Unless you know what you are doing, use the Assembler class instead
|
||||
* of this class. Contact the Libosmium developers if you want to use
|
||||
* this class.
|
||||
*/
|
||||
class GeomAssembler : public detail::BasicAssembler {
|
||||
|
||||
public:
|
||||
|
||||
using config_type = osmium::area::AssemblerConfig;
|
||||
|
||||
explicit GeomAssembler(const config_type& config) :
|
||||
detail::BasicAssembler(config) {
|
||||
}
|
||||
|
||||
~GeomAssembler() noexcept = default;
|
||||
|
||||
/**
|
||||
* Assemble an area from the given way.
|
||||
*
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
|
||||
segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way);
|
||||
|
||||
if (!create_rings()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(way);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
out_buffer.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assemble an area from the given relation and its member ways
|
||||
* which are in the ways_buffer.
|
||||
*
|
||||
* The resulting area is put into the out_buffer.
|
||||
*
|
||||
* @returns false if there was some kind of error building the
|
||||
* area, true otherwise.
|
||||
*/
|
||||
bool operator()(const osmium::Relation& relation, const osmium::memory::Buffer& ways_buffer, osmium::memory::Buffer& out_buffer) {
|
||||
for (const auto& way : ways_buffer.select<osmium::Way>()) {
|
||||
segment_list().extract_segments_from_way(config().problem_reporter, stats().duplicate_nodes, way);
|
||||
}
|
||||
|
||||
if (!create_rings()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
osmium::builder::AreaBuilder builder{out_buffer};
|
||||
builder.initialize_from_object(relation);
|
||||
add_rings_to_area(builder);
|
||||
}
|
||||
out_buffer.commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class GeomAssembler
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_GEOM_ASSEMBLER_HPP
|
210
third_party/libosmium/include/osmium/area/multipolygon_collector.hpp
vendored
Normal file
210
third_party/libosmium/include/osmium/area/multipolygon_collector.hpp
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_COLLECTOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/stats.hpp>
|
||||
#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>
|
||||
|
||||
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.
|
||||
* @pre The Ids of all objects must be unique in the input data.
|
||||
*/
|
||||
template <typename TAssembler>
|
||||
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
|
||||
|
||||
using collector_type = osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false>;
|
||||
|
||||
using assembler_config_type = typename TAssembler::config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
osmium::memory::Buffer m_output_buffer;
|
||||
|
||||
area_stats m_stats;
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
return (!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
m_stats += assembler.stats();
|
||||
possibly_flush_output_buffer();
|
||||
}
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
void complete_relation(osmium::relations::RelationMeta& relation_meta) {
|
||||
const osmium::Relation& relation = this->get_relation(relation_meta);
|
||||
const osmium::memory::Buffer& buffer = this->members_buffer();
|
||||
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
const size_t offset = this->get_offset(member.type(), member.ref());
|
||||
ways.push_back(&buffer.get<const osmium::Way>(offset));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, m_output_buffer);
|
||||
m_stats += assembler.stats();
|
||||
possibly_flush_output_buffer();
|
||||
} catch (const 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
|
189
third_party/libosmium/include/osmium/area/multipolygon_manager.hpp
vendored
Normal file
189
third_party/libosmium/include/osmium/area/multipolygon_manager.hpp
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <vector>
|
||||
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/relations/manager_util.hpp>
|
||||
#include <osmium/relations/members_database.hpp>
|
||||
#include <osmium/relations/relations_database.hpp>
|
||||
#include <osmium/relations/relations_manager.hpp>
|
||||
#include <osmium/storage/item_stash.hpp>
|
||||
#include <osmium/tags/taglist.hpp>
|
||||
#include <osmium/tags/tags_filter.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @pre The Ids of all objects must be unique in the input data.
|
||||
*/
|
||||
template <typename TAssembler>
|
||||
class MultipolygonManager : public osmium::relations::RelationsManager<MultipolygonManager<TAssembler>, false, true, false> {
|
||||
|
||||
using assembler_config_type = typename TAssembler::config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
area_stats m_stats;
|
||||
|
||||
osmium::TagsFilter m_filter;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a MultipolygonManager.
|
||||
*
|
||||
* @param assembler_config The configuration that will be given to
|
||||
* any newly constructed area assembler.
|
||||
* @param filter An optional filter specifying what tags are
|
||||
* needed on closed ways or multipolygon relations
|
||||
* to build the area.
|
||||
*/
|
||||
explicit MultipolygonManager(const assembler_config_type& assembler_config, const osmium::TagsFilter& filter = osmium::TagsFilter{true}) :
|
||||
m_assembler_config(assembler_config),
|
||||
m_filter(filter) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the aggregated statistics generated by the assemblers
|
||||
* called from the manager.
|
||||
*/
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon
|
||||
* or type=boundary with at least one way member.
|
||||
*/
|
||||
bool new_relation(const osmium::Relation& relation) const {
|
||||
const char* type = relation.tags().get_value_by_key("type");
|
||||
|
||||
// ignore relations without "type" tag
|
||||
if (type == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) && osmium::tags::match_any_of(relation.tags(), m_filter)) {
|
||||
return std::any_of(relation.members().cbegin(), relation.members().cend(), [](const RelationMember& member) {
|
||||
return member.type() == osmium::item_type::way;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a relation is complete, ie. all members
|
||||
* were found in the input. It will build the area using the
|
||||
* assembler.
|
||||
*/
|
||||
void complete_relation(const osmium::Relation& relation) {
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
ways.push_back(this->get_member_way(member.ref()));
|
||||
assert(ways.back() != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
void after_way(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()) {
|
||||
if (way.tags().has_tag("area", "no")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (osmium::tags::match_none_of(way.tags(), m_filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(way, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
this->possibly_flush();
|
||||
}
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
}; // class MultipolygonManager
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_MULTIPOLYGON_MANAGER_HPP
|
180
third_party/libosmium/include/osmium/area/multipolygon_manager_legacy.hpp
vendored
Normal file
180
third_party/libosmium/include/osmium/area/multipolygon_manager_legacy.hpp
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
#ifndef OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
||||
#define OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <vector>
|
||||
|
||||
#include <osmium/area/stats.hpp>
|
||||
#include <osmium/handler.hpp>
|
||||
#include <osmium/handler/check_order.hpp>
|
||||
#include <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/callback_buffer.hpp>
|
||||
#include <osmium/osm/item_type.hpp>
|
||||
#include <osmium/osm/relation.hpp>
|
||||
#include <osmium/osm/tag.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/relations/manager_util.hpp>
|
||||
#include <osmium/relations/members_database.hpp>
|
||||
#include <osmium/relations/relations_database.hpp>
|
||||
#include <osmium/relations/relations_manager.hpp>
|
||||
#include <osmium/storage/item_stash.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @pre The Ids of all objects must be unique in the input data.
|
||||
*/
|
||||
template <typename TAssembler>
|
||||
class MultipolygonManagerLegacy : public osmium::relations::RelationsManager<MultipolygonManagerLegacy<TAssembler>, false, true, false> {
|
||||
|
||||
using assembler_config_type = typename TAssembler::config_type;
|
||||
const assembler_config_type m_assembler_config;
|
||||
|
||||
area_stats m_stats;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a MultipolygonManagerLegacy.
|
||||
*
|
||||
* @param assembler_config The configuration that will be given to
|
||||
* any newly constructed area assembler.
|
||||
*/
|
||||
explicit MultipolygonManagerLegacy(const assembler_config_type& assembler_config) :
|
||||
m_assembler_config(assembler_config) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the aggregated statistics generated by the assemblers
|
||||
* called from the manager.
|
||||
*/
|
||||
const area_stats& stats() const noexcept {
|
||||
return m_stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* We are interested in all relations tagged with type=multipolygon
|
||||
* or type=boundary with at least one way member.
|
||||
*/
|
||||
bool new_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 ((!std::strcmp(type, "multipolygon")) || (!std::strcmp(type, "boundary"))) {
|
||||
return std::any_of(relation.members().cbegin(), relation.members().cend(), [](const RelationMember& member) {
|
||||
return member.type() == osmium::item_type::way;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a relation is complete, ie. all members
|
||||
* were found in the input. It will build the area using the
|
||||
* assembler.
|
||||
*/
|
||||
void complete_relation(const osmium::Relation& relation) {
|
||||
std::vector<const osmium::Way*> ways;
|
||||
ways.reserve(relation.members().size());
|
||||
for (const auto& member : relation.members()) {
|
||||
if (member.ref() != 0) {
|
||||
ways.push_back(this->get_member_way(member.ref()));
|
||||
assert(ways.back() != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TAssembler assembler{m_assembler_config};
|
||||
assembler(relation, ways, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when a way is not in any multipolygon
|
||||
* relation.
|
||||
*/
|
||||
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, this->buffer());
|
||||
m_stats += assembler.stats();
|
||||
}
|
||||
} catch (const osmium::invalid_location&) {
|
||||
// XXX ignore
|
||||
}
|
||||
}
|
||||
|
||||
}; // class MultipolygonManagerLegacy
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_MULTIPOLYGON_MANAGER_LEGACY_HPP
|
238
third_party/libosmium/include/osmium/area/problem_reporter.hpp
vendored
Normal file
238
third_party/libosmium/include/osmium/area/problem_reporter.hpp
vendored
Normal file
@ -0,0 +1,238 @@
|
||||
#ifndef OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||
#define OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/osm/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class NodeRef;
|
||||
class Way;
|
||||
|
||||
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;
|
||||
|
||||
// Number of nodes in the area
|
||||
size_t m_nodes;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void set_nodes(size_t nodes) noexcept {
|
||||
m_nodes = nodes;
|
||||
}
|
||||
|
||||
// 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 a node/location where rings touch. This is often wrong,
|
||||
* but not necessarily so.
|
||||
*
|
||||
* @param node_id ID of the node.
|
||||
* @param location Location of the node.
|
||||
*/
|
||||
virtual void report_touching_ring(osmium::object_id_type node_id, 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 a duplicate segments. Two or more segments are directly
|
||||
* on top of each other. This can be a problem, if there is a
|
||||
* spike for instance, or it could be okay, if there are touching
|
||||
* inner rings.
|
||||
*
|
||||
* @param nr1 NodeRef of one end of the segment.
|
||||
* @param nr2 NodeRef of the other end of the segment.
|
||||
*/
|
||||
virtual void report_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a duplicate segments. Two or more segments are directly
|
||||
* on top of each other. This can be a problem, if there is a
|
||||
* spike for instance, or it could be okay, if there are touching
|
||||
* inner rings.
|
||||
*
|
||||
* @param nr1 NodeRef of one end of the segment.
|
||||
* @param nr2 NodeRef of the other end of the segment.
|
||||
*/
|
||||
virtual void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an open ring.
|
||||
*
|
||||
* @param nr NodeRef of one end of the ring.
|
||||
* @param way Optional pointer to way the end node is in.
|
||||
*/
|
||||
virtual void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a way that is in multiple rings.
|
||||
*
|
||||
* @param way The way.
|
||||
*/
|
||||
virtual void report_way_in_multiple_rings(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a way with role inner that has the same tags as the
|
||||
* relation or outer ways.
|
||||
*
|
||||
* @param way The way.
|
||||
*/
|
||||
virtual void report_inner_with_same_tags(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report an invalid location in a way.
|
||||
*
|
||||
* @param way_id ID of the way the node is in.
|
||||
* @param node_id ID of the node with the invalid location.
|
||||
*/
|
||||
virtual void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a way that is more than once in a relation.
|
||||
*
|
||||
* @param way The way
|
||||
*/
|
||||
virtual void report_duplicate_way(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to reporting specific problems, this is used to
|
||||
* report all ways belonging to areas having problems.
|
||||
*
|
||||
* @param way The way
|
||||
*/
|
||||
virtual void report_way(const osmium::Way& way) {
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
}; // class ProblemReporter
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_HPP
|
141
third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp
vendored
Normal file
141
third_party/libosmium/include/osmium/area/problem_reporter_exception.hpp
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
#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-2017 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 {
|
||||
|
||||
class NodeRef;
|
||||
class Way;
|
||||
|
||||
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_touching_ring(osmium::object_id_type node_id, osmium::Location location) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_touching_ring(node_id, 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_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_duplicate_segment(nr1, nr2);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_overlapping_segment(nr1, nr2);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_ring_not_closed(nr, way);
|
||||
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()};
|
||||
}
|
||||
|
||||
void report_way_in_multiple_rings(const osmium::Way& way) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_way_in_multiple_rings(way);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_inner_with_same_tags(const osmium::Way& way) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_inner_with_same_tags(way);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_invalid_location(way_id, node_id);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
m_sstream.str("");
|
||||
ProblemReporterStream::report_duplicate_way(way);
|
||||
throw std::runtime_error{m_sstream.str()};
|
||||
}
|
||||
|
||||
}; // class ProblemReporterException
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_EXCEPTION_HPP
|
250
third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp
vendored
Normal file
250
third_party/libosmium/include/osmium/area/problem_reporter_ogr.hpp
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
#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-2017 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/item_type.hpp>
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/osm/node_ref.hpp>
|
||||
#include <osmium/osm/node_ref_list.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.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;
|
||||
gdalcpp::Layer m_layer_ways;
|
||||
|
||||
void set_object(gdalcpp::Feature& feature) {
|
||||
const char t[2] = {osmium::item_type_to_char(m_object_type), '\0'};
|
||||
feature.set_field("obj_type", t);
|
||||
feature.set_field("obj_id", int32_t(m_object_id));
|
||||
feature.set_field("nodes", int32_t(m_nodes));
|
||||
}
|
||||
|
||||
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)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", double(id1));
|
||||
feature.set_field("id2", double(id2));
|
||||
feature.set_field("problem", 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) {
|
||||
auto ogr_linestring = std::unique_ptr<OGRLineString>{new OGRLineString{}};
|
||||
ogr_linestring->addPoint(loc1.lon(), loc1.lat());
|
||||
ogr_linestring->addPoint(loc2.lon(), loc2.lat());
|
||||
|
||||
gdalcpp::Feature feature{m_layer_lerror, std::move(ogr_linestring)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", static_cast<double>(id1));
|
||||
feature.set_field("id2", static_cast<double>(id2));
|
||||
feature.set_field("problem", 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_ways(dataset, "ways", wkbLineString) {
|
||||
|
||||
// 64bit integers are not supported in GDAL < 2, so we
|
||||
// are using a workaround here in fields where we expect
|
||||
// node IDs, we use real numbers.
|
||||
m_layer_perror
|
||||
.add_field("obj_type", OFTString, 1)
|
||||
.add_field("obj_id", OFTInteger, 10)
|
||||
.add_field("nodes", OFTInteger, 8)
|
||||
.add_field("id1", OFTReal, 12, 1)
|
||||
.add_field("id2", OFTReal, 12, 1)
|
||||
.add_field("problem", OFTString, 30)
|
||||
;
|
||||
|
||||
m_layer_lerror
|
||||
.add_field("obj_type", OFTString, 1)
|
||||
.add_field("obj_id", OFTInteger, 10)
|
||||
.add_field("nodes", OFTInteger, 8)
|
||||
.add_field("id1", OFTReal, 12, 1)
|
||||
.add_field("id2", OFTReal, 12, 1)
|
||||
.add_field("problem", OFTString, 30)
|
||||
;
|
||||
|
||||
m_layer_ways
|
||||
.add_field("obj_type", OFTString, 1)
|
||||
.add_field("obj_id", OFTInteger, 10)
|
||||
.add_field("way_id", OFTInteger, 10)
|
||||
.add_field("nodes", OFTInteger, 8)
|
||||
;
|
||||
}
|
||||
|
||||
~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_touching_ring(osmium::object_id_type node_id, osmium::Location location) override {
|
||||
write_point("touching_ring", node_id, 0, 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", way1_id, way2_id, intersection);
|
||||
write_line("intersection", way1_id, way2_id, way1_seg_start, way1_seg_end);
|
||||
write_line("intersection", way2_id, way1_id, way2_seg_start, way2_seg_end);
|
||||
}
|
||||
|
||||
void report_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
write_line("duplicate_segment", nr1.ref(), nr2.ref(), nr1.location(), nr2.location());
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
write_line("overlapping_segment", nr1.ref(), nr2.ref(), nr1.location(), nr2.location());
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
write_point("ring_not_closed", nr.ref(), way ? way->id() : 0, nr.location());
|
||||
}
|
||||
|
||||
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", way_id, 0, 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", way_id, 0, seg_start, seg_end);
|
||||
}
|
||||
|
||||
void report_way_in_multiple_rings(const osmium::Way& way) override {
|
||||
if (way.nodes().size() < 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", int32_t(way.id()));
|
||||
feature.set_field("id2", 0);
|
||||
feature.set_field("problem", "way_in_multiple_rings");
|
||||
feature.add_to_layer();
|
||||
} catch (const osmium::geometry_error&) {
|
||||
// XXX
|
||||
}
|
||||
}
|
||||
|
||||
void report_inner_with_same_tags(const osmium::Way& way) override {
|
||||
if (way.nodes().size() < 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", int32_t(way.id()));
|
||||
feature.set_field("id2", 0);
|
||||
feature.set_field("problem", "inner_with_same_tags");
|
||||
feature.add_to_layer();
|
||||
} catch (const osmium::geometry_error&) {
|
||||
// XXX
|
||||
}
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
if (way.nodes().size() < 2) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature{m_layer_lerror, m_ogr_factory.create_linestring(way)};
|
||||
set_object(feature);
|
||||
feature.set_field("id1", int32_t(way.id()));
|
||||
feature.set_field("id2", 0);
|
||||
feature.set_field("problem", "duplicate_way");
|
||||
feature.add_to_layer();
|
||||
} catch (const osmium::geometry_error&) {
|
||||
// XXX
|
||||
}
|
||||
}
|
||||
|
||||
void report_way(const osmium::Way& way) override {
|
||||
if (way.nodes().empty()) {
|
||||
return;
|
||||
}
|
||||
if (way.nodes().size() == 1) {
|
||||
const auto& first_nr = way.nodes()[0];
|
||||
write_point("single_node_in_way", way.id(), first_nr.ref(), first_nr.location());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
gdalcpp::Feature feature{m_layer_ways, m_ogr_factory.create_linestring(way)};
|
||||
set_object(feature);
|
||||
feature.set_field("way_id", int32_t(way.id()));
|
||||
feature.add_to_layer();
|
||||
} catch (const osmium::geometry_error&) {
|
||||
// XXX
|
||||
}
|
||||
}
|
||||
|
||||
}; // class ProblemReporterOGR
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_OGR_HPP
|
139
third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp
vendored
Normal file
139
third_party/libosmium/include/osmium/area/problem_reporter_stream.hpp
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
#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-2017 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/node_ref.hpp>
|
||||
#include <osmium/osm/types.hpp>
|
||||
#include <osmium/osm/way.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 << " (with " << m_nodes << " nodes): ";
|
||||
}
|
||||
|
||||
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_touching_ring(osmium::object_id_type node_id, osmium::Location location) override {
|
||||
header("touching ring");
|
||||
*m_out << "node_id=" << node_id << " 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_duplicate_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
header("duplicate segment");
|
||||
*m_out << "node_id1=" << nr1.ref() << " location1=" << nr1.location()
|
||||
<< " node_id2=" << nr2.ref() << " location2=" << nr2.location() << "\n";
|
||||
}
|
||||
|
||||
void report_overlapping_segment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) override {
|
||||
header("overlapping segment");
|
||||
*m_out << "node_id1=" << nr1.ref() << " location1=" << nr1.location()
|
||||
<< " node_id2=" << nr2.ref() << " location2=" << nr2.location() << "\n";
|
||||
}
|
||||
|
||||
void report_ring_not_closed(const osmium::NodeRef& nr, const osmium::Way* way = nullptr) override {
|
||||
header("ring not closed");
|
||||
*m_out << "node_id=" << nr.ref() << " location=" << nr.location();
|
||||
if (way) {
|
||||
*m_out << " on way " << way->id();
|
||||
}
|
||||
*m_out << "\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";
|
||||
}
|
||||
|
||||
void report_way_in_multiple_rings(const osmium::Way& way) override {
|
||||
header("way in multiple rings");
|
||||
*m_out << "way_id=" << way.id() << '\n';
|
||||
}
|
||||
|
||||
void report_inner_with_same_tags(const osmium::Way& way) override {
|
||||
header("inner way with same tags as relation or outer");
|
||||
*m_out << "way_id=" << way.id() << '\n';
|
||||
}
|
||||
|
||||
void report_invalid_location(osmium::object_id_type way_id, osmium::object_id_type node_id) override {
|
||||
header("invalid location");
|
||||
*m_out << "way_id=" << way_id << " node_id=" << node_id << '\n';
|
||||
}
|
||||
|
||||
void report_duplicate_way(const osmium::Way& way) override {
|
||||
header("duplicate way");
|
||||
*m_out << "way_id=" << way.id() << '\n';
|
||||
}
|
||||
|
||||
}; // class ProblemReporterStream
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_PROBLEM_REPORTER_STREAM_HPP
|
135
third_party/libosmium/include/osmium/area/stats.hpp
vendored
Normal file
135
third_party/libosmium/include/osmium/area/stats.hpp
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
#ifndef OSMIUM_AREA_STATS_HPP
|
||||
#define OSMIUM_AREA_STATS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <ostream>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace area {
|
||||
|
||||
/**
|
||||
* These statistics are generated by the area assembler code. They
|
||||
* tell the user of the assembler a lot about the objects this area
|
||||
* is made out of, what happened during the assembly, and what errors
|
||||
* there were.
|
||||
*/
|
||||
struct area_stats {
|
||||
uint64_t area_really_complex_case = 0; ///< Most difficult case with rings touching in multiple points
|
||||
uint64_t area_simple_case = 0; ///< Simple case, no touching rings
|
||||
uint64_t area_touching_rings_case = 0; ///< More difficult case with touching rings
|
||||
uint64_t duplicate_nodes = 0; ///< Consecutive identical nodes or consecutive nodes with same location
|
||||
uint64_t duplicate_segments = 0; ///< Segments duplicated (going back and forth)
|
||||
uint64_t duplicate_ways = 0; ///< Ways that are in relation more than once
|
||||
uint64_t from_relations = 0; ///< Area created from multipolygon relation
|
||||
uint64_t from_ways = 0; ///< Area created from way
|
||||
uint64_t inner_rings = 0; ///< Number of inner rings
|
||||
uint64_t inner_with_same_tags = 0; ///< Number of inner ways with same tags as area
|
||||
uint64_t intersections = 0; ///< Number of intersections between segments
|
||||
uint64_t member_ways = 0; ///< Number of ways in the area
|
||||
uint64_t no_tags_on_relation = 0; ///< No tags on relation (old-style multipolygon with tags on outer ways)
|
||||
uint64_t no_way_in_mp_relation = 0; ///< Multipolygon relation with no way members
|
||||
uint64_t nodes = 0; ///< Number of nodes in the area
|
||||
uint64_t open_rings = 0; ///< Number of open rings in the area
|
||||
uint64_t outer_rings = 0; ///< Number of outer rings in the area
|
||||
uint64_t overlapping_segments = 0; ///< Three or more segments with same end points
|
||||
uint64_t short_ways = 0; ///< Number of ways with less than two nodes
|
||||
uint64_t single_way_in_mp_relation = 0; ///< Multipolygon relation containing a single way
|
||||
uint64_t touching_rings = 0; ///< Rings touching in a node
|
||||
uint64_t ways_in_multiple_rings = 0; ///< Different segments of a way ended up in different rings
|
||||
uint64_t wrong_role = 0; ///< Member has wrong role (not "outer", "inner", or empty)
|
||||
uint64_t invalid_locations = 0; ///< Invalid location found
|
||||
|
||||
area_stats& operator+=(const area_stats& other) noexcept {
|
||||
area_really_complex_case += other.area_really_complex_case;
|
||||
area_simple_case += other.area_simple_case;
|
||||
area_touching_rings_case += other.area_touching_rings_case;
|
||||
duplicate_nodes += other.duplicate_nodes;
|
||||
duplicate_segments += other.duplicate_segments;
|
||||
duplicate_ways += other.duplicate_ways;
|
||||
from_relations += other.from_relations;
|
||||
from_ways += other.from_ways;
|
||||
inner_rings += other.inner_rings;
|
||||
inner_with_same_tags += other.inner_with_same_tags;
|
||||
intersections += other.intersections;
|
||||
member_ways += other.member_ways;
|
||||
no_tags_on_relation += other.no_tags_on_relation;
|
||||
no_way_in_mp_relation += other.no_way_in_mp_relation;
|
||||
nodes += other.nodes;
|
||||
open_rings += other.open_rings;
|
||||
outer_rings += other.outer_rings;
|
||||
short_ways += other.short_ways;
|
||||
single_way_in_mp_relation += other.single_way_in_mp_relation;
|
||||
touching_rings += other.touching_rings;
|
||||
ways_in_multiple_rings += other.ways_in_multiple_rings;
|
||||
wrong_role += other.wrong_role;
|
||||
invalid_locations += invalid_locations;
|
||||
return *this;
|
||||
}
|
||||
|
||||
}; // struct area_stats
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const area_stats& s) {
|
||||
return out << " area_really_complex_case=" << s.area_really_complex_case
|
||||
<< " area_simple_case=" << s.area_simple_case
|
||||
<< " area_touching_rings_case=" << s.area_touching_rings_case
|
||||
<< " duplicate_nodes=" << s.duplicate_nodes
|
||||
<< " duplicate_segments=" << s.duplicate_segments
|
||||
<< " duplicate_ways=" << s.duplicate_ways
|
||||
<< " from_relations=" << s.from_relations
|
||||
<< " from_ways=" << s.from_ways
|
||||
<< " inner_rings=" << s.inner_rings
|
||||
<< " inner_with_same_tags=" << s.inner_with_same_tags
|
||||
<< " intersections=" << s.intersections
|
||||
<< " member_ways=" << s.member_ways
|
||||
<< " no_tags_on_relation=" << s.no_tags_on_relation
|
||||
<< " no_way_in_mp_relation=" << s.no_way_in_mp_relation
|
||||
<< " nodes=" << s.nodes
|
||||
<< " open_rings=" << s.open_rings
|
||||
<< " outer_rings=" << s.outer_rings
|
||||
<< " short_ways=" << s.short_ways
|
||||
<< " single_way_in_mp_relation=" << s.single_way_in_mp_relation
|
||||
<< " touching_rings=" << s.touching_rings
|
||||
<< " ways_in_multiple_rings=" << s.ways_in_multiple_rings
|
||||
<< " wrong_role=" << s.wrong_role
|
||||
<< " invalid_locations=" << s.invalid_locations;
|
||||
}
|
||||
|
||||
} // namespace area
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_AREA_STATS_HPP
|
922
third_party/libosmium/include/osmium/builder/attr.hpp
vendored
Normal file
922
third_party/libosmium/include/osmium/builder/attr.hpp
vendored
Normal file
@ -0,0 +1,922 @@
|
||||
#ifndef OSMIUM_BUILDER_ATTR_HPP
|
||||
#define OSMIUM_BUILDER_ATTR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/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/timestamp.hpp>
|
||||
#include <osmium/osm/types.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 member_type_string {
|
||||
|
||||
osmium::item_type m_type;
|
||||
osmium::object_id_type m_ref;
|
||||
std::string m_role;
|
||||
|
||||
public:
|
||||
|
||||
member_type_string(osmium::item_type type, osmium::object_id_type ref, std::string&& role) :
|
||||
m_type(type),
|
||||
m_ref(ref),
|
||||
m_role(std::move(role)) {
|
||||
}
|
||||
|
||||
osmium::item_type type() const noexcept {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
osmium::object_id_type ref() const noexcept {
|
||||
return m_ref;
|
||||
}
|
||||
|
||||
const char* role() const noexcept {
|
||||
return m_role.c_str();
|
||||
}
|
||||
|
||||
}; // class member_type_string
|
||||
|
||||
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.set_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
|
235
third_party/libosmium/include/osmium/builder/builder.hpp
vendored
Normal file
235
third_party/libosmium/include/osmium/builder/builder.hpp
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
#ifndef OSMIUM_BUILDER_BUILDER_HPP
|
||||
#define OSMIUM_BUILDER_BUILDER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <osmium/memory/buffer.hpp>
|
||||
#include <osmium/memory/item.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
/**
|
||||
* @brief Classes for building OSM objects and other items in buffers
|
||||
*/
|
||||
namespace builder {
|
||||
|
||||
/**
|
||||
* Parent class for individual builder classes. Instantiate one of
|
||||
* its derived classes.
|
||||
*/
|
||||
class Builder {
|
||||
|
||||
osmium::memory::Buffer& m_buffer;
|
||||
Builder* m_parent;
|
||||
std::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()) {
|
||||
reserve_space(size);
|
||||
assert(buffer.is_aligned());
|
||||
if (m_parent) {
|
||||
assert(m_buffer.builder_count() == 1 && "Only one sub-builder can be open at any time.");
|
||||
m_parent->add_size(size);
|
||||
} else {
|
||||
assert(m_buffer.builder_count() == 0 && "Only one builder can be open at any time.");
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
m_buffer.increment_builder_count();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef NDEBUG
|
||||
~Builder() = default;
|
||||
#else
|
||||
~Builder() noexcept {
|
||||
m_buffer.decrement_builder_count();
|
||||
}
|
||||
#endif
|
||||
|
||||
osmium::memory::Item& item() const {
|
||||
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset);
|
||||
}
|
||||
|
||||
unsigned char* reserve_space(std::size_t size) {
|
||||
return m_buffer.reserve_space(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// We know the padding is only a very small number, so it will
|
||||
// always fit.
|
||||
const auto padding = static_cast<osmium::memory::item_size_type>(osmium::memory::align_bytes - (size() % osmium::memory::align_bytes));
|
||||
if (padding != osmium::memory::align_bytes) {
|
||||
std::fill_n(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(osmium::memory::item_size_type size) {
|
||||
item().add_size(size);
|
||||
if (m_parent) {
|
||||
m_parent->add_size(size);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t size() const noexcept {
|
||||
return item().byte_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*>(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 = reserve_space(length);
|
||||
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append data to buffer and append an additional \0.
|
||||
*
|
||||
* @param data Pointer to data.
|
||||
* @param length Length of data in bytes.
|
||||
* @returns The number of bytes appended (length + 1).
|
||||
*/
|
||||
osmium::memory::item_size_type append_with_zero(const char* data, const osmium::memory::item_size_type length) {
|
||||
unsigned char* target = reserve_space(length + 1);
|
||||
std::copy_n(reinterpret_cast<const unsigned char*>(data), length, target);
|
||||
target[length] = '\0';
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @deprecated Use append_with_zero() instead.
|
||||
*
|
||||
* @returns The number of bytes appended (always 1).
|
||||
*/
|
||||
OSMIUM_DEPRECATED osmium::memory::item_size_type append_zero() {
|
||||
*reserve_space(1) = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/// Return the buffer this builder is using.
|
||||
osmium::memory::Buffer& buffer() noexcept {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subitem to the object being built. This can be something
|
||||
* like a TagList or RelationMemberList.
|
||||
*/
|
||||
void add_item(const osmium::memory::Item& item) {
|
||||
m_buffer.add_item(item);
|
||||
add_size(item.padded_size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use the version of add_item() taking a
|
||||
* reference instead.
|
||||
*/
|
||||
OSMIUM_DEPRECATED void add_item(const osmium::memory::Item* item) {
|
||||
assert(item);
|
||||
add_item(*item);
|
||||
}
|
||||
|
||||
}; // class Builder
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_BUILDER_BUILDER_HPP
|
120
third_party/libosmium/include/osmium/builder/builder_helper.hpp
vendored
Normal file
120
third_party/libosmium/include/osmium/builder/builder_helper.hpp
vendored
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-2017 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) {
|
||||
const 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.
|
||||
*/
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list(osmium::memory::Buffer& buffer, const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
const 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.
|
||||
*/
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list_from_map(osmium::memory::Buffer& buffer, const std::map<const char*, const char*>& tags) {
|
||||
const 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.
|
||||
*/
|
||||
OSMIUM_DEPRECATED inline const osmium::TagList& build_tag_list_from_func(osmium::memory::Buffer& buffer, std::function<void(osmium::builder::TagListBuilder&)> func) {
|
||||
const 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
|
680
third_party/libosmium/include/osmium/builder/osm_object_builder.hpp
vendored
Normal file
680
third_party/libosmium/include/osmium/builder/osm_object_builder.hpp
vendored
Normal file
@ -0,0 +1,680 @@
|
||||
#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-2017 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 <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <initializer_list>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include <osmium/builder/builder.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/types.hpp>
|
||||
#include <osmium/osm/way.hpp>
|
||||
#include <osmium/util/cast.hpp>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace memory {
|
||||
class Buffer;
|
||||
} // namespace memory
|
||||
|
||||
namespace builder {
|
||||
|
||||
class TagListBuilder : public Builder {
|
||||
|
||||
public:
|
||||
|
||||
explicit TagListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(TagList)) {
|
||||
new (&item()) TagList{};
|
||||
}
|
||||
|
||||
explicit TagListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(TagList)) {
|
||||
new (&item()) TagList{};
|
||||
}
|
||||
|
||||
~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));
|
||||
add_size(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 std::size_t key_length, const char* value, const std::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_with_zero(key, osmium::memory::item_size_type(key_length)));
|
||||
add_size(append_with_zero(value, osmium::memory::item_size_type(value_length)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
add_size(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()));
|
||||
add_size(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 Builder {
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeRefListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(T)) {
|
||||
new (&item()) T{};
|
||||
}
|
||||
|
||||
explicit NodeRefListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(T)) {
|
||||
new (&item()) T{};
|
||||
}
|
||||
|
||||
~NodeRefListBuilder() {
|
||||
add_padding();
|
||||
}
|
||||
|
||||
void add_node_ref(const NodeRef& node_ref) {
|
||||
new (reserve_space_for<osmium::NodeRef>()) osmium::NodeRef{node_ref};
|
||||
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
|
||||
|
||||
using WayNodeListBuilder = NodeRefListBuilder<WayNodeList>;
|
||||
using OuterRingBuilder = NodeRefListBuilder<OuterRing>;
|
||||
using InnerRingBuilder = NodeRefListBuilder<InnerRing>;
|
||||
|
||||
class RelationMemberListBuilder : public Builder {
|
||||
|
||||
/**
|
||||
* 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 std::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_with_zero(role, osmium::memory::item_size_type(length)));
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit RelationMemberListBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList{};
|
||||
}
|
||||
|
||||
explicit RelationMemberListBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(RelationMemberList)) {
|
||||
new (&item()) RelationMemberList{};
|
||||
}
|
||||
|
||||
~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 std::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 Builder {
|
||||
|
||||
osmium::ChangesetComment* m_comment = nullptr;
|
||||
|
||||
void add_user(osmium::ChangesetComment& comment, const char* user, const std::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_with_zero(user, osmium::memory::item_size_type(length)));
|
||||
}
|
||||
|
||||
void add_text(osmium::ChangesetComment& comment, const char* text, const std::size_t length) {
|
||||
if (length > std::numeric_limits<osmium::changeset_comment_size_type>::max() - 1) {
|
||||
throw std::length_error{"OSM changeset comment is too long"};
|
||||
}
|
||||
comment.set_text_size(osmium::changeset_comment_size_type(length) + 1);
|
||||
add_size(append_with_zero(text, osmium::memory::item_size_type(length)));
|
||||
add_padding(true);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit ChangesetDiscussionBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion{};
|
||||
}
|
||||
|
||||
explicit ChangesetDiscussionBuilder(Builder& parent) :
|
||||
Builder(parent.buffer(), &parent, sizeof(ChangesetDiscussion)) {
|
||||
new (&item()) ChangesetDiscussion{};
|
||||
}
|
||||
|
||||
~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!");
|
||||
osmium::ChangesetComment& comment = *m_comment;
|
||||
m_comment = nullptr;
|
||||
add_text(comment, text, std::strlen(text));
|
||||
}
|
||||
|
||||
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!");
|
||||
osmium::ChangesetComment& comment = *m_comment;
|
||||
m_comment = nullptr;
|
||||
add_text(comment, text.c_str(), text.size());
|
||||
}
|
||||
|
||||
}; // class ChangesetDiscussionBuilder
|
||||
|
||||
#define OSMIUM_FORWARD(setter) \
|
||||
template <typename... TArgs> \
|
||||
type& setter(TArgs&&... args) { \
|
||||
object().setter(std::forward<TArgs>(args)...); \
|
||||
return static_cast<type&>(*this); \
|
||||
}
|
||||
|
||||
template <typename TDerived, typename T>
|
||||
class OSMObjectBuilder : public Builder {
|
||||
|
||||
using type = TDerived;
|
||||
|
||||
constexpr static const std::size_t min_size_for_user = osmium::memory::padded_length(sizeof(string_size_type) + 1);
|
||||
|
||||
public:
|
||||
|
||||
explicit OSMObjectBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(T) + min_size_for_user) {
|
||||
new (&item()) T{};
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(T), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the object buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
T& object() noexcept {
|
||||
return static_cast<T&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a const reference to the object buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
const T& cobject() const noexcept {
|
||||
return static_cast<const T&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
TDerived& set_user(const char* user, const string_size_type length) {
|
||||
const auto size_of_object = sizeof(T) + sizeof(string_size_type);
|
||||
assert(cobject().user_size() == 1 && (size() <= size_of_object + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - sizeof(string_size_type) - 1;
|
||||
if (length > available_space) {
|
||||
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||
std::fill_n(reserve_space(space_needed), space_needed, 0);
|
||||
add_size(static_cast<uint32_t>(space_needed));
|
||||
}
|
||||
std::copy_n(user, length, object().data() + size_of_object);
|
||||
object().set_user_size(length + 1);
|
||||
|
||||
return static_cast<TDerived&>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
TDerived& set_user(const char* user) {
|
||||
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user User name.
|
||||
*/
|
||||
TDerived& set_user(const std::string& user) {
|
||||
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||
}
|
||||
|
||||
/// @deprecated Use set_user(...) instead.
|
||||
template <typename... TArgs>
|
||||
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||
set_user(std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_id)
|
||||
OSMIUM_FORWARD(set_visible)
|
||||
OSMIUM_FORWARD(set_deleted)
|
||||
OSMIUM_FORWARD(set_version)
|
||||
OSMIUM_FORWARD(set_changeset)
|
||||
OSMIUM_FORWARD(set_uid)
|
||||
OSMIUM_FORWARD(set_uid_from_signed)
|
||||
OSMIUM_FORWARD(set_timestamp)
|
||||
OSMIUM_FORWARD(set_attribute)
|
||||
OSMIUM_FORWARD(set_removed)
|
||||
|
||||
void add_tags(const std::initializer_list<std::pair<const char*, const char*>>& tags) {
|
||||
osmium::builder::TagListBuilder tl_builder{buffer(), this};
|
||||
for (const auto& p : tags) {
|
||||
tl_builder.add_tag(p.first, p.second);
|
||||
}
|
||||
}
|
||||
|
||||
}; // class OSMObjectBuilder
|
||||
|
||||
class NodeBuilder : public OSMObjectBuilder<NodeBuilder, Node> {
|
||||
|
||||
using type = NodeBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit NodeBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<NodeBuilder, Node>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit NodeBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<NodeBuilder, Node>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_location)
|
||||
|
||||
}; // class NodeBuilder
|
||||
|
||||
class WayBuilder : public OSMObjectBuilder<WayBuilder, Way> {
|
||||
|
||||
using type = WayBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit WayBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<WayBuilder, Way>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit WayBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<WayBuilder, Way>(parent.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 RelationBuilder : public OSMObjectBuilder<RelationBuilder, Relation> {
|
||||
|
||||
using type = RelationBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit RelationBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<RelationBuilder, Relation>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit RelationBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<RelationBuilder, Relation>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
}; // class RelationBuilder
|
||||
|
||||
class AreaBuilder : public OSMObjectBuilder<AreaBuilder, Area> {
|
||||
|
||||
using type = AreaBuilder;
|
||||
|
||||
public:
|
||||
|
||||
explicit AreaBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
OSMObjectBuilder<AreaBuilder, Area>(buffer, parent) {
|
||||
}
|
||||
|
||||
explicit AreaBuilder(Builder& parent) :
|
||||
OSMObjectBuilder<AreaBuilder, Area>(parent.buffer(), &parent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize area attributes from the attributes of the given object.
|
||||
*/
|
||||
void initialize_from_object(const osmium::OSMObject& source) {
|
||||
set_id(osmium::object_id_to_area_id(source.id(), source.type()));
|
||||
set_version(source.version());
|
||||
set_changeset(source.changeset());
|
||||
set_timestamp(source.timestamp());
|
||||
set_visible(source.visible());
|
||||
set_uid(source.uid());
|
||||
set_user(source.user());
|
||||
}
|
||||
|
||||
}; // class AreaBuilder
|
||||
|
||||
class ChangesetBuilder : public Builder {
|
||||
|
||||
using type = ChangesetBuilder;
|
||||
|
||||
constexpr static const std::size_t min_size_for_user = osmium::memory::padded_length(1);
|
||||
|
||||
public:
|
||||
|
||||
explicit ChangesetBuilder(osmium::memory::Buffer& buffer, Builder* parent = nullptr) :
|
||||
Builder(buffer, parent, sizeof(Changeset) + min_size_for_user) {
|
||||
new (&item()) Changeset{};
|
||||
add_size(min_size_for_user);
|
||||
std::fill_n(object().data() + sizeof(Changeset), min_size_for_user, 0);
|
||||
object().set_user_size(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reference to the changeset buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
Changeset& object() noexcept {
|
||||
return static_cast<Changeset&>(item());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a const reference to the changeset buing built.
|
||||
*
|
||||
* Note that this reference will be invalidated by every action
|
||||
* on the builder that might make the buffer grow. This includes
|
||||
* calls to set_user() and any time a new sub-builder is created.
|
||||
*/
|
||||
const Changeset& cobject() const noexcept {
|
||||
return static_cast<const Changeset&>(item());
|
||||
}
|
||||
|
||||
OSMIUM_FORWARD(set_id)
|
||||
OSMIUM_FORWARD(set_uid)
|
||||
OSMIUM_FORWARD(set_uid_from_signed)
|
||||
OSMIUM_FORWARD(set_created_at)
|
||||
OSMIUM_FORWARD(set_closed_at)
|
||||
OSMIUM_FORWARD(set_num_changes)
|
||||
OSMIUM_FORWARD(set_num_comments)
|
||||
OSMIUM_FORWARD(set_attribute)
|
||||
OSMIUM_FORWARD(set_removed)
|
||||
|
||||
// @deprecated Use set_bounds() instead.
|
||||
OSMIUM_DEPRECATED osmium::Box& bounds() noexcept {
|
||||
return object().bounds();
|
||||
}
|
||||
|
||||
ChangesetBuilder& set_bounds(const osmium::Box& box) noexcept {
|
||||
object().bounds() = box;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to user name.
|
||||
* @param length Length of user name (without \0 termination).
|
||||
*/
|
||||
ChangesetBuilder& set_user(const char* user, const string_size_type length) {
|
||||
assert(cobject().user_size() == 1 && (size() <= sizeof(Changeset) + osmium::memory::padded_length(1))
|
||||
&& "set_user() must be called at most once and before any sub-builders");
|
||||
const auto available_space = min_size_for_user - 1;
|
||||
if (length > available_space) {
|
||||
const auto space_needed = osmium::memory::padded_length(length - available_space);
|
||||
std::fill_n(reserve_space(space_needed), space_needed, 0);
|
||||
add_size(static_cast<uint32_t>(space_needed));
|
||||
}
|
||||
std::copy_n(user, length, object().data() + sizeof(Changeset));
|
||||
object().set_user_size(length + 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user Pointer to \0-terminated user name.
|
||||
*/
|
||||
ChangesetBuilder& set_user(const char* user) {
|
||||
return set_user(user, static_cast_with_assert<string_size_type>(std::strlen(user)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user name.
|
||||
*
|
||||
* @param user User name.
|
||||
*/
|
||||
ChangesetBuilder& set_user(const std::string& user) {
|
||||
return set_user(user.data(), static_cast_with_assert<string_size_type>(user.size()));
|
||||
}
|
||||
|
||||
/// @deprecated Use set_user(...) instead.
|
||||
template <typename... TArgs>
|
||||
OSMIUM_DEPRECATED void add_user(TArgs&&... args) {
|
||||
set_user(std::forward<TArgs>(args)...);
|
||||
}
|
||||
|
||||
}; // class ChangesetBuilder
|
||||
|
||||
#undef OSMIUM_FORWARD
|
||||
|
||||
} // namespace builder
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_BUILDER_OSM_OBJECT_BUILDER_HPP
|
66
third_party/libosmium/include/osmium/diff_handler.hpp
vendored
Normal file
66
third_party/libosmium/include/osmium/diff_handler.hpp
vendored
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-2017 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 noexcept {
|
||||
}
|
||||
|
||||
void way(const osmium::DiffWay&) const noexcept {
|
||||
}
|
||||
|
||||
void relation(const osmium::DiffRelation&) const noexcept {
|
||||
}
|
||||
|
||||
}; // class DiffHandler
|
||||
|
||||
} // namespace diff_handler
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_DIFF_HANDLER_HPP
|
143
third_party/libosmium/include/osmium/diff_iterator.hpp
vendored
Normal file
143
third_party/libosmium/include/osmium/diff_iterator.hpp
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
#ifndef OSMIUM_DIFF_ITERATOR_HPP
|
||||
#define OSMIUM_DIFF_ITERATOR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#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 {
|
||||
|
||||
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);
|
||||
|
||||
const bool use_curr_for_prev = m_prev->type() != m_curr->type() || m_prev->id() != m_curr->id();
|
||||
const 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:
|
||||
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
using value_type = const osmium::DiffObject;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = value_type*;
|
||||
using reference = value_type&;
|
||||
|
||||
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
third_party/libosmium/include/osmium/diff_visitor.hpp
vendored
Normal file
104
third_party/libosmium/include/osmium/diff_visitor.hpp
vendored
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-2017 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
|
195
third_party/libosmium/include/osmium/dynamic_handler.hpp
vendored
Normal file
195
third_party/libosmium/include/osmium/dynamic_handler.hpp
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
#ifndef OSMIUM_DYNAMIC_HANDLER_HPP
|
||||
#define OSMIUM_DYNAMIC_HANDLER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/handler.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
class Node;
|
||||
class Way;
|
||||
class Relation;
|
||||
class Area;
|
||||
class Changeset;
|
||||
|
||||
namespace handler {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class HandlerWrapperBase {
|
||||
|
||||
public:
|
||||
|
||||
virtual ~HandlerWrapperBase() = default;
|
||||
|
||||
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>
|
||||
explicit 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 {
|
||||
|
||||
using impl_ptr = std::unique_ptr<osmium::handler::detail::HandlerWrapperBase>;
|
||||
impl_ptr m_impl;
|
||||
|
||||
public:
|
||||
|
||||
DynamicHandler() :
|
||||
m_impl(new osmium::handler::detail::HandlerWrapperBase) {
|
||||
}
|
||||
|
||||
template <typename THandler, typename... TArgs>
|
||||
void set(TArgs&&... args) {
|
||||
m_impl.reset(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
|
138
third_party/libosmium/include/osmium/experimental/flex_reader.hpp
vendored
Normal file
138
third_party/libosmium/include/osmium/experimental/flex_reader.hpp
vendored
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
|
||||
#define OSMIUM_EXPERIMENTAL_FLEX_READER_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <osmium/area/assembler.hpp>
|
||||
#include <osmium/area/multipolygon_collector.hpp>
|
||||
#include <osmium/handler/node_locations_for_ways.hpp> // IWYU pragma: keep
|
||||
#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
third_party/libosmium/include/osmium/fwd.hpp
vendored
Normal file
70
third_party/libosmium/include/osmium/fwd.hpp
vendored
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-2017 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
|
158
third_party/libosmium/include/osmium/geom/coordinates.hpp
vendored
Normal file
158
third_party/libosmium/include/osmium/geom/coordinates.hpp
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
#ifndef OSMIUM_GEOM_COORDINATES_HPP
|
||||
#define OSMIUM_GEOM_COORDINATES_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <iosfwd>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <osmium/osm/location.hpp>
|
||||
#include <osmium/util/double.hpp>
|
||||
|
||||
namespace osmium {
|
||||
|
||||
namespace geom {
|
||||
|
||||
struct Coordinates {
|
||||
|
||||
double x;
|
||||
double y;
|
||||
|
||||
/**
|
||||
* Default constructor creates invalid coordinates.
|
||||
*/
|
||||
Coordinates() noexcept :
|
||||
x(std::numeric_limits<double>::quiet_NaN()),
|
||||
y(std::numeric_limits<double>::quiet_NaN()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Coordinates from doubles. If any of them is NaN, the
|
||||
* coordinates are invalid.
|
||||
*/
|
||||
explicit Coordinates(double cx, double cy) noexcept :
|
||||
x(cx),
|
||||
y(cy) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Coordinates from a Location. Will throw
|
||||
* osmium::invalid_location if the location is not valid.
|
||||
*/
|
||||
Coordinates(const osmium::Location& location) :
|
||||
x(location.lon()),
|
||||
y(location.lat()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Coordinates are invalid if they have been default constructed.
|
||||
*/
|
||||
bool valid() const noexcept {
|
||||
return !std::isnan(x) && !std::isnan(y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert coordinates to text and append to given string. If the
|
||||
* coordinate is invalid, the fixed string "invalid" will be
|
||||
* added to the string.
|
||||
*
|
||||
* @param s String to append the coordinates to.
|
||||
* @param infix Character to print between the two coordinates.
|
||||
* @param precision Number of digits after the decimal point the
|
||||
* coordinate will be rounded to.
|
||||
*/
|
||||
void append_to_string(std::string& s, const char infix, int precision) const {
|
||||
if (valid()) {
|
||||
osmium::util::double2string(s, x, precision);
|
||||
s += infix;
|
||||
osmium::util::double2string(s, y, precision);
|
||||
} else {
|
||||
s.append("invalid");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert coordinates to text and append to given string. If the
|
||||
* coordinate is invalid, the fixed string "invalid" will be
|
||||
* added to the string between the prefix and suffix characters.
|
||||
*
|
||||
* @param s String to append the coordinates to.
|
||||
* @param prefix Character to print before the first coordinate.
|
||||
* @param infix Character to print between the two coordinates.
|
||||
* @param suffix Character to print after the second coordinate.
|
||||
* @param precision Number of digits after the decimal point the
|
||||
* coordinate will be rounded to.
|
||||
*/
|
||||
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
|
||||
|
||||
/**
|
||||
* Check whether two Coordinates are equal. Invalid coordinates are
|
||||
* equal to other invalid coordinates but not equal to any valid
|
||||
* coordinates.
|
||||
*
|
||||
* Because this is comparing floating point values, it 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 {
|
||||
if (!lhs.valid() && !rhs.valid()) {
|
||||
return true;
|
||||
}
|
||||
#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
|
428
third_party/libosmium/include/osmium/geom/factory.hpp
vendored
Normal file
428
third_party/libosmium/include/osmium/geom/factory.hpp
vendored
Normal file
@ -0,0 +1,428 @@
|
||||
#ifndef OSMIUM_GEOM_FACTORY_HPP
|
||||
#define OSMIUM_GEOM_FACTORY_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/node_ref_list.hpp>
|
||||
#include <osmium/osm/types.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();
|
||||
}
|
||||
|
||||
}; // class 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::NodeRefList& 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:
|
||||
|
||||
GeometryFactory<TGeomImpl, TProjection>() :
|
||||
m_projection(),
|
||||
m_impl(m_projection.epsg()) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for default initialized projection.
|
||||
*/
|
||||
template <typename... TArgs>
|
||||
explicit GeometryFactory<TGeomImpl, TProjection>(TArgs&&... args) :
|
||||
m_projection(),
|
||||
m_impl(m_projection.epsg(), 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(m_projection.epsg(), std::forward<TArgs>(args)...) {
|
||||
}
|
||||
|
||||
using projection_type = TProjection;
|
||||
|
||||
using point_type = typename TGeomImpl::point_type;
|
||||
using linestring_type = typename TGeomImpl::linestring_type;
|
||||
using polygon_type = typename TGeomImpl::polygon_type;
|
||||
using multipolygon_type = typename TGeomImpl::multipolygon_type;
|
||||
using ring_type = typename TGeomImpl::ring_type;
|
||||
|
||||
int epsg() const noexcept {
|
||||
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 (const auto& item : area) {
|
||||
if (item.type() == osmium::item_type::outer_ring) {
|
||||
auto& ring = static_cast<const osmium::OuterRing&>(item);
|
||||
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 (item.type() == osmium::item_type::inner_ring) {
|
||||
auto& ring = static_cast<const osmium::InnerRing&>(item);
|
||||
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{"invalid area"};
|
||||
}
|
||||
|
||||
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
|
161
third_party/libosmium/include/osmium/geom/geojson.hpp
vendored
Normal file
161
third_party/libosmium/include/osmium/geom/geojson.hpp
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
#ifndef OSMIUM_GEOM_GEOJSON_HPP
|
||||
#define OSMIUM_GEOM_GEOJSON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 GeoJSONFactoryImpl {
|
||||
|
||||
std::string m_str;
|
||||
int m_precision;
|
||||
|
||||
public:
|
||||
|
||||
using point_type = std::string;
|
||||
using linestring_type = std::string;
|
||||
using polygon_type = std::string;
|
||||
using multipolygon_type = std::string;
|
||||
using ring_type = std::string;
|
||||
|
||||
GeoJSONFactoryImpl(int /* srid */, 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
|
271
third_party/libosmium/include/osmium/geom/geos.hpp
vendored
Normal file
271
third_party/libosmium/include/osmium/geom/geos.hpp
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
#ifndef OSMIUM_GEOM_GEOS_HPP
|
||||
#define OSMIUM_GEOM_GEOS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 <geos/version.h>
|
||||
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && (GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR <= 5))
|
||||
|
||||
#define OSMIUM_WITH_GEOS
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* This file contains code for conversion of OSM geometries into GEOS
|
||||
* geometries.
|
||||
*
|
||||
* Note that everything in this file is deprecated and only works up to
|
||||
* GEOS 3.5. It uses the GEOS C++ API which the GEOS project does not consider
|
||||
* to be a stable, external API. We probably should have used the GEOS C API
|
||||
* instead.
|
||||
*
|
||||
* @attention If you include this file, you'll need to link with `libgeos`.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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>
|
||||
#include <osmium/util/compatibility.hpp>
|
||||
|
||||
// MSVC doesn't support throw_with_nested yet
|
||||
#ifdef _MSC_VER
|
||||
# define THROW throw
|
||||
#else
|
||||
# include <exception>
|
||||
# define THROW std::throw_with_nested
|
||||
#endif
|
||||
|
||||
namespace osmium {
|
||||
|
||||
struct geos_geometry_error : public geometry_error {
|
||||
|
||||
explicit 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 {
|
||||
|
||||
/// @deprecated
|
||||
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:
|
||||
|
||||
using point_type = std::unique_ptr<geos::geom::Point>;
|
||||
using linestring_type = std::unique_ptr<geos::geom::LineString>;
|
||||
using polygon_type = std::unique_ptr<geos::geom::Polygon>;
|
||||
using multipolygon_type = std::unique_ptr<geos::geom::MultiPolygon>;
|
||||
using ring_type = std::unique_ptr<geos::geom::LinearRing>;
|
||||
|
||||
explicit GEOSFactoryImpl(int /* srid */, geos::geom::GeometryFactory& geos_factory) :
|
||||
m_precision_model(nullptr),
|
||||
m_our_geos_factory(nullptr),
|
||||
m_geos_factory(&geos_factory) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Do not set SRID explicitly. It will be set to the
|
||||
* correct value automatically.
|
||||
*/
|
||||
OSMIUM_DEPRECATED explicit GEOSFactoryImpl(int /* srid */, int srid) :
|
||||
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()) {
|
||||
}
|
||||
|
||||
explicit GEOSFactoryImpl(int srid) :
|
||||
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 (const 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<std::size_t>(0), 2));
|
||||
} catch (const 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 (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
linestring_type linestring_finish(std::size_t /* num_points */) {
|
||||
try {
|
||||
return linestring_type{m_geos_factory->createLineString(m_coordinate_sequence.release())};
|
||||
} catch (const 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 (const 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<std::size_t>(0), 2));
|
||||
} catch (const 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 (const 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<std::size_t>(0), 2));
|
||||
} catch (const 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 (const 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 (const 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 (const geos::util::GEOSException& e) {
|
||||
THROW(osmium::geos_geometry_error(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
}; // class GEOSFactoryImpl
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// @deprecated
|
||||
template <typename TProjection = IdentityProjection>
|
||||
using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#undef THROW
|
||||
|
||||
#endif
|
||||
|
||||
#endif // OSMIUM_GEOM_GEOS_HPP
|
96
third_party/libosmium/include/osmium/geom/haversine.hpp
vendored
Normal file
96
third_party/libosmium/include/osmium/geom/haversine.hpp
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef OSMIUM_GEOM_HAVERSINE_HPP
|
||||
#define OSMIUM_GEOM_HAVERSINE_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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 const double EARTH_RADIUS_IN_METERS = 6372797.560856;
|
||||
|
||||
/**
|
||||
* Calculate distance in meters between two sets of coordinates.
|
||||
*
|
||||
* @pre @code c1.valid() && c2.valid() @endcode
|
||||
*/
|
||||
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
|
162
third_party/libosmium/include/osmium/geom/mercator_projection.hpp
vendored
Normal file
162
third_party/libosmium/include/osmium/geom/mercator_projection.hpp
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
#ifndef OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||
#define OSMIUM_GEOM_MERCATOR_PROJECTION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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_with_tan(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));
|
||||
}
|
||||
|
||||
#ifdef OSMIUM_USE_SLOW_MERCATOR_PROJECTION
|
||||
inline double lat_to_y(double lat) {
|
||||
return lat_to_y_with_tan(lat);
|
||||
}
|
||||
#else
|
||||
|
||||
// This is a much faster implementation than the canonical
|
||||
// implementation using the tan() function. For details
|
||||
// see https://github.com/osmcode/mercator-projection .
|
||||
inline double lat_to_y(double lat) { // not constexpr because math functions aren't
|
||||
if (lat < -78.0 || lat > 78.0) {
|
||||
return lat_to_y_with_tan(lat);
|
||||
}
|
||||
|
||||
return earth_radius_for_epsg3857 *
|
||||
((((((((((-3.1112583378460085319e-23 * lat +
|
||||
2.0465852743943268009e-19) * lat +
|
||||
6.4905282018672673884e-18) * lat +
|
||||
-1.9685447939983315591e-14) * lat +
|
||||
-2.2022588158115104182e-13) * lat +
|
||||
5.1617537365509453239e-10) * lat +
|
||||
2.5380136069803016519e-9) * lat +
|
||||
-5.1448323697228488745e-6) * lat +
|
||||
-9.4888671473357768301e-6) * lat +
|
||||
1.7453292518154191887e-2) * lat)
|
||||
/
|
||||
((((((((((-1.9741136066814230637e-22 * lat +
|
||||
-1.258514031244679556e-20) * lat +
|
||||
4.8141483273572351796e-17) * lat +
|
||||
8.6876090870176172185e-16) * lat +
|
||||
-2.3298743439377541768e-12) * lat +
|
||||
-1.9300094785736130185e-11) * lat +
|
||||
4.3251609106864178231e-8) * lat +
|
||||
1.7301944508516974048e-7) * lat +
|
||||
-3.4554675198786337842e-4) * lat +
|
||||
-5.4367203601085991108e-4) * lat + 1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Convert the coordinates from WGS84 lon/lat to web mercator.
|
||||
*
|
||||
* @pre @code c.valid() @endcode
|
||||
*/
|
||||
inline Coordinates lonlat_to_mercator(const Coordinates& c) {
|
||||
return Coordinates{detail::lon_to_x(c.x), detail::lat_to_y(c.y)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the coordinates from web mercator to WGS84 lon/lat.
|
||||
*
|
||||
* @pre @code c.valid() @endcode
|
||||
*/
|
||||
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:
|
||||
|
||||
MercatorProjection() {
|
||||
}
|
||||
|
||||
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
|
180
third_party/libosmium/include/osmium/geom/ogr.hpp
vendored
Normal file
180
third_party/libosmium/include/osmium/geom/ogr.hpp
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
#ifndef OSMIUM_GEOM_OGR_HPP
|
||||
#define OSMIUM_GEOM_OGR_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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:
|
||||
|
||||
using point_type = std::unique_ptr<OGRPoint>;
|
||||
using linestring_type = std::unique_ptr<OGRLineString>;
|
||||
using polygon_type = std::unique_ptr<OGRPolygon>;
|
||||
using multipolygon_type = std::unique_ptr<OGRMultiPolygon>;
|
||||
using ring_type = std::unique_ptr<OGRLinearRing>;
|
||||
|
||||
private:
|
||||
|
||||
linestring_type m_linestring{nullptr};
|
||||
multipolygon_type m_multipolygon{nullptr};
|
||||
polygon_type m_polygon{nullptr};
|
||||
ring_type m_ring{nullptr};
|
||||
|
||||
public:
|
||||
|
||||
explicit OGRFactoryImpl(int /* srid */) {
|
||||
}
|
||||
|
||||
/* 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.reset(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 */) {
|
||||
assert(!!m_linestring);
|
||||
return std::move(m_linestring);
|
||||
}
|
||||
|
||||
/* Polygon */
|
||||
|
||||
void polygon_start() {
|
||||
m_ring.reset(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 */) {
|
||||
auto 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
|
193
third_party/libosmium/include/osmium/geom/projection.hpp
vendored
Normal file
193
third_party/libosmium/include/osmium/geom/projection.hpp
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
#ifndef OSMIUM_GEOM_PROJECTION_HPP
|
||||
#define OSMIUM_GEOM_PROJECTION_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/mercator_projection.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:
|
||||
|
||||
explicit CRS(const char* crs) :
|
||||
m_crs(pj_init_plus(crs), ProjCRSDeleter()) {
|
||||
if (!m_crs) {
|
||||
throw osmium::projection_error{std::string{"creation of CRS failed: "} + pj_strerrno(*pj_get_errno_ref())};
|
||||
}
|
||||
}
|
||||
|
||||
explicit CRS(const std::string& crs) :
|
||||
CRS(crs.c_str()) {
|
||||
}
|
||||
|
||||
explicit CRS(int epsg) :
|
||||
CRS(std::string{"+init=epsg:"} + std::to_string(epsg)) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get underlying projPJ handle from proj library.
|
||||
*/
|
||||
projPJ get() const noexcept {
|
||||
return m_crs.get();
|
||||
}
|
||||
|
||||
bool is_latlong() const noexcept {
|
||||
return pj_is_latlong(m_crs.get()) != 0;
|
||||
}
|
||||
|
||||
bool is_geocent() const noexcept {
|
||||
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 osmium::projection_error if the projection fails
|
||||
*/
|
||||
// cppcheck-suppress passedByValue (because c is small and we want to change it)
|
||||
inline Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) {
|
||||
const 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.
|
||||
*
|
||||
* If this Projection is initialized with the constructor taking
|
||||
* an integer with the epsg code 4326, no projection is done. If it
|
||||
* is initialized with epsg code 3857 the Osmium-internal
|
||||
* implementation of the Mercator projection is used, otherwise this
|
||||
* falls back to using the proj.4 library. Note that this "magic" does
|
||||
* not work if you use any of the constructors taking a string.
|
||||
*/
|
||||
class Projection {
|
||||
|
||||
int m_epsg;
|
||||
std::string m_proj_string;
|
||||
CRS m_crs_wgs84{4326};
|
||||
CRS m_crs_user;
|
||||
|
||||
public:
|
||||
|
||||
explicit Projection(const std::string& proj_string) :
|
||||
m_epsg(-1),
|
||||
m_proj_string(proj_string),
|
||||
m_crs_user(proj_string) {
|
||||
}
|
||||
|
||||
explicit Projection(const char* proj_string) :
|
||||
m_epsg(-1),
|
||||
m_proj_string(proj_string),
|
||||
m_crs_user(proj_string) {
|
||||
}
|
||||
|
||||
explicit 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 {
|
||||
if (m_epsg == 4326) {
|
||||
return Coordinates{location.lon(), location.lat()};
|
||||
} else if (m_epsg == 3857) {
|
||||
return Coordinates{detail::lon_to_x(location.lon()),
|
||||
detail::lat_to_y(location.lat())};
|
||||
}
|
||||
|
||||
Coordinates 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
|
192
third_party/libosmium/include/osmium/geom/rapid_geojson.hpp
vendored
Normal file
192
third_party/libosmium/include/osmium/geom/rapid_geojson.hpp
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
#ifndef OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||
#define OSMIUM_GEOM_RAPID_GEOJSON_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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/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:
|
||||
|
||||
using point_type = void;
|
||||
using linestring_type = void;
|
||||
using polygon_type = void;
|
||||
using multipolygon_type = void;
|
||||
using ring_type = void;
|
||||
|
||||
RapidGeoJSONFactoryImpl(int /* srid */, 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
|
67
third_party/libosmium/include/osmium/geom/relations.hpp
vendored
Normal file
67
third_party/libosmium/include/osmium/geom/relations.hpp
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef OSMIUM_GEOM_RELATIONS_HPP
|
||||
#define OSMIUM_GEOM_RELATIONS_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is part of Osmium (http://osmcode.org/libosmium).
|
||||
|
||||
Copyright 2013-2017 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& lhs, const osmium::Box& rhs) noexcept {
|
||||
return ((lhs.bottom_left().x() >= rhs.bottom_left().x()) &&
|
||||
(lhs.top_right().x() <= rhs.top_right().x()) &&
|
||||
(lhs.bottom_left().y() >= rhs.bottom_left().y()) &&
|
||||
(lhs.top_right().y() <= rhs.top_right().y()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether one geometry overlaps another.
|
||||
*/
|
||||
inline bool overlaps(const osmium::Box& lhs, const osmium::Box& rhs) noexcept {
|
||||
return ((lhs.bottom_left().x() <= rhs.top_right().x()) &&
|
||||
(lhs.bottom_left().y() <= rhs.top_right().y()) &&
|
||||
(rhs.bottom_left().x() <= lhs.top_right().x()) &&
|
||||
(rhs.bottom_left().y() <= lhs.top_right().y()));
|
||||
}
|
||||
|
||||
} // namespace geom
|
||||
|
||||
} // namespace osmium
|
||||
|
||||
#endif // OSMIUM_GEOM_RELATIONS_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