Upgrade libosmium to v2.15.6

This commit is contained in:
Desone Burns II 2020-11-17 14:59:06 -07:00
parent 98fd17589d
commit dfc1bfc27e
319 changed files with 6268 additions and 3946 deletions

View File

@ -1,14 +1,22 @@
--- ---
Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-vararg,-fuchsia-*,-google-runtime-references,-hicpp-invalid-access-moved,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-vararg,-misc-macro-parentheses,-misc-unused-parameters,-modernize-make-unique,-modernize-raw-string-literal,-readability-avoid-const-params-in-decls,-readability-implicit-bool-cast,-readability-implicit-bool-conversion' Checks: '*,-android-cloexec-*,-bugprone-branch-clone,-bugprone-macro-parentheses,-cert-dcl21-cpp,-cert-err58-cpp,-clang-analyzer-optin.cplusplus.VirtualCall,-cppcoreguidelines-avoid-c-arrays,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-macro-usage,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-type-vararg,-fuchsia-*,-google-runtime-references,-hicpp-avoid-c-arrays,-hicpp-invalid-access-moved,-hicpp-no-array-decay,-hicpp-no-assembler,-hicpp-vararg,-misc-macro-parentheses,-misc-non-private-member-variables-in-classes,-misc-unused-parameters,-modernize-avoid-c-arrays,-modernize-make-unique,-modernize-raw-string-literal,-modernize-use-trailing-return-type,-readability-avoid-const-params-in-decls,-readability-implicit-bool-cast,-readability-implicit-bool-conversion,-readability-magic-numbers'
# #
# For a list of check options, see: # For a list of check options, see:
# http://clang.llvm.org/extra/clang-tidy/checks/list.html # https://clang.llvm.org/extra/clang-tidy/checks/list.html
# #
# Disabled checks: # Disabled checks:
# #
# android-cloexec-* # android-cloexec-*
# O_CLOEXEC isn't available on Windows making this non-portable. # O_CLOEXEC isn't available on Windows making this non-portable.
# #
# bugprone-branch-clone
# Nice idea but collides but with switch statements we'll need to use
# fall-throughs to fix this, which is also bad.
#
# bugprone-macro-parentheses
# False positive in the only place where it reports something and
# disabling locally doesn't work.
#
# cert-dcl21-cpp # cert-dcl21-cpp
# It is unclear whether this is still a good recommendation in modern C++. # It is unclear whether this is still a good recommendation in modern C++.
# #
@ -16,6 +24,22 @@ Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines
# Used in several singelton factory functions. I don't know of a better # Used in several singelton factory functions. I don't know of a better
# way to do this and it is rather unlikely that this will be a problem. # way to do this and it is rather unlikely that this will be a problem.
# #
# clang-analyzer-optin.cplusplus.VirtualCall
# Disable a warning we get from the Catch test framework.
#
# cppcoreguidelines-avoid-c-arrays
# Alias for modernize-avoid-c-arrays.
#
# cppcoreguidelines-avoid-magic-numbers
# Generally good advice, but there are too many places where this is
# useful, for instance in tests.
#
# cppcoreguidelines-macro-usage
# There are cases where we actually need macros.
#
# cppcoreguidelines-non-private-member-variables-in-classes
# Alias for misc-non-private-member-variables-in-classes
#
# cppcoreguidelines-owning-memory # cppcoreguidelines-owning-memory
# Don't want to add dependency on gsl library. # Don't want to add dependency on gsl library.
# #
@ -48,6 +72,9 @@ Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines
# This is just a matter of preference, and we can't change the interfaces # This is just a matter of preference, and we can't change the interfaces
# now anyways. # now anyways.
# #
# hicpp-avoid-c-arrays
# Alias for modernize-avoid-c-arrays.
#
# hicpp-invalid-access-moved # hicpp-invalid-access-moved
# Creates false positives. # Creates false positives.
# #
@ -61,13 +88,21 @@ Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines
# Too strict, sometimes calling vararg functions is necessary. # Too strict, sometimes calling vararg functions is necessary.
# #
# misc-macro-parentheses # misc-macro-parentheses
# False positive in the only place where it reports something and # Old name for bugprone-macro-parentheses.
# disabling locally doesn't work. #
# misc-non-private-member-variables-in-classes
# Reports this also for structs, which doesn't make any sense. There is
# an option "IgnoreClassesWithAllMemberVariablesBeingPublic" which should
# disable this, but it didn't work for me.
# #
# misc-unused-parameters # misc-unused-parameters
# Can't be fixed, because then Doxygen will complain. (In file # Can't be fixed, because then Doxygen will complain. (In file
# include/osmium/area/problem_reporter.hpp). # include/osmium/area/problem_reporter.hpp).
# #
# modernize-avoid-c-arrays
# Makes sense for some array, but especially for char arrays using
# std::array isn't a good solution.
#
# modernize-make-unique # modernize-make-unique
# This is a C++11 library and C++ doesn't have std::make_unique. # This is a C++11 library and C++ doesn't have std::make_unique.
# #
@ -75,6 +110,9 @@ Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines
# Readability isn't that much better, arguably worse because of the new # Readability isn't that much better, arguably worse because of the new
# syntax. # syntax.
# #
# modernize-use-trailing-return-type
# I am not quite that modern.
#
# readability-avoid-const-params-in-decls # readability-avoid-const-params-in-decls
# This is header only library, so the declaration and implementation are # This is header only library, so the declaration and implementation are
# often the same and we want to have the const in implementations. # often the same and we want to have the const in implementations.
@ -85,6 +123,9 @@ Checks: '*,-android-cloexec-*,-cert-dcl21-cpp,-cert-err58-cpp,-cppcoreguidelines
# readability-implicit-bool-conversion # readability-implicit-bool-conversion
# I don't think this makes the code more readable. # I don't think this makes the code more readable.
# #
# readability-magic-numbers
# Alias for cppcoreguidelines-avoid-magic-numbers.
#
#WarningsAsErrors: '*' #WarningsAsErrors: '*'
HeaderFilterRegex: '\/include\/osmium\/.*' HeaderFilterRegex: '\/include\/osmium\/.*'
... ...

View File

@ -4,12 +4,12 @@
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
os: linux
dist: xenial
language: generic language: generic
sudo: false
dist: trusty
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
cache: cache:
@ -32,190 +32,171 @@ addons_shortcuts:
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.5'] packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.5']
addons_clang38: &clang38 addons_clang38: &clang38
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.8']
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.8']
addons_clang39: &clang39 addons_clang39: &clang39
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.9']
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-3.9']
addons_clang40: &clang40
apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest', 'llvm-toolchain-trusty-4.0' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-4.0']
addons_clang50: &clang50 addons_clang50: &clang50
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest', 'llvm-toolchain-trusty-5.0' ] sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-5.0', 'g++-6', 'gcc-6'] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-5.0', 'g++-6', 'gcc-6']
addons_clang60: &clang60
apt:
sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-6.0', 'g++-6', 'gcc-6']
addons_clang7: &clang7
apt:
packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'clang-7' ]
addons_gcc48: &gcc48 addons_gcc48: &gcc48
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-4.8', 'gcc-4.8' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-4.8', 'gcc-4.8' ]
addons_gcc49: &gcc49 addons_gcc49: &gcc49
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-4.9', 'gcc-4.9' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-4.9', 'gcc-4.9' ]
addons_gcc5: &gcc5 addons_gcc5: &gcc5
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-5', 'gcc-5' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-5', 'gcc-5' ]
addons_gcc6: &gcc6 addons_gcc6: &gcc6
apt: apt:
sources: [ 'ubuntu-toolchain-r-test', 'boost-latest' ] sources: [ 'ubuntu-toolchain-r-test' ]
packages: [ 'libboost1.55-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-6', 'gcc-6' ] packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin', 'g++-6', 'gcc-6' ]
addons_gcc7: &gcc7
apt:
packages: [ 'libboost-all-dev', 'libgdal-dev', 'libproj-dev', 'libsparsehash-dev', 'spatialite-bin' ]
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
matrix: addons:
homebrew:
packages:
- cmake
- boost
- google-sparsehash
- gdal
update: true
#-----------------------------------------------------------------------------
jobs:
include: include:
# 1/ Linux Clang Builds # Linux Clang Builds
- os: linux
compiler: linux-clang35-release
env: CC='clang-3.5' CXX='clang++-3.5' BUILD_TYPE='Release'
addons: *clang35
- os: linux - os: linux
compiler: linux-clang35-dev compiler: linux-clang35-dev
env: CC='clang-3.5' CXX='clang++-3.5' BUILD_TYPE='Dev' env: CC='clang-3.5' CXX='clang++-3.5' BUILD_TYPE='Dev'
addons: *clang35 addons: *clang35
dist: trusty
- os: linux
compiler: linux-clang38-release
env: CC='clang-3.8' CXX='clang++-3.8' BUILD_TYPE='Release'
addons: *clang38
- os: linux - os: linux
compiler: linux-clang38-dev compiler: linux-clang38-dev
env: CC='clang-3.8' CXX='clang++-3.8' BUILD_TYPE='Dev' env: CC='clang-3.8' CXX='clang++-3.8' BUILD_TYPE='Dev'
addons: *clang38 addons: *clang38
- os: linux
compiler: linux-clang39-release
env: CC='clang-3.9' CXX='clang++-3.9' BUILD_TYPE='Release'
addons: *clang39
- os: linux - os: linux
compiler: linux-clang39-dev compiler: linux-clang39-dev
env: CC='clang-3.9' CXX='clang++-3.9' BUILD_TYPE='Dev' env: CC='clang-3.9' CXX='clang++-3.9' BUILD_TYPE='Dev'
addons: *clang39 addons: *clang39
- os: linux
compiler: linux-clang40-release
env: CC='clang-4.0' CXX='clang++-4.0' BUILD_TYPE='Release'
addons: *clang40
- os: linux
compiler: linux-clang40-dev
env: CC='clang-4.0' CXX='clang++-4.0' BUILD_TYPE='Dev'
addons: *clang40
- os: linux
compiler: linux-clang50-release
env: CC='clang-5.0' CXX='clang++-5.0' BUILD_TYPE='Release'
addons: *clang50
- os: linux - os: linux
compiler: linux-clang50-dev compiler: linux-clang50-dev
env: CC='clang-5.0' CXX='clang++-5.0' BUILD_TYPE='Dev' env: CC='clang-5.0' CXX='clang++-5.0' BUILD_TYPE='Dev'
addons: *clang50 addons: *clang50
# Disabled because it creates false-positives on the old travis systems
# - os: linux
# compiler: linux-clang50-debug
# env: CC='clang-5.0' CXX='clang++-5.0' BUILD_TYPE='Debug'
# CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
# LDFLAGS="-fsanitize=address,undefined,integer"
# # LSAN doesn't work on container-based system
# sudo: required
# addons: *clang50
# 2/ Linux GCC Builds
- os: linux - os: linux
compiler: linux-gcc48-release compiler: linux-clang60-dev
env: CC='gcc-4.8' CXX='g++-4.8' BUILD_TYPE='Release' env: CC='clang-6.0' CXX='clang++-6.0' BUILD_TYPE='Dev'
CXXFLAGS='-Wno-return-type' addons: *clang60
addons: *gcc48
- os: linux
compiler: linux-clang60-debug
env: CC='clang-6.0' CXX='clang++-6.0' BUILD_TYPE='Debug'
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
LDFLAGS="-fsanitize=address,undefined,integer"
addons: *clang60
- os: linux
compiler: linux-clang60-release
env: CC='clang-6.0' CXX='clang++-6.0' BUILD_TYPE='Release'
addons: *clang60
- os: linux
compiler: linux-clang7-debug
env: CC='clang-7' CXX='clang++-7' BUILD_TYPE='Debug'
CXXFLAGS="-fsanitize=address,undefined,integer -fno-sanitize-recover=all -fno-omit-frame-pointer"
LDFLAGS="-fsanitize=address,undefined,integer"
addons: *clang7
dist: bionic
- os: linux
compiler: linux-clang7-release
env: CC='clang-7' CXX='clang++-7' BUILD_TYPE='Release'
addons: *clang7
dist: bionic
# Linux GCC Builds
- os: linux - os: linux
compiler: linux-gcc48-dev compiler: linux-gcc48-dev
env: CC='gcc-4.8' CXX='g++-4.8' BUILD_TYPE='Dev' env: CC='gcc-4.8' CXX='g++-4.8' BUILD_TYPE='Dev'
CXXFLAGS='-Wno-return-type' CXXFLAGS='-Wno-return-type'
addons: *gcc48 addons: *gcc48
- os: linux
compiler: linux-gcc49-release
env: CC='gcc-4.9' CXX='g++-4.9' BUILD_TYPE='Release'
addons: *gcc49
- os: linux - os: linux
compiler: linux-gcc49-dev compiler: linux-gcc49-dev
env: CC='gcc-4.9' CXX='g++-4.9' BUILD_TYPE='Dev' env: CC='gcc-4.9' CXX='g++-4.9' BUILD_TYPE='Dev'
addons: *gcc49 addons: *gcc49
- os: linux
compiler: linux-gcc5-release
env: CC='gcc-5' CXX='g++-5' BUILD_TYPE='Release'
addons: *gcc5
- os: linux - os: linux
compiler: linux-gcc5-dev compiler: linux-gcc5-dev
env: CC='gcc-5' CXX='g++-5' BUILD_TYPE='Dev' env: CC='gcc-5' CXX='g++-5' BUILD_TYPE='Dev'
addons: *gcc5 addons: *gcc5
- os: linux
compiler: linux-gcc6-release
env: CC='gcc-6' CXX='g++-6' BUILD_TYPE='Release'
addons: *gcc6
- os: linux - os: linux
compiler: linux-gcc6-dev compiler: linux-gcc6-dev
env: CC='gcc-6' CXX='g++-6' BUILD_TYPE='Dev' env: CC='gcc-6' CXX='g++-6' BUILD_TYPE='Dev'
addons: *gcc6 addons: *gcc6
- os: linux - os: linux
compiler: linux-gcc6-coverage compiler: linux-gcc7-dev
env: CC='gcc-6' CXX='g++-6' BUILD_TYPE='Coverage' env: CC='gcc-7' CXX='g++-7' BUILD_TYPE='Dev'
addons: *gcc6 addons: *gcc7
dist: bionic
# 3/ OSX Clang Builds - os: linux
- os: osx compiler: linux-gcc7-coverage
osx_image: xcode6.4 env: CC='gcc-7' CXX='g++-7' BUILD_TYPE='Coverage'
compiler: xcode64-clang-release addons: *gcc7
env: CC='clang' CXX='clang++' BUILD_TYPE='Release' dist: bionic
- os: linux
compiler: linux-gcc7-release
env: CC='gcc-7' CXX='g++-7' BUILD_TYPE='Release'
addons: *gcc7
dist: bionic
# OSX Clang Builds
- os: osx - os: osx
osx_image: xcode6.4 osx_image: xcode9.4
compiler: xcode64-clang-dev compiler: xcode94-clang-dev
env: CC='clang' CXX='clang++' BUILD_TYPE='Dev' env: CC='clang' CXX='clang++' BUILD_TYPE='Dev'
- os: osx - os: osx
osx_image: xcode7 osx_image: xcode10.2
compiler: xcode7-clang-release compiler: xcode10-clang-dev
env: CC='clang' CXX='clang++' BUILD_TYPE='Release'
- os: osx
osx_image: xcode7
compiler: xcode7-clang-dev
env: CC='clang' CXX='clang++' BUILD_TYPE='Dev' env: CC='clang' CXX='clang++' BUILD_TYPE='Dev'
- os: osx - os: osx
osx_image: xcode8.3 osx_image: xcode11
compiler: xcode8-clang-release compiler: xcode11-clang-dev
env: CC='clang' CXX='clang++' BUILD_TYPE='Release' env: CC='clang' CXX='clang++' BUILD_TYPE='Dev'
- os: osx - os: osx
osx_image: xcode8.3 osx_image: xcode11
compiler: xcode8-clang-dev compiler: xcode11-clang-release
env: CC='clang' CXX='clang++' BUILD_TYPE='Dev' env: CC='clang' CXX='clang++' BUILD_TYPE='Release'
install: install:
- git clone --quiet --depth 1 https://github.com/mapbox/protozero.git ../protozero - git clone --quiet --depth 1 https://github.com/mapbox/protozero.git ../protozero
- |
if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
brew remove gdal
brew install cmake boost google-sparsehash gdal || true
fi
- cmake --version - cmake --version
before_script: before_script:

View File

@ -2,7 +2,7 @@
# #
# Configuration for YouCompleteMe Vim plugin # Configuration for YouCompleteMe Vim plugin
# #
# http://valloric.github.io/YouCompleteMe/ # https://valloric.github.io/YouCompleteMe/
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------

View File

@ -13,6 +13,215 @@ This project adheres to [Semantic Versioning](https://semver.org/).
### Fixed ### Fixed
## [2.15.6] - 2020-06-27
### Added
* Add `IdSetSmall::merge_sorted` function.
### Changed
* Little optimization for IdSetSmall: Don't add the same id twice in a row.
### Fixed
* Do not build areas with "recursion depth > 20". This happens when there
are complex multipolygon with many rings touching in single points. This
is a quick fix that hopefully keeps us going until we find a better
solution.
## [2.15.5] - 2020-04-21
### Added
* Additional constructor for `builder::attr::member_type(_string)` taking
char type making it even easier to generate test data.
* Allow single C string or `std::string` as argument for `builder::attr::_tag`.
Must contain key and value separated by the equal sign.
* New `builder::attr::_t()` function to set tags from comma-separated string.
* New `nwr_array` iterator.
* Support for the PROJ library has now been declared deprecated. The old
PROJ API (up to version PROJ 6) is currently still available, but will
be removed in a future version. Support for the new PROJ API will not be
in libosmium. See https://github.com/osmcode/osmium-proj for some code
that might help you if you need this.
### Changed
* Check how much space is available in file system before resizing memory
mapped file (not on Windows). This means we can, at least in some cases,
show an error message instead of crashing the program.
### Fixed
* Parsing coordinates in PBF files did not work correctly if an lat/lon
offset was specified (which almost never happens).
* Make OPL parser more strict: Attributes can only be specified once.
* Do not close stdout after writing OSM file to it.
## [2.15.4] - 2019-11-28
### Added
* Add osmium::Options::empty() for consistency with STL containers.
### Fixed
* Massive reduction of memory consumption in area assembly code. For some
very complex polygons memory usage can drop from multiple gigabytes to just
megabytes.
## [2.15.3] - 2019-09-16
### Added
* New header option "sorting" when reading and writing PBFs. If the header
option "sorting" is set to `Type_then_ID`, the optional header property
`Sort.Type_then_ID` is set on writing to PBF files. When reading PBF files
with this header property, the "sorting" header option is set accordingly.
### Fixed
* Do not propagate C++ exception through C code. We are using the Expat
XML parser, a C library. It calls callbacks in our code. When those
callbacks throw, the exception was propagated through the C code. This
did work in the tests, but that behaviour isn't guaranteed (C++
standard says it is implementation defined). This fixes it by catching
the exception and rethrowing it later.
## [2.15.2] - 2019-08-16
### Added
* Instead of handler classes, the `apply` function can now also take
lambdas (or objects from classes implementing `operator()`).
* Add swap, copy constructor and assignment operator to IdSetDense.
### Changed
* Enable use of the old proj API in proj version 6. This is a stopgap
solution until we find a better one.
* Better error messages when there is an error parsing a timestamp.
* Cleaned up a lot of code based on clang-tidy warnings.
* Ignore <bbox> or <bounds> subelement of <way> or <relation>. <bounds>
elements are created by Overpass API as subelements of ways or relations
when the "out bb" format is used. <bbox> subelements turn up in files
downloaded from http://download.openstreetmap.fr/replication . Libosmium
used to throw an error like "Unknown element in <way>: bbox". With this
commit, these subelements are ignored, ie. there is no error any more,
but the data is not read.
* Add swap, copy constructor and assignment operator to IdSetDense.
* Update included catch.hpp to 1.12.2.
* Retire use of `OSMIUM_NORETURN` macro. Use `[[noreturn]]` instead.
### Fixed
* Do not build areas with more than 100 locations where rings touch.
Places where rings touch are unusual for normal multipolygons and the
algorithm in libosmium that assembles multipolygons does not handle
them well. If there are too many touching points it becomes very slow.
This is not a problem for almost all multipolygons. As I am writing
this there are only three relations in the OSM database with more than
100 touching points, all of them rather weird boundaries in the US.
With this commit libosmium will simply ignore those areas to keep the
processing speed within reasonable bounds.
## [2.15.1] - 2019-02-26
### Added
* More tests.
* CMake config: also find clang-tidy-7.
### Changed
* Example and benchmark programs now don't crash with exceptions any more
but report them properly.
### Fixed
* Compile with NDEBUG in RelWithDebInfo mode.
* Correctly throw exception in `multimap::dump_as_list()`.
* Integer truncation on 32 bit systems in `MemoryUsage`.
* Exception specification on some functions.
* Forwarding references that might have hidden copy/move constructors.
## [2.15.0] - 2018-12-07
### Added
* Function `dump_as_array()` to dump sparse array indexes.
* Set the `xml_josm_upload` header option when reading XML files.
* New function `OSMObject::remove_tags()` marks tags on OSM objects as
removed.
* More tests.
### Changed
* When reading OSM files Libosmium now has less memory overhead, especially
when reading PBF files. This works by using more, but smaller buffers.
* The `TagsFilter` class is now based on the `TagsFilterBase` template
class which allows setting the result type. This allows the filter to
return more data depending on the rule that matched.
* Use enums for many constants instead of (static) const(expr) variables.
* Make `chunk_bits` in `IdSetDense` configurable.
* Hardcode `%lld` format instead of using `<cinttypes>` PRI macro.
* Update included gdalcpp to version 1.2.0.
### Fixed
* The gzip/bzip2 compression code was overhauled and is better tested now.
This fixes some bugs on Windows.
## [2.14.2] - 2018-07-23
### Fixed
* PBF reader and writer depended on byte order of system architecture.
* Removed an unreliable test that didn't work on some architectures.
## [2.14.1] - 2018-07-23
### Changed
* Libosmium now needs the newest Protozero version 1.6.3.
* Removes dependency on the utfcpp library for conversions between Unicode
code points and UTF-8. We have our own functions for this now. This also
gives us more control on where errors are thrown in this code.
* Add support for using the CRC32 implementation from the zlib library in
addition to the one from Boost. It is significantly faster and means we
have one less dependency, because zlib is needed anyway in almost all
programs using Osmium due to its use in the PBF format. Set macro
`OSMIUM_TEST_CRC_USE_BOOST` before compiling the tests, if you want to
run the tests with the boost library code, otherwise it will use the
zlib code. Note that to use this you have to change your software slightly,
see the documentation of the `CRC_zlib` class for details.
* Add a `clear_user()` function to OSMObject and Changeset which allows
removing the user name of an entity without re-creating it in a new buffer.
* In Osmium the 0 value of the Timestamp is used to denote the "invalid"
Timestamp, and its output using the `to_iso()` function is the empty
string. But this is the wrong output for OSM XML files, where a
timestamp that's not set should still be output as
1970-01-01T00:00:00Z. This version introduces a new `to_is_all()`
function which will do this and uses that function in the XML writer.
* Use `protozero::byteswap_inplace` instead of `htonl`/`ntohl`. Makes the
code simpler and also works on Windows.
* Marked `MultipolygonCollector` class as deprecated. Use the
`MultipolygonManager` class introduced in 2.13.0 instead.
* Lots of code cleanups especially around `assert`s. Libosmium checks out
clean with `clang-tidy` now. Some documentation updates.
### Fixed
* Fix compilation error when `fileno()` is a macro (as in OpenBSD 6.3).
* Make `Box` output consistent with the output of a single `Location`
and avoids problems with some locales.
## [2.14.0] - 2018-03-31 ## [2.14.0] - 2018-03-31
### Added ### Added
@ -823,7 +1032,16 @@ This project adheres to [Semantic Versioning](https://semver.org/).
Doxygen (up to version 1.8.8). This version contains a workaround to fix Doxygen (up to version 1.8.8). This version contains a workaround to fix
this. this.
[unreleased]: https://github.com/osmcode/libosmium/compare/v2.14.0...HEAD [unreleased]: https://github.com/osmcode/libosmium/compare/v2.15.6...HEAD
[2.15.6]: https://github.com/osmcode/libosmium/compare/v2.15.5...v2.15.6
[2.15.5]: https://github.com/osmcode/libosmium/compare/v2.15.4...v2.15.5
[2.15.4]: https://github.com/osmcode/libosmium/compare/v2.15.3...v2.15.4
[2.15.3]: https://github.com/osmcode/libosmium/compare/v2.15.2...v2.15.3
[2.15.2]: https://github.com/osmcode/libosmium/compare/v2.15.1...v2.15.2
[2.15.1]: https://github.com/osmcode/libosmium/compare/v2.15.0...v2.15.1
[2.15.0]: https://github.com/osmcode/libosmium/compare/v2.14.2...v2.15.0
[2.14.2]: https://github.com/osmcode/libosmium/compare/v2.14.1...v2.14.2
[2.14.1]: https://github.com/osmcode/libosmium/compare/v2.14.0...v2.14.1
[2.14.0]: https://github.com/osmcode/libosmium/compare/v2.13.1...v2.14.0 [2.14.0]: https://github.com/osmcode/libosmium/compare/v2.13.1...v2.14.0
[2.13.1]: https://github.com/osmcode/libosmium/compare/v2.13.0...v2.13.1 [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.13.0]: https://github.com/osmcode/libosmium/compare/v2.12.2...v2.13.0

View File

@ -12,20 +12,35 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# #
# Project version # Configurations
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
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.")
set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Coverage" set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev;Coverage"
CACHE STRING CACHE STRING
"List of available configuration types" "List of available configuration types"
FORCE) FORCE)
#-----------------------------------------------------------------------------
#
# Project version
#
#-----------------------------------------------------------------------------
project(libosmium) project(libosmium)
set(LIBOSMIUM_VERSION_MAJOR 2) set(LIBOSMIUM_VERSION_MAJOR 2)
set(LIBOSMIUM_VERSION_MINOR 14) set(LIBOSMIUM_VERSION_MINOR 15)
set(LIBOSMIUM_VERSION_PATCH 0) set(LIBOSMIUM_VERSION_PATCH 6)
set(LIBOSMIUM_VERSION set(LIBOSMIUM_VERSION
"${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}") "${LIBOSMIUM_VERSION_MAJOR}.${LIBOSMIUM_VERSION_MINOR}.${LIBOSMIUM_VERSION_PATCH}")
@ -62,7 +77,6 @@ option(BUILD_BENCHMARKS "compile benchmark programs" ${dev_build})
option(BUILD_DATA_TESTS "compile data tests, please run them with ctest" ${data_test_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_GDALCPP "also install gdalcpp headers" OFF)
option(INSTALL_UTFCPP "also install utfcpp headers" OFF)
option(WITH_PROFILING "add flags needed for profiling" OFF) option(WITH_PROFILING "add flags needed for profiling" OFF)
@ -101,14 +115,6 @@ endif()
# set(extra_coverage_flags_ "-fkeep-inline-functions") # set(extra_coverage_flags_ "-fkeep-inline-functions")
#endif() #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(CMAKE_BUILD_TYPE STREQUAL "Coverage")
if(BUILD_EXAMPLES OR BUILD_HEADERS OR BUILD_BENCHMARKS) if(BUILD_EXAMPLES OR BUILD_HEADERS OR BUILD_BENCHMARKS)
message(WARNING "Coverage builds don't work for anything but the tests") message(WARNING "Coverage builds don't work for anything but the tests")
@ -200,11 +206,13 @@ endif()
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
if(MSVC) if(MSVC)
set(USUAL_COMPILE_OPTIONS "/Ox") set(DEV_COMPILE_OPTIONS "/Ox")
set(RWD_COMPILE_OPTIONS "/Ox /DNDEBUG")
# do not show warnings caused by missing .pdb files for libraries # do not show warnings caused by missing .pdb files for libraries
set(USUAL_LINK_OPTIONS "/debug /ignore:4099") set(USUAL_LINK_OPTIONS "/debug /ignore:4099")
else() else()
set(USUAL_COMPILE_OPTIONS "-O3 -g") set(DEV_COMPILE_OPTIONS "-O3 -g")
set(RWD_COMPILE_OPTIONS "-O3 -g -DNDEBUG")
set(USUAL_LINK_OPTIONS "") set(USUAL_LINK_OPTIONS "")
endif() endif()
@ -212,7 +220,7 @@ if(WIN32)
add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32) add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32)
endif() endif()
set(CMAKE_CXX_FLAGS_DEV "${USUAL_COMPILE_OPTIONS}" set(CMAKE_CXX_FLAGS_DEV "${DEV_COMPILE_OPTIONS}"
CACHE STRING "Flags used by the compiler during developer builds." CACHE STRING "Flags used by the compiler during developer builds."
FORCE) FORCE)
@ -224,7 +232,7 @@ mark_as_advanced(
CMAKE_EXE_LINKER_FLAGS_DEV CMAKE_EXE_LINKER_FLAGS_DEV
) )
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${USUAL_COMPILE_OPTIONS}" set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${RWD_COMPILE_OPTIONS}"
CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds." CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds."
FORCE) FORCE)
@ -397,7 +405,7 @@ if(BUILD_HEADERS)
# Create a dummy .cpp file that includes the header file we want to # Create a dummy .cpp file that includes the header file we want to
# check. # check.
set(DUMMYCPP ${CMAKE_BINARY_DIR}/header_check/${libname}.cpp) set(DUMMYCPP ${CMAKE_BINARY_DIR}/header_check/${libname}.cpp)
file(WRITE ${DUMMYCPP} "#include <${hpp}> // IWYU pragma: keep\n") file(WRITE ${DUMMYCPP} "#define OSMIUM_UTIL_COMPATIBILITY_HPP\n#define OSMIUM_DEPRECATED\n#include <${hpp}> // IWYU pragma: keep\n")
# There is no way in CMake to just compile but not link a C++ file, # There is no way in CMake to just compile but not link a C++ file,
# so we pretend to build a library here. # so we pretend to build a library here.
@ -416,7 +424,7 @@ endif()
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
message(STATUS "Looking for clang-tidy") message(STATUS "Looking for clang-tidy")
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0 clang-tidy-5.0) find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-10 clang-tidy-9 clang-tidy-8 clang-tidy-7 clang-tidy-7.0 clang-tidy-6.0 clang-tidy-5.0)
if(CLANG_TIDY) if(CLANG_TIDY)
message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}") message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}")
@ -459,6 +467,7 @@ if(CLANG_TIDY)
add_custom_target(clang-tidy add_custom_target(clang-tidy
${CLANG_TIDY} ${CLANG_TIDY}
-p ${CMAKE_BINARY_DIR} -p ${CMAKE_BINARY_DIR}
"-extra-arg=-Wno-#pragma-messages"
${CT_CHECK_FILES} ${CT_CHECK_FILES}
) )
else() else()
@ -480,11 +489,6 @@ if(INSTALL_GDALCPP)
install(FILES include/gdalcpp.hpp DESTINATION include) install(FILES include/gdalcpp.hpp DESTINATION include)
endif() endif()
if(INSTALL_UTFCPP)
install(FILES include/utf8.h DESTINATION include)
install(DIRECTORY include/utf8 DESTINATION include)
endif()
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
# #

View File

@ -1,27 +0,0 @@
==== 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.

View File

@ -1,17 +1,17 @@
# Libosmium # Libosmium
http://osmcode.org/libosmium https://osmcode.org/libosmium
A fast and flexible C++ library for working with OpenStreetMap data. A fast and flexible C++ library for working with OpenStreetMap data.
Libosmium works on Linux, Mac OSX and Windows. Libosmium works on Linux, Mac OSX and Windows.
[![Travis Build Status](https://secure.travis-ci.org/osmcode/libosmium.svg)](https://travis-ci.org/osmcode/libosmium) [![Travis Build Status](https://secure.travis-ci.org/osmcode/libosmium.svg)](https://travis-ci.org/osmcode/libosmium)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/osmcode/libosmium?svg=true)](https://ci.appveyor.com/project/Mapbox/libosmium) [![Appveyor Build status](https://ci.appveyor.com/api/projects/status/yy099a4vxcb604rn/branch/master?svg=true)](https://ci.appveyor.com/project/lonvia/libosmium-eq41p/branch/master)
[![Coverage Status](https://codecov.io/gh/osmcode/libosmium/branch/master/graph/badge.svg)](https://codecov.io/gh/osmcode/libosmium) [![Coverage Status](https://codecov.io/gh/osmcode/libosmium/branch/master/graph/badge.svg)](https://codecov.io/gh/osmcode/libosmium)
[![Packaging status](https://repology.org/badge/tiny-repos/libosmium.svg)](https://repology.org/metapackage/libosmium) [![Packaging status](https://repology.org/badge/tiny-repos/libosmium.svg)](https://repology.org/metapackage/libosmium)
Please see the [Libosmium manual](http://osmcode.org/libosmium/manual.html) Please see the [Libosmium manual](https://osmcode.org/libosmium/manual.html)
for more details than this README can provide. for more details than this README can provide.
@ -26,13 +26,12 @@ different libraries. You DO NOT NEED to install all of them, just install those
you need for your programs. you need for your programs.
For details see the [list of For details see the [list of
dependencies](http://osmcode.org/libosmium/manual.html#dependencies) in the dependencies](https://osmcode.org/libosmium/manual.html#dependencies) in the
manual. manual.
The following external (header-only) libraries are included in the libosmium The following external (header-only) libraries are included in the libosmium
repository: repository:
* [gdalcpp](https://github.com/joto/gdalcpp) * [gdalcpp](https://github.com/joto/gdalcpp)
* [utfcpp](http://utfcpp.sourceforge.net/)
Note that [protozero](https://github.com/mapbox/protozero) was included in Note that [protozero](https://github.com/mapbox/protozero) was included in
earlier versions of libosmium, but isn't any more. earlier versions of libosmium, but isn't any more.
@ -69,8 +68,8 @@ cmake:
This will build the examples and tests. Call `ctest` to run the tests. This will build the examples and tests. Call `ctest` to run the tests.
For more detals see the For more details see the
[Building Libosmium](http://osmcode.org/libosmium/manual.html#building-libosmium) [Building Libosmium](https://osmcode.org/libosmium/manual.html#building-libosmium)
chapter in the manual. chapter in the manual.
@ -85,7 +84,7 @@ git submodule update --init
This will enable additional tests. This will enable additional tests.
See the See the
[Libosmium Manual](http://osmcode.org/libosmium/manual.html#running-tests) [Libosmium Manual](https://osmcode.org/libosmium/manual.html#running-tests)
for instructions. for instructions.
@ -93,7 +92,7 @@ for instructions.
If you have been using the old version of Osmium at If you have been using the old version of Osmium at
https://github.com/joto/osmium you might want to read about the [changes 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). needed](https://osmcode.org/libosmium/manual.html#changes-from-old-versions-of-osmium).
## License ## License

View File

@ -4,25 +4,28 @@
# #
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
environment: os: Visual Studio 2017
matrix:
- config: MSYS2 platform: x64
autocrlf: true
- config: Debug
autocrlf: true
- config: Release
autocrlf: true
- config: Debug
autocrlf: false
- config: Release
autocrlf: false
clone_depth: 1 clone_depth: 1
# Operating system (build VM template) #-----------------------------------------------------------------------------
os: Visual Studio 2015
platform: x64 environment:
matrix:
- config: Debug
autocrlf: true
- config: Release
autocrlf: true
- config: Debug
autocrlf: false
- config: Release
autocrlf: false
- config: MSYS2
autocrlf: true
#-----------------------------------------------------------------------------
# scripts that are called at very beginning, before repo cloning # scripts that are called at very beginning, before repo cloning
init: init:

View File

@ -39,16 +39,21 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string input_filename{argv[1]};
osmium::io::Reader reader{input_filename}; osmium::io::Reader reader{input_filename};
CountHandler handler; CountHandler handler;
osmium::apply(reader, handler); osmium::apply(reader, handler);
reader.close(); reader.close();
std::cout << "Nodes: " << handler.nodes << '\n'; std::cout << "Nodes: " << handler.nodes << '\n';
std::cout << "Ways: " << handler.ways << '\n'; std::cout << "Ways: " << handler.ways << '\n';
std::cout << "Relations: " << handler.relations << '\n'; std::cout << "Relations: " << handler.relations << '\n';
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -42,14 +42,19 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string input_filename{argv[1]};
osmium::io::Reader reader{input_filename}; osmium::io::Reader reader{input_filename};
CountHandler handler; CountHandler handler;
osmium::apply(reader, handler); osmium::apply(reader, handler);
reader.close(); reader.close();
std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << '\n'; std::cout << "r_all=" << handler.all << " r_counter=" << handler.counter << '\n';
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -24,17 +24,22 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string location_store{argv[2]}; const std::string input_filename{argv[1]};
const std::string location_store{argv[2]};
osmium::io::Reader reader{input_filename}; osmium::io::Reader reader{input_filename};
const auto& map_factory = osmium::index::MapFactory<osmium::unsigned_object_id_type, osmium::Location>::instance(); 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); std::unique_ptr<index_type> index = map_factory.create_map(location_store);
location_handler_type location_handler{*index}; location_handler_type location_handler{*index};
location_handler.ignore_errors(); location_handler.ignore_errors();
osmium::apply(reader, location_handler); osmium::apply(reader, location_handler);
reader.close(); reader.close();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -31,12 +31,17 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string input_filename{argv[1]};
osmium::io::Reader reader{input_filename}; osmium::io::Reader reader{input_filename};
GeomHandler handler; GeomHandler handler;
osmium::apply(reader, handler); osmium::apply(reader, handler);
reader.close(); reader.close();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -44,101 +44,106 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string input_filename{argv[1]};
osmium::memory::Buffer buffer{osmium::io::read_file(input_filename)}; 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& 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 auto buffer_size = buffer.committed() / (1024 * 1024); // buffer size in MBytes
const int runs = std::max(10, static_cast<int>(5000ull / buffer_size)); 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 << "input: filename=" << input_filename << " buffer_size=" << buffer_size << "MBytes\n";
std::cout << "runs: " << runs << "\n"; std::cout << "runs: " << runs << "\n";
double static_min = std::numeric_limits<double>::max(); double static_min = std::numeric_limits<double>::max();
double static_sum = 0; double static_sum = 0;
double static_max = 0; double static_max = 0;
double dynamic_min = std::numeric_limits<double>::max(); double dynamic_min = std::numeric_limits<double>::max();
double dynamic_sum = 0; double dynamic_sum = 0;
double dynamic_max = 0; double dynamic_max = 0;
for (int i = 0; i < runs; ++i) { for (int i = 0; i < runs; ++i) {
{ {
// static index // static index
osmium::memory::Buffer tmp_buffer{buffer.committed()}; osmium::memory::Buffer tmp_buffer{buffer.committed()};
for (const auto& item : buffer) { for (const auto& item : buffer) {
tmp_buffer.add_item(item); tmp_buffer.add_item(item);
tmp_buffer.commit(); 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;
} }
static_index_type static_index; {
static_location_handler_type static_location_handler{static_index}; // dynamic index
osmium::memory::Buffer tmp_buffer{buffer.committed()};
for (const auto& item : buffer) {
tmp_buffer.add_item(item);
tmp_buffer.commit();
}
const auto start = std::chrono::steady_clock::now(); std::unique_ptr<dynamic_index_type> index = map_factory.create_map(location_store);
osmium::apply(tmp_buffer, static_location_handler); dynamic_location_handler_type dynamic_location_handler{*index};
const auto end = std::chrono::steady_clock::now(); dynamic_location_handler.ignore_errors();
const double duration = std::chrono::duration<double, std::milli>(end - start).count(); const auto start = std::chrono::steady_clock::now();
osmium::apply(tmp_buffer, dynamic_location_handler);
const auto end = std::chrono::steady_clock::now();
if (duration < static_min) { const double duration = std::chrono::duration<double, std::milli>(end - start).count();
static_min = duration;
if (duration < dynamic_min) {
dynamic_min = duration;
}
if (duration > dynamic_max) {
dynamic_max = duration;
}
dynamic_sum += duration;
} }
if (duration > static_max) {
static_max = duration;
}
static_sum += duration;
} }
{ const double static_avg = static_sum / runs;
// dynamic index const double dynamic_avg = dynamic_sum / runs;
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); std::cout << "static min=" << static_min << "ms avg=" << static_avg << "ms max=" << static_max << "ms\n";
dynamic_location_handler_type dynamic_location_handler{*index}; std::cout << "dynamic min=" << dynamic_min << "ms avg=" << dynamic_avg << "ms max=" << dynamic_max << "ms\n";
dynamic_location_handler.ignore_errors();
const auto start = std::chrono::steady_clock::now(); const double rfactor = 100.0;
osmium::apply(tmp_buffer, dynamic_location_handler); const double diff_min = std::round((dynamic_min - static_min) * rfactor) / rfactor;
const auto end = std::chrono::steady_clock::now(); 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 duration = std::chrono::duration<double, std::milli>(end - start).count(); 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;
if (duration < dynamic_min) { std::cout << "difference:";
dynamic_min = duration; std::cout << " min=" << diff_min << "ms (" << percent_min << "%)";
} std::cout << " avg=" << diff_avg << "ms (" << percent_avg << "%)";
if (duration > dynamic_max) { std::cout << " max=" << diff_max << "ms (" << percent_max << "%)\n";
dynamic_max = duration; } catch (const std::exception& e) {
} std::cerr << e.what() << '\n';
dynamic_sum += duration; std::exit(1);
}
} }
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";
} }

View File

@ -17,19 +17,24 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
std::string input_filename{argv[1]}; try {
std::string output_filename{argv[2]}; std::string input_filename{argv[1]};
std::string output_filename{argv[2]};
osmium::io::Reader reader{input_filename}; osmium::io::Reader reader{input_filename};
osmium::io::File output_file{output_filename, "pbf"}; osmium::io::File output_file{output_filename, "pbf"};
osmium::io::Header header; osmium::io::Header header;
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow}; osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
while (osmium::memory::Buffer buffer = reader.read()) { while (osmium::memory::Buffer buffer = reader.read()) { // NOLINT(bugprone-use-after-move) Bug in clang-tidy https://bugs.llvm.org/show_bug.cgi?id=36516
writer(std::move(buffer)); writer(std::move(buffer));
}
writer.close();
reader.close();
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
std::exit(1);
} }
writer.close();
reader.close();
} }

View File

@ -46,7 +46,7 @@ SET CMAKE_CMD=cmake .. -LA -G "Visual Studio 14 Win64" ^
-DOsmium_DEBUG=TRUE ^ -DOsmium_DEBUG=TRUE ^
-DCMAKE_BUILD_TYPE=%config% ^ -DCMAKE_BUILD_TYPE=%config% ^
-DBUILD_HEADERS=OFF ^ -DBUILD_HEADERS=OFF ^
-DBOOST_ROOT=C:/Libraries/boost_1_63_0 ^ -DBOOST_ROOT=C:/Libraries/boost_1_67_0 ^
-DZLIB_INCLUDE_DIR=C:/projects/zlib-vc140-static-64.1.2.11/lib/native/include ^ -DZLIB_INCLUDE_DIR=C:/projects/zlib-vc140-static-64.1.2.11/lib/native/include ^
-DZLIB_LIBRARY=C:/projects/zlib-vc140-static-64.1.2.11/lib/native/libs/x64/static/%config%/zlibstatic.lib ^ -DZLIB_LIBRARY=C:/projects/zlib-vc140-static-64.1.2.11/lib/native/libs/x64/static/%config%/zlibstatic.lib ^
-DEXPAT_INCLUDE_DIR=C:/projects/expat.v140.2.2.5/build/native/include ^ -DEXPAT_INCLUDE_DIR=C:/projects/expat.v140.2.2.5/build/native/include ^
@ -68,7 +68,7 @@ msbuild libosmium.sln ^
/p:PlatformToolset=v140 %avlogger% /p:PlatformToolset=v140 %avlogger%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR IF %ERRORLEVEL% NEQ 0 GOTO ERROR
ctest --output-on-failure -C %config% -E testdata-overview ctest --output-on-failure -C %config%
IF %ERRORLEVEL% NEQ 0 GOTO ERROR IF %ERRORLEVEL% NEQ 0 GOTO ERROR
GOTO DONE GOTO DONE

View File

@ -13,6 +13,9 @@ bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-g
bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-postgresql mingw-w64-x86_64-netcdf mingw-w64-x86_64-crypto++" bash -lc "pacman -S --needed --noconfirm mingw-w64-x86_64-postgresql mingw-w64-x86_64-netcdf mingw-w64-x86_64-crypto++"
call C:\msys64\mingw64\bin\gem.cmd install json call C:\msys64\mingw64\bin\gem.cmd install json
REM Workaround for problem with spatialite (see https://github.com/osmcode/libosmium/issues/262)
copy /y C:\msys64\mingw64\bin\libreadline8.dll C:\msys64\mingw64\bin\libreadline7.dll
echo "Setting PROJ_LIB variable for correct PROJ.4 working" echo "Setting PROJ_LIB variable for correct PROJ.4 working"
set PROJ_LIB=c:\msys64\mingw64\share\proj set PROJ_LIB=c:\msys64\mingw64\share\proj

View File

@ -71,6 +71,9 @@ find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp
# Check libosmium version number # Check libosmium version number
if(Osmium_FIND_VERSION) if(Osmium_FIND_VERSION)
if(NOT EXISTS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp")
message(FATAL_ERROR "Missing ${OSMIUM_INCLUDE_DIR}/osmium/version.hpp. Either your libosmium version is too old, or libosmium wasn't found in the place you said.")
endif()
file(STRINGS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp" _libosmium_version_define REGEX "#define LIBOSMIUM_VERSION_STRING") 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.]+)\"") if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"")
set(_libosmium_version "${CMAKE_MATCH_1}") set(_libosmium_version "${CMAKE_MATCH_1}")
@ -111,7 +114,7 @@ endif()
if(Osmium_USE_PBF) if(Osmium_USE_PBF)
find_package(ZLIB) find_package(ZLIB)
find_package(Threads) find_package(Threads)
find_package(Protozero 1.5.1) find_package(Protozero 1.6.3)
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR) list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR)
if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_FOUND) if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_FOUND)
@ -324,7 +327,7 @@ if(MSVC)
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS)
endif() endif()
if(APPLE) if(APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# following only available from cmake 2.8.12: # following only available from cmake 2.8.12:
# add_compile_options(-stdlib=libc++) # add_compile_options(-stdlib=libc++)
# so using this instead: # so using this instead:

View File

@ -4,7 +4,7 @@ data.
This is the API documentation that was automatically created from the This is the API documentation that was automatically created from the
source code. For more information about the Osmium Library see source code. For more information about the Osmium Library see
http://osmcode.org/libosmium . https://osmcode.org/libosmium .
Osmium is free software and available under the Boost Software License. Osmium is free software and available under the Boost Software License.
The source code is available at https://github.com/osmcode/libosmium . The source code is available at https://github.com/osmcode/libosmium .

View File

@ -58,12 +58,12 @@ using location_handler_type = osmium::handler::NodeLocationsForWays<index_type>;
class AmenityHandler : public osmium::handler::Handler { class AmenityHandler : public osmium::handler::Handler {
// Print info about one amenity to stdout. // Print info about one amenity to stdout.
void print_amenity(const char* type, const char* name, const osmium::geom::Coordinates& c) { static 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 : ""); std::printf("%8.4f,%8.4f %-15s %s\n", c.x, c.y, type, name ? name : "");
} }
// Calculate the center point of a NodeRefList. // Calculate the center point of a NodeRefList.
osmium::geom::Coordinates calc_center(const osmium::NodeRefList& nr_list) { static osmium::geom::Coordinates calc_center(const osmium::NodeRefList& nr_list) {
// Coordinates simply store an X and Y coordinate pair as doubles. // Coordinates simply store an X and Y coordinate pair as doubles.
// (Unlike osmium::Location which stores them more efficiently as // (Unlike osmium::Location which stores them more efficiently as
// 32 bit integers.) Use Coordinates when you want to do calculations // 32 bit integers.) Use Coordinates when you want to do calculations
@ -113,59 +113,65 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// The input file try {
const osmium::io::File input_file{argv[1]}; // The input file
const osmium::io::File input_file{argv[1]};
// Configuration for the multipolygon assembler. We disable the option to // Configuration for the multipolygon assembler. We disable the option to
// create empty areas when invalid multipolygons are encountered. This // create empty areas when invalid multipolygons are encountered. This
// means areas created have a valid geometry and invalid multipolygons // means areas created have a valid geometry and invalid multipolygons
// are simply ignored. // are simply ignored.
osmium::area::Assembler::config_type assembler_config; osmium::area::Assembler::config_type assembler_config;
assembler_config.create_empty_areas = false; assembler_config.create_empty_areas = false;
// Initialize the MultipolygonManager. Its job is to collect all // Initialize the MultipolygonManager. Its job is to collect all
// relations and member ways needed for each area. It then calls an // relations and member ways needed for each area. It then calls an
// instance of the osmium::area::Assembler class (with the given config) // instance of the osmium::area::Assembler class (with the given config)
// to actually assemble one area. // to actually assemble one area.
osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config}; osmium::area::MultipolygonManager<osmium::area::Assembler> mp_manager{assembler_config};
// We read the input file twice. In the first pass, only relations are // We read the input file twice. In the first pass, only relations are
// read and fed into the multipolygon manager. // read and fed into the multipolygon manager.
std::cerr << "Pass 1...\n"; std::cerr << "Pass 1...\n";
osmium::relations::read_relations(input_file, mp_manager); osmium::relations::read_relations(input_file, mp_manager);
std::cerr << "Pass 1 done\n"; std::cerr << "Pass 1 done\n";
// The index storing all node locations. // The index storing all node locations.
index_type index; index_type index;
// The handler that stores all node locations in the index and adds them // The handler that stores all node locations in the index and adds them
// to the ways. // to the ways.
location_handler_type location_handler{index}; location_handler_type location_handler{index};
// If a location is not available in the index, we ignore it. It might // 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 // not be needed (if it is not part of a multipolygon relation), so why
// create an error? // create an error?
location_handler.ignore_errors(); location_handler.ignore_errors();
// Create our handler. // Create our handler.
AmenityHandler data_handler; AmenityHandler data_handler;
// On the second pass we read all objects and run them first through the // On the second pass we read all objects and run them first through the
// node location handler and then the multipolygon manager. The manager // node location handler and then the multipolygon manager. The manager
// will put the areas it has created into the "buffer" which are then // will put the areas it has created into the "buffer" which are then
// fed through our handler. // fed through our handler.
// //
// The read_meta::no option disables reading of meta data (such as version // The read_meta::no option disables reading of meta data (such as version
// numbers, timestamps, etc.) which are not needed in this case. Disabling // numbers, timestamps, etc.) which are not needed in this case. Disabling
// this can speed up your program. // this can speed up your program.
std::cerr << "Pass 2...\n"; std::cerr << "Pass 2...\n";
osmium::io::Reader reader{input_file, osmium::io::read_meta::no}; 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(reader, location_handler, data_handler, mp_manager.handler([&data_handler](const osmium::memory::Buffer& area_buffer) {
osmium::apply(area_buffer, data_handler); osmium::apply(area_buffer, data_handler);
})); }));
reader.close(); reader.close();
std::cerr << "Pass 2 done\n"; std::cerr << "Pass 2 done\n";
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -107,92 +107,98 @@ int main(int argc, char* argv[]) {
print_usage(argv[0]); print_usage(argv[0]);
} }
// Initialize an empty DynamicHandler. Later it will be associated try {
// with one of the handlers. You can think of the DynamicHandler as // Initialize an empty DynamicHandler. Later it will be associated
// a kind of "variant handler" or a "pointer handler" pointing to the // with one of the handlers. You can think of the DynamicHandler as
// real handler. // a kind of "variant handler" or a "pointer handler" pointing to the
osmium::handler::DynamicHandler handler; // real handler.
osmium::handler::DynamicHandler handler;
if (!std::strcmp(argv[1], "-w") || !std::strcmp(argv[1], "--dump-wkt")) { if (!std::strcmp(argv[1], "-w") || !std::strcmp(argv[1], "--dump-wkt")) {
handler.set<WKTDump>(); handler.set<WKTDump>();
} else if (!std::strcmp(argv[1], "-o") || !std::strcmp(argv[1], "--dump-objects")) { } else if (!std::strcmp(argv[1], "-o") || !std::strcmp(argv[1], "--dump-objects")) {
handler.set<osmium::handler::Dump>(std::cout); handler.set<osmium::handler::Dump>(std::cout);
} else { } else {
print_usage(argv[0]); print_usage(argv[0]);
}
osmium::io::File input_file{argv[2]};
// 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";
osmium::io::File input_file{argv[2]};
// 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";
}
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
} }
} }

View File

@ -66,7 +66,7 @@ class RewriteHandler : public osmium::handler::Handler {
// Copy all tags with two changes: // Copy all tags with two changes:
// * Do not copy "created_by" tags // * Do not copy "created_by" tags
// * Change "landuse=forest" into "natural=wood" // * Change "landuse=forest" into "natural=wood"
void copy_tags(osmium::builder::Builder& parent, const osmium::TagList& tags) { static void copy_tags(osmium::builder::Builder& parent, const osmium::TagList& tags) {
// The TagListBuilder is used to create a list of tags. The parameter // 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 // to create it is a reference to the builder of the object that
@ -196,7 +196,7 @@ int main(int argc, char* argv[]) {
reader.close(); reader.close();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception. // All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << "\n"; std::cerr << e.what() << '\n';
std::exit(1); std::exit(1);
} }
} }

View File

@ -135,7 +135,7 @@ int main(int argc, char* argv[]) {
// a time. This is much easier and faster than copying each object // 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 // in the file. Buffers are moved around, so there is no cost for
// copying in memory. // copying in memory.
while (osmium::memory::Buffer buffer = reader.read()) { while (osmium::memory::Buffer buffer = reader.read()) { // NOLINT(bugprone-use-after-move) Bug in clang-tidy https://bugs.llvm.org/show_bug.cgi?id=36516
writer(std::move(buffer)); writer(std::move(buffer));
} }
@ -147,7 +147,7 @@ int main(int argc, char* argv[]) {
reader.close(); reader.close();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception. // All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << "\n"; std::cerr << e.what() << '\n';
std::exit(1); std::exit(1);
} }
} }

View File

@ -66,30 +66,36 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// The Reader is initialized here with an osmium::io::File, but could try {
// also be directly initialized with a file name. // The Reader is initialized here with an osmium::io::File, but could
osmium::io::File input_file{argv[1]}; // also be directly initialized with a file name.
osmium::io::Reader reader{input_file}; 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 // Create an instance of our own CountHandler and push the data from the
// input file through it. // input file through it.
CountHandler handler; CountHandler handler;
osmium::apply(reader, handler); osmium::apply(reader, handler);
// You do not have to close the Reader explicitly, but because the // You do not have to close the Reader explicitly, but because the
// destructor can't throw, you will not see any errors otherwise. // destructor can't throw, you will not see any errors otherwise.
reader.close(); reader.close();
std::cout << "Nodes: " << handler.nodes << "\n"; std::cout << "Nodes: " << handler.nodes << "\n";
std::cout << "Ways: " << handler.ways << "\n"; std::cout << "Ways: " << handler.ways << "\n";
std::cout << "Relations: " << handler.relations << "\n"; std::cout << "Relations: " << handler.relations << "\n";
// Because of the huge amount of OSM data, some Osmium-based programs // 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 // (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. // memore usage is often useful and can be done easily with this class.
// (Currently only works on Linux, not OSX and Windows.) // (Currently only works on Linux, not OSX and Windows.)
osmium::MemoryUsage memory; osmium::MemoryUsage memory;
std::cout << "\nMemory used: " << memory.peak() << " MBytes\n"; std::cout << "\nMemory used: " << memory.peak() << " MBytes\n";
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -93,7 +93,7 @@ int main(int argc, char* argv[]) {
writer.close(); writer.close();
} catch (const std::exception& e) { } catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception. // All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << "\n"; std::cerr << e.what() << '\n';
std::exit(1); std::exit(1);
} }
} }

View File

@ -37,48 +37,54 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// Default is all entity types: nodes, ways, relations, and changesets try {
osmium::osm_entity_bits::type read_types = osmium::osm_entity_bits::all; // 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. // Get entity types from command line if there is a 2nd argument.
if (argc == 3) { if (argc == 3) {
read_types = osmium::osm_entity_bits::nothing; read_types = osmium::osm_entity_bits::nothing;
std::string types = argv[2]; std::string types = argv[2];
if (types.find('n') != std::string::npos) { if (types.find('n') != std::string::npos) {
read_types |= osmium::osm_entity_bits::node; 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;
}
} }
if (types.find('w') != std::string::npos) {
read_types |= osmium::osm_entity_bits::way; // Initialize Reader with file name and the types of entities we want to
} // read.
if (types.find('r') != std::string::npos) { osmium::io::Reader reader{argv[1], read_types};
read_types |= osmium::osm_entity_bits::relation;
} // The file header can contain metadata such as the program that generated
if (types.find('c') != std::string::npos) { // the file and the bounding box of the data.
read_types |= osmium::osm_entity_bits::changeset; 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();
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
} }
// 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();
} }

View File

@ -105,92 +105,98 @@ int main(int argc, char* argv[]) {
std::exit(2); std::exit(2);
} }
const std::string input_file_name{argv[1]}; try {
const std::string output_dir{argv[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. // Create output directory. Ignore the error if it already exists.
#ifndef _WIN32 #ifndef _WIN32
const int result = ::mkdir(output_dir.c_str(), 0777); const int result = ::mkdir(output_dir.c_str(), 0777);
#else #else
const int result = mkdir(output_dir.c_str()); const int result = mkdir(output_dir.c_str());
#endif #endif
if (result == -1 && errno != EEXIST) { if (result == -1 && errno != EEXIST) {
std::cerr << "Problem creating directory '" << output_dir << "': " << std::strerror(errno) << "\n"; std::cerr << "Problem creating directory '" << output_dir << "': " << std::strerror(errno) << "\n";
std::exit(2); std::exit(2);
} }
// Create the output file which will contain our serialized OSM data // Create the output file which will contain our serialized OSM data
const std::string data_file{output_dir + "/data.osm.ser"}; 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); // NOLINT(hicpp-signed-bitwise) const int data_fd = ::open(data_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666); // NOLINT(hicpp-signed-bitwise)
if (data_fd < 0) { if (data_fd < 0) {
std::cerr << "Can't open data file '" << data_file << "': " << std::strerror(errno) << "\n"; std::cerr << "Can't open data file '" << data_file << "': " << std::strerror(errno) << "\n";
std::exit(2); std::exit(2);
} }
#ifdef _WIN32 #ifdef _WIN32
_setmode(data_fd, _O_BINARY); _setmode(data_fd, _O_BINARY);
#endif #endif
// These indexes store the offset in the data file where each node, way, // These indexes store the offset in the data file where each node, way,
// or relation is stored. // or relation is stored.
offset_index_type node_index; offset_index_type node_index;
offset_index_type way_index; offset_index_type way_index;
offset_index_type relation_index; offset_index_type relation_index;
// This handler will dump the internal data to disk using the given file // This handler will dump the internal data to disk using the given file
// descriptor while updating the indexes. // descriptor while updating the indexes.
osmium::handler::DiskStore disk_store_handler{data_fd, node_index, way_index, relation_index}; 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 // 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 // containing this node, and from node/way/relation ids to the ids of the
// relations containing those objects. // relations containing those objects.
map_type map_node2way; map_type map_node2way;
map_type map_node2relation; map_type map_node2relation;
map_type map_way2relation; map_type map_way2relation;
map_type map_relation2relation; map_type map_relation2relation;
// This handler will update the map indexes. // This handler will update the map indexes.
osmium::handler::ObjectRelations object_relations_handler{map_node2way, map_node2relation, map_way2relation, map_relation2relation}; osmium::handler::ObjectRelations object_relations_handler{map_node2way, map_node2relation, map_way2relation, map_relation2relation};
// Read OSM data buffer by buffer. // Read OSM data buffer by buffer.
osmium::io::Reader reader{input_file_name}; osmium::io::Reader reader{input_file_name};
while (osmium::memory::Buffer buffer = reader.read()) { while (osmium::memory::Buffer buffer = reader.read()) {
// Write buffer to disk and update indexes. // Write buffer to disk and update indexes.
disk_store_handler(buffer); disk_store_handler(buffer);
// Update object relation index maps. // Update object relation index maps.
osmium::apply(buffer, object_relations_handler); 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());
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
} }
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());
} }

View File

@ -46,47 +46,53 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// The input file, deduce file format from file suffix. try {
osmium::io::File input_file{argv[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. // The output file, force XML OSM file format.
osmium::io::File output_file{argv[2], "osm"}; osmium::io::File output_file{argv[2], "osm"};
// Initialize Reader for the input file. // Initialize Reader for the input file.
// Read only changesets (will ignore nodes, ways, and // Read only changesets (will ignore nodes, ways, and
// relations if there are any). // relations if there are any).
osmium::io::Reader reader{input_file, osmium::osm_entity_bits::changeset}; osmium::io::Reader reader{input_file, osmium::osm_entity_bits::changeset};
// Get the header from the input file. // Get the header from the input file.
osmium::io::Header header = reader.header(); osmium::io::Header header = reader.header();
// Set the "generator" on the header to ourselves. // Set the "generator" on the header to ourselves.
header.set("generator", "osmium_filter_discussions"); header.set("generator", "osmium_filter_discussions");
// Initialize writer for the output file. Use the header from the input // Initialize writer for the output file. Use the header from the input
// file for the output file. This will copy over some header information. // 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 // The last parameter will tell the writer that it is allowed to overwrite
// an existing file. Without it, it will refuse to do so. // an existing file. Without it, it will refuse to do so.
osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow}; osmium::io::Writer writer{output_file, header, osmium::io::overwrite::allow};
// Create range of input iterators that will iterator over all changesets // Create range of input iterators that will iterator over all changesets
// delivered from input file through the "reader". // delivered from input file through the "reader".
auto input_range = osmium::io::make_input_iterator_range<osmium::Changeset>(reader); auto input_range = osmium::io::make_input_iterator_range<osmium::Changeset>(reader);
// Create an output iterator writing through the "writer" object to the // Create an output iterator writing through the "writer" object to the
// output file. // output file.
auto output_iterator = osmium::io::make_output_iterator(writer); auto output_iterator = osmium::io::make_output_iterator(writer);
// Copy all changesets from input to output that have at least one comment. // 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) { std::copy_if(input_range.begin(), input_range.end(), output_iterator, [](const osmium::Changeset& changeset) {
return changeset.num_comments() > 0; return changeset.num_comments() > 0;
}); });
// Explicitly close the writer and reader. Will throw an exception if // 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 // 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 // and reader, you will not notice the problem, because destructors must
// not throw. // not throw.
writer.close(); writer.close();
reader.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);
}
} }

View File

@ -182,7 +182,7 @@ class Options {
bool m_array_format = false; bool m_array_format = false;
bool m_list_format = false; bool m_list_format = false;
void print_help() { static void print_help() {
std::cout << "Usage: osmium_index_lookup [OPTIONS]\n\n" std::cout << "Usage: osmium_index_lookup [OPTIONS]\n\n"
<< "-h, --help Print this help message\n" << "-h, --help Print this help message\n"
<< "-a, --array=FILE Read given index file in array format\n" << "-a, --array=FILE Read given index file in array format\n"
@ -193,7 +193,7 @@ class Options {
; ;
} }
void print_usage(const char* prgname) { static void print_usage(const char* prgname) {
std::cout << "Usage: " << prgname << " [OPTIONS]\n\n"; std::cout << "Usage: " << prgname << " [OPTIONS]\n\n";
std::exit(0); std::exit(0);
} }
@ -363,7 +363,8 @@ int main(int argc, char* argv[]) {
const auto index = create<std::size_t>(options.dense_format(), fd); const auto index = create<std::size_t>(options.dense_format(), fd);
return run(*index, options); return run(*index, options);
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << '\n'; // All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1); std::exit(1);
} }
} }

View File

@ -65,30 +65,36 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string cache_filename{argv[2]}; const std::string input_filename{argv[1]};
const std::string cache_filename{argv[2]};
// Construct Reader reading only nodes // Construct Reader reading only nodes
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::node}; osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::node};
// Initialize location index on disk creating a new file. // Initialize location index on disk creating a new file.
const int fd = ::open(cache_filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); // NOLINT(hicpp-signed-bitwise) const int fd = ::open(cache_filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666); // NOLINT(hicpp-signed-bitwise)
if (fd == -1) { if (fd == -1) {
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n"; 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();
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1); 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();
} }

View File

@ -78,31 +78,37 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
const std::string input_filename{argv[1]}; try {
const std::string cache_filename{argv[2]}; const std::string input_filename{argv[1]};
const std::string cache_filename{argv[2]};
// Construct Reader reading only ways // Construct Reader reading only ways
osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::way}; osmium::io::Reader reader{input_filename, osmium::osm_entity_bits::way};
// Initialize location index on disk using an existing file // Initialize location index on disk using an existing file
const int fd = ::open(cache_filename.c_str(), O_RDWR); const int fd = ::open(cache_filename.c_str(), O_RDWR);
if (fd == -1) { if (fd == -1) {
std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n"; std::cerr << "Can not open location cache file '" << cache_filename << "': " << std::strerror(errno) << "\n";
return 1; return 1;
} }
#ifdef _WIN32 #ifdef _WIN32
_setmode(fd, _O_BINARY); _setmode(fd, _O_BINARY);
#endif #endif
index_type index{fd}; index_type index{fd};
// The handler that adds node locations from the index to the ways. // The handler that adds node locations from the index to the ways.
location_handler_type location_handler{index}; location_handler_type location_handler{index};
// Feed all ways through the location handler and then our own handler. // Feed all ways through the location handler and then our own handler.
MyHandler handler; MyHandler handler;
osmium::apply(reader, location_handler, handler); osmium::apply(reader, location_handler, handler);
// Explicitly close input so we get notified of any errors. // Explicitly close input so we get notified of any errors.
reader.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);
}
} }

View File

@ -33,7 +33,7 @@
class NamesHandler : public osmium::handler::Handler { class NamesHandler : public osmium::handler::Handler {
void output_pubs(const osmium::OSMObject& object) { static void output_pubs(const osmium::OSMObject& object) {
const osmium::TagList& tags = object.tags(); const osmium::TagList& tags = object.tags();
if (tags.has_tag("amenity", "pub")) { if (tags.has_tag("amenity", "pub")) {
@ -75,15 +75,21 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// Construct the handler defined above try {
NamesHandler names_handler; // Construct the handler defined above
NamesHandler names_handler;
// Initialize the reader with the filename from the command line and // Initialize the reader with the filename from the command line and
// tell it to only read nodes and ways. We are ignoring multipolygon // tell it to only read nodes and ways. We are ignoring multipolygon
// relations in this simple example. // relations in this simple example.
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way}; osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way};
// Apply input data to our own handler // Apply input data to our own handler
osmium::apply(reader, names_handler); osmium::apply(reader, names_handler);
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -25,18 +25,24 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// The Reader is initialized here with an osmium::io::File, but could try {
// also be directly initialized with a file name. // The Reader is initialized here with an osmium::io::File, but could
osmium::io::File input_file{argv[1]}; // also be directly initialized with a file name.
osmium::io::Reader reader{input_file}; osmium::io::File input_file{argv[1]};
osmium::io::Reader reader{input_file};
// OSM data comes in buffers, read until there are no more. // OSM data comes in buffers, read until there are no more.
while (osmium::memory::Buffer buffer = reader.read()) { while (osmium::memory::Buffer buffer = reader.read()) {
// do nothing // 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();
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
} }
// 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();
} }

View File

@ -32,25 +32,31 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// The Reader is initialized here with an osmium::io::File, but could try {
// also be directly initialized with a file name. // The Reader is initialized here with an osmium::io::File, but could
osmium::io::File input_file{argv[1]}; // also be directly initialized with a file name.
osmium::io::Reader reader{input_file}; osmium::io::File input_file{argv[1]};
osmium::io::Reader reader{input_file};
// Initialize progress bar, enable it only if STDERR is a TTY. // Initialize progress bar, enable it only if STDERR is a TTY.
osmium::ProgressBar progress{reader.file_size(), osmium::isatty(2)}; osmium::ProgressBar progress{reader.file_size(), osmium::isatty(2)};
// OSM data comes in buffers, read until there are no more. // OSM data comes in buffers, read until there are no more.
while (osmium::memory::Buffer buffer = reader.read()) { while (osmium::memory::Buffer buffer = reader.read()) {
// Update progress bar for each buffer. // Update progress bar for each buffer.
progress.update(reader.offset()); 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();
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
} }
// 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();
} }

View File

@ -68,25 +68,31 @@ int main(int argc, char* argv[]) {
std::exit(1); std::exit(1);
} }
// Initialize the reader with the filename from the command line and try {
// tell it to only read nodes and ways. // Initialize the reader with the filename from the command line and
osmium::io::Reader reader{argv[1], osmium::osm_entity_bits::node | osmium::osm_entity_bits::way}; // 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. // The index to hold node locations.
index_type index; index_type index;
// The location handler will add the node locations to the index and then // The location handler will add the node locations to the index and then
// to the ways // to the ways
location_handler_type location_handler{index}; location_handler_type location_handler{index};
// Our handler defined above // Our handler defined above
RoadLengthHandler road_length_handler; RoadLengthHandler road_length_handler;
// Apply input data to first the location handler and then our own handler // Apply input data to first the location handler and then our own handler
osmium::apply(reader, location_handler, road_length_handler); osmium::apply(reader, location_handler, road_length_handler);
// Output the length. The haversine function calculates it in meters, // Output the length. The haversine function calculates it in meters,
// so we first devide by 1000 to get kilometers. // so we first devide by 1000 to get kilometers.
std::cout << "Length: " << road_length_handler.length / 1000 << " km\n"; std::cout << "Length: " << road_length_handler.length / 1000 << " km\n";
} catch (const std::exception& e) {
// All exceptions used by the Osmium library derive from std::exception.
std::cerr << e.what() << '\n';
std::exit(1);
}
} }

View File

@ -5,11 +5,11 @@
C++11 wrapper classes for GDAL/OGR. C++11 wrapper classes for GDAL/OGR.
Version 1.1.1 Version 1.2.0
https://github.com/joto/gdalcpp https://github.com/joto/gdalcpp
Copyright 2015 Jochen Topf <jochen@topf.org> Copyright 2015-2018 Jochen Topf <jochen@topf.org>
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -37,17 +37,19 @@ DEALINGS IN THE SOFTWARE.
*/ */
#include <algorithm>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
#include <gdal_priv.h> #include <gdal_priv.h>
#include <gdal_version.h> #include <gdal_version.h>
#include <ogr_api.h> #include <ogr_api.h>
#include <ogrsf_frmts.h> #include <ogrsf_frmts.h>
#include <cstdint>
#include <algorithm>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
namespace gdalcpp { namespace gdalcpp {
#if GDAL_VERSION_MAJOR >= 2 #if GDAL_VERSION_MAJOR >= 2
@ -85,23 +87,23 @@ namespace gdalcpp {
m_error(error) { m_error(error) {
} }
const std::string& driver() const { const std::string& driver() const noexcept {
return m_driver; return m_driver;
} }
const std::string& dataset() const { const std::string& dataset() const noexcept {
return m_dataset; return m_dataset;
} }
const std::string& layer() const { const std::string& layer() const noexcept {
return m_layer; return m_layer;
} }
const std::string& field() const { const std::string& field() const noexcept {
return m_field; return m_field;
} }
OGRErr error() const { OGRErr error() const noexcept {
return m_error; return m_error;
} }
@ -111,18 +113,26 @@ namespace gdalcpp {
struct init_wrapper { struct init_wrapper {
#if GDAL_VERSION_MAJOR >= 2 #if GDAL_VERSION_MAJOR >= 2
init_wrapper() { GDALAllRegister(); } init_wrapper() noexcept {
GDALAllRegister();
}
#else #else
init_wrapper() { OGRRegisterAll(); } init_wrapper() noexcept {
~init_wrapper() { OGRCleanupAll(); } OGRRegisterAll();
}
~init_wrapper() noexcept {
OGRCleanupAll();
}
#endif #endif
}; }; // struct init_wrapper
struct init_library { struct init_library {
init_library() { init_library() {
static init_wrapper iw; static init_wrapper iw;
} }
};
}; // struct init_library
class Driver : private init_library { class Driver : private init_library {
@ -138,11 +148,13 @@ namespace gdalcpp {
m_driver(OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str())) { m_driver(OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(driver_name.c_str())) {
#endif #endif
if (!m_driver) { if (!m_driver) {
throw gdal_error(std::string("unknown driver: '") + driver_name + "'", OGRERR_NONE, driver_name); throw gdal_error{std::string{"unknown driver: '"} + driver_name + "'",
OGRERR_NONE,
driver_name};
} }
} }
gdal_driver_type& get() const { gdal_driver_type& get() const noexcept {
return *m_driver; return *m_driver;
} }
@ -155,14 +167,14 @@ namespace gdalcpp {
Options(const std::vector<std::string>& options) : Options(const std::vector<std::string>& options) :
m_options(options), m_options(options),
m_ptrs(new const char*[options.size()+1]) { m_ptrs(new const char*[options.size() + 1]) {
std::transform(m_options.begin(), m_options.end(), m_ptrs.get(), [&](const std::string& s) { std::transform(m_options.begin(), m_options.end(), m_ptrs.get(), [&](const std::string& s) {
return s.data(); return s.data();
}); });
m_ptrs[options.size()] = nullptr; m_ptrs[options.size()] = nullptr;
} }
char** get() const { char** get() const noexcept {
return const_cast<char**>(m_ptrs.get()); return const_cast<char**>(m_ptrs.get());
} }
@ -178,33 +190,37 @@ namespace gdalcpp {
SRS() : SRS() :
m_spatial_reference() { m_spatial_reference() {
auto result = m_spatial_reference.SetWellKnownGeogCS("WGS84"); const auto result = m_spatial_reference.SetWellKnownGeogCS("WGS84");
if (result != OGRERR_NONE) { if (result != OGRERR_NONE) {
throw gdal_error(std::string("can not initialize spatial reference system WGS84"), result); throw gdal_error{std::string{"can not initialize spatial reference system WGS84"},
result};
} }
} }
explicit SRS(int epsg) : explicit SRS(int epsg) :
m_spatial_reference() { m_spatial_reference() {
auto result = m_spatial_reference.importFromEPSG(epsg); const auto result = m_spatial_reference.importFromEPSG(epsg);
if (result != OGRERR_NONE) { if (result != OGRERR_NONE) {
throw gdal_error(std::string("can not initialize spatial reference system for EPSG:") + std::to_string(epsg), result); throw gdal_error{std::string{"can not initialize spatial reference system for EPSG:"} + std::to_string(epsg),
result};
} }
} }
explicit SRS(const char* name) : explicit SRS(const char* name) :
m_spatial_reference() { m_spatial_reference() {
auto result = m_spatial_reference.importFromProj4(name); const auto result = m_spatial_reference.importFromProj4(name);
if (result != OGRERR_NONE) { if (result != OGRERR_NONE) {
throw gdal_error(std::string("can not initialize spatial reference system '") + name + "'", result); throw gdal_error{std::string{"can not initialize spatial reference system '"} + name + "'",
result};
} }
} }
explicit SRS(const std::string& name) : explicit SRS(const std::string& name) :
m_spatial_reference() { m_spatial_reference() {
auto result = m_spatial_reference.importFromProj4(name.c_str()); const auto result = m_spatial_reference.importFromProj4(name.c_str());
if (result != OGRERR_NONE) { if (result != OGRERR_NONE) {
throw gdal_error(std::string("can not initialize spatial reference system '") + name + "'", result); throw gdal_error{std::string{"can not initialize spatial reference system '"} + name + "'",
result};
} }
} }
@ -212,11 +228,11 @@ namespace gdalcpp {
m_spatial_reference(spatial_reference) { m_spatial_reference(spatial_reference) {
} }
OGRSpatialReference& get() { OGRSpatialReference& get() noexcept {
return m_spatial_reference; return m_spatial_reference;
} }
const OGRSpatialReference& get() const { const OGRSpatialReference& get() const noexcept {
return m_spatial_reference; return m_spatial_reference;
} }
@ -257,11 +273,14 @@ namespace gdalcpp {
m_dataset(detail::Driver(driver_name).get().CreateDataSource(dataset_name.c_str(), m_options.get())) { m_dataset(detail::Driver(driver_name).get().CreateDataSource(dataset_name.c_str(), m_options.get())) {
#endif #endif
if (!m_dataset) { if (!m_dataset) {
throw gdal_error(std::string("failed to create dataset '") + dataset_name + "'", OGRERR_NONE, driver_name, dataset_name); throw gdal_error{std::string{"failed to create dataset '"} + dataset_name + "'",
OGRERR_NONE,
driver_name,
dataset_name};
} }
} }
~Dataset() { ~Dataset() noexcept {
try { try {
if (m_edit_count > 0) { if (m_edit_count > 0) {
commit_transaction(); commit_transaction();
@ -270,24 +289,24 @@ namespace gdalcpp {
} }
} }
const std::string& driver_name() const { const std::string& driver_name() const noexcept {
return m_driver_name; return m_driver_name;
} }
const std::string& dataset_name() const { const std::string& dataset_name() const noexcept {
return m_dataset_name; return m_dataset_name;
} }
gdal_dataset_type& get() const { gdal_dataset_type& get() const noexcept {
return *m_dataset; return *m_dataset;
} }
SRS& srs() { SRS& srs() noexcept {
return m_srs; return m_srs;
} }
void exec(const char* sql) { void exec(const char* sql) {
auto result = m_dataset->ExecuteSQL(sql, nullptr, nullptr); const auto result = m_dataset->ExecuteSQL(sql, nullptr, nullptr);
if (result) { if (result) {
m_dataset->ReleaseResultSet(result); m_dataset->ReleaseResultSet(result);
} }
@ -334,7 +353,7 @@ namespace gdalcpp {
} }
} }
Dataset& enable_auto_transactions(uint64_t edits = 100000) { Dataset& enable_auto_transactions(uint64_t edits = 100000) noexcept {
m_max_edit_count = edits; m_max_edit_count = edits;
return *this; return *this;
} }
@ -362,20 +381,23 @@ namespace gdalcpp {
m_dataset(dataset), m_dataset(dataset),
m_layer(dataset.get().CreateLayer(layer_name.c_str(), &dataset.srs().get(), type, m_options.get())) { m_layer(dataset.get().CreateLayer(layer_name.c_str(), &dataset.srs().get(), type, m_options.get())) {
if (!m_layer) { if (!m_layer) {
throw gdal_error(std::string("failed to create layer '") + layer_name + "'", OGRERR_NONE, throw gdal_error{std::string{"failed to create layer '"} + layer_name + "'",
dataset.driver_name(), dataset.dataset_name(), layer_name); OGRERR_NONE,
dataset.driver_name(),
dataset.dataset_name(),
layer_name};
} }
} }
OGRLayer& get() { OGRLayer& get() noexcept {
return *m_layer; return *m_layer;
} }
const OGRLayer& get() const { const OGRLayer& get() const noexcept {
return *m_layer; return *m_layer;
} }
Dataset& dataset() const { Dataset& dataset() const noexcept {
return m_dataset; return m_dataset;
} }
@ -389,8 +411,12 @@ namespace gdalcpp {
field.SetPrecision(precision); field.SetPrecision(precision);
if (m_layer->CreateField(&field) != OGRERR_NONE) { if (m_layer->CreateField(&field) != OGRERR_NONE) {
throw gdal_error(std::string("failed to create field '") + field_name + "' in layer '" + name() + "'", OGRERR_NONE, throw gdal_error{std::string{"failed to create field '"} + field_name + "' in layer '" + name() + "'",
m_dataset.driver_name(), m_dataset.dataset_name(), name(), field_name); OGRERR_NONE,
m_dataset.driver_name(),
m_dataset.dataset_name(),
name(),
field_name};
} }
return *this; return *this;
@ -398,18 +424,25 @@ namespace gdalcpp {
void create_feature(OGRFeature* feature) { void create_feature(OGRFeature* feature) {
dataset().prepare_edit(); dataset().prepare_edit();
OGRErr result = m_layer->CreateFeature(feature); const auto result = m_layer->CreateFeature(feature);
if (result != OGRERR_NONE) { if (result != OGRERR_NONE) {
throw gdal_error(std::string("creating feature in layer '") + name() + "' failed", result, dataset().driver_name(), dataset().dataset_name()); throw gdal_error{std::string{"creating feature in layer '"} + name() + "' failed",
result,
dataset().driver_name(),
dataset().dataset_name()};
} }
dataset().finalize_edit(); dataset().finalize_edit();
} }
Layer& start_transaction() { Layer& start_transaction() {
#if GDAL_VERSION_MAJOR < 2 #if GDAL_VERSION_MAJOR < 2
OGRErr result = m_layer->StartTransaction(); const auto result = m_layer->StartTransaction();
if (result != OGRERR_NONE) { 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()); throw gdal_error{std::string{"starting transaction on layer '"} + name() + "' failed",
result,
m_dataset.driver_name(),
m_dataset.dataset_name(),
name()};
} }
#endif #endif
return *this; return *this;
@ -417,9 +450,13 @@ namespace gdalcpp {
Layer& commit_transaction() { Layer& commit_transaction() {
#if GDAL_VERSION_MAJOR < 2 #if GDAL_VERSION_MAJOR < 2
OGRErr result = m_layer->CommitTransaction(); const auto result = m_layer->CommitTransaction();
if (result != OGRERR_NONE) { 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()); throw gdal_error{std::string{"committing transaction on layer '"} + name() + "' failed",
result,
m_dataset.driver_name(),
m_dataset.dataset_name(),
name()};
} }
#endif #endif
return *this; return *this;
@ -446,11 +483,14 @@ namespace gdalcpp {
m_layer(layer), m_layer(layer),
m_feature(OGRFeature::CreateFeature(m_layer.get().GetLayerDefn())) { m_feature(OGRFeature::CreateFeature(m_layer.get().GetLayerDefn())) {
if (!m_feature) { if (!m_feature) {
throw std::bad_alloc(); throw std::bad_alloc{};
} }
OGRErr result = m_feature->SetGeometryDirectly(geometry.release()); const auto result = m_feature->SetGeometryDirectly(geometry.release());
if (result != OGRERR_NONE) { 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()); 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()};
} }
} }
@ -458,13 +498,13 @@ namespace gdalcpp {
m_layer.create_feature(m_feature.get()); m_layer.create_feature(m_feature.get());
} }
template <class T> template <typename T>
Feature& set_field(int n, T&& arg) { Feature& set_field(int n, T&& arg) {
m_feature->SetField(n, std::forward<T>(arg)); m_feature->SetField(n, std::forward<T>(arg));
return *this; return *this;
} }
template <class T> template <typename T>
Feature& set_field(const char* name, T&& arg) { Feature& set_field(const char* name, T&& arg) {
m_feature->SetField(name, std::forward<T>(arg)); m_feature->SetField(name, std::forward<T>(arg));
return *this; return *this;

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -72,10 +72,6 @@ namespace osmium {
*/ */
class AssemblerLegacy : public detail::BasicAssemblerWithTags { 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 { void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
std::map<std::string, std::size_t> counter; std::map<std::string, std::size_t> counter;
for (const osmium::Way* way : ways) { for (const osmium::Way* way : ways) {
@ -166,7 +162,7 @@ namespace osmium {
const bool area_okay = create_rings(); const bool area_okay = create_rings();
if (area_okay || config().create_empty_areas) { if (area_okay || config().create_empty_areas) {
add_tags_to_area(builder, way); builder.add_item(way.tags());
} }
if (area_okay) { if (area_okay) {
add_rings_to_area(builder); add_rings_to_area(builder);

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -103,9 +103,19 @@ namespace osmium {
*/ */
class BasicAssembler { class BasicAssembler {
static constexpr const std::size_t max_split_locations = 100ULL;
// Maximum recursion depth, stops complex multipolygons from
// breaking everything.
enum : unsigned {
max_depth = 20U
};
struct slocation { struct slocation {
static constexpr const uint32_t invalid_item = 1u << 30u; enum {
invalid_item = 1U << 30U
};
uint32_t item : 31; uint32_t item : 31;
uint32_t reverse : 1; uint32_t reverse : 1;
@ -269,7 +279,7 @@ namespace osmium {
using rings_stack = std::vector<rings_stack_element>; using rings_stack = std::vector<rings_stack_element>;
void remove_duplicates(rings_stack& outer_rings) { static void remove_duplicates(rings_stack& outer_rings) {
while (true) { while (true) {
const auto it = std::adjacent_find(outer_rings.begin(), outer_rings.end()); const auto it = std::adjacent_find(outer_rings.begin(), outer_rings.end());
if (it == outer_rings.end()) { if (it == outer_rings.end()) {
@ -350,7 +360,8 @@ namespace osmium {
std::cerr << " Segment is below (nesting=" << nesting << ")\n"; std::cerr << " Segment is below (nesting=" << nesting << ")\n";
} }
if (segment->ring()->is_outer()) { if (segment->ring()->is_outer()) {
const double y = ay + (by - ay) * (lx - ax) / double(bx - ax); const double y = static_cast<double>(ay) +
static_cast<double>((by - ay) * (lx - ax)) / static_cast<double>(bx - ax);
if (debug()) { if (debug()) {
std::cerr << " Segment belongs to outer ring (y=" << y << " ring=" << *segment->ring() << ")\n"; std::cerr << " Segment belongs to outer ring (y=" << y << " ring=" << *segment->ring() << ")\n";
} }
@ -500,7 +511,12 @@ namespace osmium {
void create_locations_list() { void create_locations_list() {
m_locations.reserve(m_segment_list.size() * 2); m_locations.reserve(m_segment_list.size() * 2);
for (uint32_t n = 0; n < m_segment_list.size(); ++n) { // static_cast is okay here: The 32bit limit is way past
// anything that makes sense here and even if there are
// 2^32 segments here, it would simply not go through
// all of them not building the multipolygon correctly.
assert(m_segment_list.size() < std::numeric_limits<uint32_t>::max());
for (uint32_t n = 0; n < static_cast<uint32_t>(m_segment_list.size()); ++n) {
m_locations.emplace_back(n, false); m_locations.emplace_back(n, false);
m_locations.emplace_back(n, true); m_locations.emplace_back(n, true);
} }
@ -703,7 +719,13 @@ namespace osmium {
}; };
void find_candidates(std::vector<candidate>& candidates, std::unordered_set<osmium::Location>& loc_done, const std::vector<location_to_ring_map>& xrings, candidate& cand) { struct exceeded_max_depth {};
void find_candidates(std::vector<candidate>& candidates, std::unordered_set<osmium::Location>& loc_done, const std::vector<location_to_ring_map>& xrings, const candidate& cand, unsigned depth = 0) {
if (depth > max_depth) {
throw exceeded_max_depth{};
}
if (debug()) { if (debug()) {
std::cerr << " find_candidates sum=" << cand.sum << " start=" << cand.start_location << " stop=" << cand.stop_location << "\n"; std::cerr << " find_candidates sum=" << cand.sum << " start=" << cand.start_location << " stop=" << cand.stop_location << "\n";
for (const auto& ring : cand.rings) { for (const auto& ring : cand.rings) {
@ -741,13 +763,30 @@ namespace osmium {
if (debug()) { if (debug()) {
std::cerr << " found candidate\n"; std::cerr << " found candidate\n";
} }
candidates.push_back(c);
if (candidates.empty()) {
candidates.push_back(c);
} else if (candidates.size() == 1) {
// add new candidate to vector, keep sorted
if (std::abs(c.sum) < std::abs(candidates.front().sum)) {
candidates.insert(candidates.begin(), c);
} else {
candidates.push_back(c);
}
} else {
// add new candidate if it has either smallest or largest area
if (std::abs(c.sum) < std::abs(candidates.front().sum)) {
candidates.front() = c;
} else if (std::abs(c.sum) > std::abs(candidates.back().sum)) {
candidates.back() = c;
}
}
} else if (loc_done.count(c.stop_location) == 0) { } else if (loc_done.count(c.stop_location) == 0) {
if (debug()) { if (debug()) {
std::cerr << " recurse...\n"; std::cerr << " recurse... (depth=" << depth << " candidates.size=" << candidates.size() << ")\n";
} }
loc_done.insert(c.stop_location); loc_done.insert(c.stop_location);
find_candidates(candidates, loc_done, xrings, c); find_candidates(candidates, loc_done, xrings, c, depth + 1);
loc_done.erase(c.stop_location); loc_done.erase(c.stop_location);
if (debug()) { if (debug()) {
std::cerr << " ...back\n"; std::cerr << " ...back\n";
@ -790,7 +829,7 @@ namespace osmium {
ring.reset(); ring.reset();
} }
candidate cand{*ring_min, false}; const candidate cand{*ring_min, false};
// Locations we have visited while finding candidates, used // Locations we have visited while finding candidates, used
// to detect loops. // to detect loops.
@ -799,7 +838,14 @@ namespace osmium {
loc_done.insert(cand.stop_location); loc_done.insert(cand.stop_location);
std::vector<candidate> candidates; std::vector<candidate> candidates;
find_candidates(candidates, loc_done, xrings, cand); try {
find_candidates(candidates, loc_done, xrings, cand);
} catch (const exceeded_max_depth&) {
if (m_config.debug_level > 0) {
std::cerr << " Exceeded max depth (" << static_cast<unsigned>(max_depth) << ")\n";
}
return false;
}
if (candidates.empty()) { if (candidates.empty()) {
if (debug()) { if (debug()) {
@ -828,26 +874,20 @@ namespace osmium {
} }
// Find the candidate with the smallest/largest area // Find the candidate with the smallest/largest area
const auto chosen_cand = ring_min_is_outer ? const auto chosen_cand = ring_min_is_outer ? candidates.front() : candidates.back();
std::min_element(candidates.cbegin(), candidates.cend(), [](const candidate& lhs, const candidate& rhs) {
return std::abs(lhs.sum) < std::abs(rhs.sum);
}) :
std::max_element(candidates.cbegin(), candidates.cend(), [](const candidate& lhs, const candidate& rhs) {
return std::abs(lhs.sum) < std::abs(rhs.sum);
});
if (debug()) { if (debug()) {
std::cerr << " Decided on: sum=" << chosen_cand->sum << "\n"; std::cerr << " Decided on: sum=" << chosen_cand.sum << "\n";
for (const auto& ring : chosen_cand->rings) { for (const auto& ring : chosen_cand.rings) {
std::cerr << " " << ring.first.ring() << (ring.second ? " reverse" : "") << "\n"; std::cerr << " " << ring.first.ring() << (ring.second ? " reverse" : "") << "\n";
} }
} }
// Join all (open) rings in the candidate to get one closed ring. // Join all (open) rings in the candidate to get one closed ring.
assert(chosen_cand->rings.size() > 1); assert(chosen_cand.rings.size() > 1);
const auto& first_ring = chosen_cand->rings.front().first; const auto& first_ring = chosen_cand.rings.front().first;
const ProtoRing& remaining_ring = first_ring.ring(); const ProtoRing& remaining_ring = first_ring.ring();
for (auto it = std::next(chosen_cand->rings.begin()); it != chosen_cand->rings.end(); ++it) { for (auto it = std::next(chosen_cand.rings.begin()); it != chosen_cand.rings.end(); ++it) {
merge_two_rings(open_ring_its, first_ring, it->first); merge_two_rings(open_ring_its, first_ring, it->first);
} }
@ -1077,9 +1117,20 @@ namespace osmium {
timer_simple_case.start(); timer_simple_case.start();
create_rings_simple_case(); create_rings_simple_case();
timer_simple_case.stop(); timer_simple_case.stop();
} else if (m_split_locations.size() > max_split_locations) {
if (m_config.debug_level > 0) {
std::cerr << " Ignoring polygon with "
<< m_split_locations.size()
<< " split locations (>"
<< max_split_locations
<< ")\n";
}
return false;
} else { } else {
if (debug()) { if (m_config.debug_level > 0) {
std::cerr << " Found split locations -> using complex algorithm\n"; std::cerr << " Found "
<< m_split_locations.size()
<< " split locations -> using complex algorithm\n";
} }
++m_stats.area_touching_rings_case; ++m_stats.area_touching_rings_case;

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -38,6 +38,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/osm/node_ref.hpp> #include <osmium/osm/node_ref.hpp>
#include <algorithm> #include <algorithm>
#include <array>
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <iosfwd> #include <iosfwd>
@ -101,14 +102,10 @@ namespace osmium {
NodeRefSegment() noexcept = default; NodeRefSegment() noexcept = default;
NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, role_type role, const osmium::Way* way) noexcept : NodeRefSegment(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2, role_type role, const osmium::Way* way) noexcept :
m_first(nr1), m_first(nr1.location() < nr2.location() ? nr1 : nr2),
m_second(nr2), m_second(nr1.location() < nr2.location() ? nr2 : nr1),
m_way(way), m_way(way),
m_role(role) { m_role(role) {
if (nr2.location() < nr1.location()) {
using std::swap;
swap(m_first, m_second);
}
} }
/** /**
@ -195,7 +192,7 @@ namespace osmium {
} }
const char* role_name() const noexcept { const char* role_name() const noexcept {
static const char* names[] = { "unknown", "outer", "inner", "empty" }; static const std::array<const char*, 4> names = {{ "unknown", "outer", "inner", "empty" }};
return names[int(m_role)]; return names[int(m_role)];
} }
@ -205,7 +202,7 @@ namespace osmium {
/** /**
* The "determinant" of this segment. Used for calculating * The "determinant" of this segment. Used for calculating
* the winding order or a ring. * the winding order of a ring.
*/ */
int64_t det() const noexcept { int64_t det() const noexcept {
const vec a{start()}; const vec a{start()};
@ -348,13 +345,14 @@ namespace osmium {
osmium::Location location; osmium::Location location;
}; };
seg_loc sl[4]; std::array<seg_loc, 4> sl = {{
sl[0] = {0, s1.first().location() }; {0, s1.first().location() },
sl[1] = {0, s1.second().location()}; {0, s1.second().location()},
sl[2] = {1, s2.first().location() }; {1, s2.first().location() },
sl[3] = {1, s2.second().location()}; {1, s2.second().location()},
}};
std::sort(sl, sl+4, [](const seg_loc& lhs, const seg_loc& rhs) { std::sort(sl.begin(), sl.end(), [](const seg_loc& lhs, const seg_loc& rhs) {
return lhs.location < rhs.location; return lhs.location < rhs.location;
}); });

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -196,12 +196,14 @@ namespace osmium {
} }
void join_forward(ProtoRing& other) { void join_forward(ProtoRing& other) {
m_segments.reserve(m_segments.size() + other.m_segments.size());
for (NodeRefSegment* segment : other.m_segments) { for (NodeRefSegment* segment : other.m_segments) {
add_segment_back(segment); add_segment_back(segment);
} }
} }
void join_backward(ProtoRing& other) { void join_backward(ProtoRing& other) {
m_segments.reserve(m_segments.size() + other.m_segments.size());
for (auto it = other.m_segments.rbegin(); it != other.m_segments.rend(); ++it) { for (auto it = other.m_segments.rbegin(); it != other.m_segments.rend(); ++it) {
(*it)->reverse(); (*it)->reverse();
add_segment_back(*it); add_segment_back(*it);

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -147,14 +147,14 @@ namespace osmium {
m_debug(debug) { m_debug(debug) {
} }
~SegmentList() noexcept = default;
SegmentList(const SegmentList&) = delete; SegmentList(const SegmentList&) = delete;
SegmentList(SegmentList&&) = delete; SegmentList(SegmentList&&) = delete;
SegmentList& operator=(const SegmentList&) = delete; SegmentList& operator=(const SegmentList&) = delete;
SegmentList& operator=(SegmentList&&) = delete; SegmentList& operator=(SegmentList&&) = delete;
~SegmentList() noexcept = default;
/// The number of segments in the list. /// The number of segments in the list.
std::size_t size() const noexcept { std::size_t size() const noexcept {
return m_segments.size(); return m_segments.size();
@ -181,7 +181,7 @@ namespace osmium {
return m_segments[n]; return m_segments[n];
} }
NodeRefSegment& operator[](std::size_t n) noexcept { NodeRefSegment& operator[](const std::size_t n) noexcept {
assert(n < m_segments.size()); assert(n < m_segments.size());
return m_segments[n]; return m_segments[n];
} }
@ -206,7 +206,7 @@ namespace osmium {
* Enable or disable debug output to stderr. This is used * Enable or disable debug output to stderr. This is used
* for debugging libosmium itself. * for debugging libosmium itself.
*/ */
void enable_debug_output(bool debug = true) noexcept { void enable_debug_output(const bool debug = true) noexcept {
m_debug = debug; m_debug = debug;
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -68,8 +68,6 @@ namespace osmium {
detail::BasicAssembler(config) { detail::BasicAssembler(config) {
} }
~GeomAssembler() noexcept = default;
/** /**
* Assemble an area from the given way. * Assemble an area from the given way.
* *

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -70,6 +70,8 @@ namespace osmium {
* *
* @tparam TAssembler Multipolygon Assembler class. * @tparam TAssembler Multipolygon Assembler class.
* @pre The Ids of all objects must be unique in the input data. * @pre The Ids of all objects must be unique in the input data.
*
* @deprecated Use MultipolygonManager instead.
*/ */
template <typename TAssembler> template <typename TAssembler>
class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> { class MultipolygonCollector : public osmium::relations::Collector<MultipolygonCollector<TAssembler>, false, true, false> {
@ -83,8 +85,13 @@ namespace osmium {
area_stats m_stats; area_stats m_stats;
static constexpr size_t initial_output_buffer_size = 1024 * 1024; enum {
static constexpr size_t max_buffer_size_for_flush = 100 * 1024; initial_output_buffer_size = 1024UL * 1024UL
};
enum {
max_buffer_size_for_flush = 100UL * 1024UL
};
void flush_output_buffer() { void flush_output_buffer() {
if (this->callback()) { if (this->callback()) {

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -63,8 +63,8 @@ namespace osmium {
/** /**
* This class collects all data needed for creating areas from * This class collects all data needed for creating areas from
* relations tagged with type=multipolygon or type=boundary. * relations tagged with type=multipolygon or type=boundary.
* Most of its functionality is derived from the parent class * Most of its functionality is derived from the parent template class
* osmium::relations::Collector. * osmium::relations::RelationsManager.
* *
* The actual assembling of the areas is done by the assembler * The actual assembling of the areas is done by the assembler
* class given as template argument. * class given as template argument.

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -93,6 +93,10 @@ namespace osmium {
m_object_id = object_id; m_object_id = object_id;
} }
osmium::object_id_type object_id() const noexcept {
return m_object_id;
}
void set_nodes(size_t nodes) noexcept { void set_nodes(size_t nodes) noexcept {
m_nodes = nodes; m_nodes = nodes;
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -45,6 +45,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/osm/relation.hpp> #include <osmium/osm/relation.hpp>
#include <osmium/osm/timestamp.hpp> #include <osmium/osm/timestamp.hpp>
#include <osmium/osm/types.hpp> #include <osmium/osm/types.hpp>
#include <osmium/util/string.hpp>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@ -226,8 +227,8 @@ namespace osmium {
OSMIUM_ATTRIBUTE(node_handler, _location, osmium::Location) OSMIUM_ATTRIBUTE(node_handler, _location, osmium::Location)
constexpr explicit _location(const osmium::Location& value) noexcept : constexpr explicit _location(const osmium::Location& value) noexcept :
type_wrapper(value) {} type_wrapper(value) {}
explicit _location(double lat, double lon) : explicit _location(double lon, double lat) :
type_wrapper(osmium::Location{lat, lon}) {} type_wrapper(osmium::Location{lon, lat}) {}
}; };
OSMIUM_ATTRIBUTE(entity_handler, _user, const char*) OSMIUM_ATTRIBUTE(entity_handler, _user, const char*)
@ -254,6 +255,10 @@ namespace osmium {
m_role(role) { m_role(role) {
} }
member_type(char type, osmium::object_id_type ref, const char* role = "") noexcept :
member_type(osmium::char_to_item_type(type), ref, role) {
}
constexpr osmium::item_type type() const noexcept { constexpr osmium::item_type type() const noexcept {
return m_type; return m_type;
} }
@ -282,6 +287,10 @@ namespace osmium {
m_role(std::move(role)) { m_role(std::move(role)) {
} }
member_type_string(char type, osmium::object_id_type ref, std::string&& role) noexcept :
member_type_string(osmium::char_to_item_type(type), ref, std::forward<std::string>(role)) {
}
osmium::item_type type() const noexcept { osmium::item_type type() const noexcept {
return m_type; return m_type;
} }
@ -360,6 +369,15 @@ namespace osmium {
type_wrapper(std::make_pair(key, val)) {} type_wrapper(std::make_pair(key, val)) {}
explicit _tag(const std::string& key, const std::string& val) : explicit _tag(const std::string& key, const std::string& val) :
type_wrapper(std::make_pair(key.c_str(), val.c_str())) {} type_wrapper(std::make_pair(key.c_str(), val.c_str())) {}
explicit _tag(const char* const key_value) :
type_wrapper(pair_of_cstrings{key_value, nullptr}) {}
explicit _tag(const std::string& key_value) :
type_wrapper(pair_of_cstrings{key_value.c_str(), nullptr}) {}
};
OSMIUM_ATTRIBUTE(tags_handler, _t, const char*)
explicit _t(const char *tags) :
type_wrapper(tags) {}
}; };
template <typename TTagIterator> template <typename TTagIterator>
@ -659,7 +677,19 @@ namespace osmium {
} }
static void set_value(TagListBuilder& builder, const attr::_tag& tag) { static void set_value(TagListBuilder& builder, const attr::_tag& tag) {
builder.add_tag(tag.value); if (tag.value.second != nullptr) {
builder.add_tag(tag.value);
return;
}
const char* key = tag.value.first;
auto const equal_sign = std::strchr(key, '=');
if (!equal_sign) {
builder.add_tag(key, "");
return;
}
const char* value = equal_sign + 1;
builder.add_tag(key, equal_sign - key,
value, std::strlen(value));
} }
template <typename TIterator> template <typename TIterator>
@ -669,6 +699,21 @@ namespace osmium {
} }
} }
static void set_value(TagListBuilder& builder, const attr::_t& tags) {
const auto taglist = osmium::split_string(tags.value, ',', true);
for (const auto& tag : taglist) {
const std::size_t pos = tag.find_first_of('=');
if (pos == std::string::npos) {
builder.add_tag(tag, "");
} else {
const char* value = tag.c_str() + pos + 1;
builder.add_tag(tag.c_str(), pos,
value, tag.size() - pos - 1);
}
}
}
}; // struct tags_handler }; // struct tags_handler
struct nodes_handler { struct nodes_handler {
@ -764,7 +809,7 @@ namespace osmium {
template <typename TBuilder, typename THandler, typename... TArgs> template <typename TBuilder, typename THandler, typename... TArgs>
inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>::type inline typename std::enable_if<is_handled_by<THandler, TArgs...>::value>::type
add_list(osmium::builder::Builder& parent, const TArgs&... args) { add_list(osmium::builder::Builder& parent, const TArgs&... args) {
TBuilder builder(parent.buffer(), &parent); TBuilder builder{parent.buffer(), &parent};
(void)std::initializer_list<int>{ (void)std::initializer_list<int>{
(THandler::set_value(builder, args), 0)... (THandler::set_value(builder, args), 0)...
}; };
@ -792,7 +837,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()"); static_assert(detail::are_all_handled_by<detail::any_node_handlers, TArgs...>::value, "Attribute not allowed in add_node()");
{ {
NodeBuilder builder(buffer); NodeBuilder builder{buffer};
detail::add_basic<detail::node_handler>(builder, args...); detail::add_basic<detail::node_handler>(builder, args...);
detail::add_user(builder, args...); detail::add_user(builder, args...);
@ -815,7 +860,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()"); static_assert(detail::are_all_handled_by<detail::any_way_handlers, TArgs...>::value, "Attribute not allowed in add_way()");
{ {
WayBuilder builder(buffer); WayBuilder builder{buffer};
detail::add_basic<detail::object_handler>(builder, args...); detail::add_basic<detail::object_handler>(builder, args...);
detail::add_user(builder, args...); detail::add_user(builder, args...);
@ -839,7 +884,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()"); static_assert(detail::are_all_handled_by<detail::any_relation_handlers, TArgs...>::value, "Attribute not allowed in add_relation()");
{ {
RelationBuilder builder(buffer); RelationBuilder builder{buffer};
detail::add_basic<detail::object_handler>(builder, args...); detail::add_basic<detail::object_handler>(builder, args...);
detail::add_user(builder, args...); detail::add_user(builder, args...);
@ -863,7 +908,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()"); static_assert(detail::are_all_handled_by<detail::any_changeset_handlers, TArgs...>::value, "Attribute not allowed in add_changeset()");
{ {
ChangesetBuilder builder(buffer); ChangesetBuilder builder{buffer};
detail::add_basic<detail::changeset_handler>(builder, args...); detail::add_basic<detail::changeset_handler>(builder, args...);
detail::add_user(builder, args...); detail::add_user(builder, args...);
@ -887,7 +932,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()"); static_assert(detail::are_all_handled_by<detail::any_area_handlers, TArgs...>::value, "Attribute not allowed in add_area()");
{ {
AreaBuilder builder(buffer); AreaBuilder builder{buffer};
detail::add_basic<detail::object_handler>(builder, args...); detail::add_basic<detail::object_handler>(builder, args...);
detail::add_user(builder, args...); detail::add_user(builder, args...);
@ -914,7 +959,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::nodes_handler, TArgs...>::value, "Attribute not allowed in add_way_node_list()"); static_assert(detail::are_all_handled_by<detail::nodes_handler, TArgs...>::value, "Attribute not allowed in add_way_node_list()");
{ {
WayNodeListBuilder builder(buffer); WayNodeListBuilder builder{buffer};
(void)std::initializer_list<int>{ (void)std::initializer_list<int>{
(detail::nodes_handler::set_value(builder, args), 0)... (detail::nodes_handler::set_value(builder, args), 0)...
}; };
@ -936,7 +981,7 @@ namespace osmium {
static_assert(detail::are_all_handled_by<detail::tags_handler, TArgs...>::value, "Attribute not allowed in add_tag_list()"); static_assert(detail::are_all_handled_by<detail::tags_handler, TArgs...>::value, "Attribute not allowed in add_tag_list()");
{ {
TagListBuilder builder(buffer); TagListBuilder builder{buffer};
(void)std::initializer_list<int>{ (void)std::initializer_list<int>{
(detail::tags_handler::set_value(builder, args), 0)... (detail::tags_handler::set_value(builder, args), 0)...
}; };

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -65,7 +65,7 @@ namespace osmium {
explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, osmium::memory::item_size_type size) : explicit Builder(osmium::memory::Buffer& buffer, Builder* parent, osmium::memory::item_size_type size) :
m_buffer(buffer), m_buffer(buffer),
m_parent(parent), m_parent(parent),
m_item_offset(buffer.written()) { m_item_offset(buffer.written() - buffer.committed()) {
reserve_space(size); reserve_space(size);
assert(buffer.is_aligned()); assert(buffer.is_aligned());
if (m_parent) { if (m_parent) {
@ -80,7 +80,7 @@ namespace osmium {
} }
#ifdef NDEBUG #ifdef NDEBUG
~Builder() = default; ~Builder() noexcept = default;
#else #else
~Builder() noexcept { ~Builder() noexcept {
m_buffer.decrement_builder_count(); m_buffer.decrement_builder_count();
@ -88,7 +88,7 @@ namespace osmium {
#endif #endif
osmium::memory::Item& item() const { osmium::memory::Item& item() const {
return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_item_offset); return *reinterpret_cast<osmium::memory::Item*>(m_buffer.data() + m_buffer.committed() + m_item_offset);
} }
unsigned char* reserve_space(std::size_t size) { unsigned char* reserve_space(std::size_t size) {

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -49,6 +49,9 @@ namespace osmium {
* An input iterator wrapping any iterator over OSMObjects. When * An input iterator wrapping any iterator over OSMObjects. When
* dereferenced it will yield DiffObject objects pointing to the * dereferenced it will yield DiffObject objects pointing to the
* underlying OSMObjects. * underlying OSMObjects.
*
* Note that this class uses a mutable member variable internally.
* It can not be used safely in multiple threads!
*/ */
template <typename TBasicIterator> template <typename TBasicIterator>
class DiffIterator { class DiffIterator {

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/geom/coordinates.hpp> #include <osmium/geom/coordinates.hpp>
#include <osmium/geom/util.hpp> #include <osmium/geom/util.hpp>
#include <osmium/osm/node_ref.hpp> #include <osmium/osm/node_ref_list.hpp>
#include <osmium/osm/way.hpp> #include <osmium/osm/way.hpp>
#include <cmath> #include <cmath>
@ -63,13 +63,13 @@ namespace osmium {
* *
* @pre @code c1.valid() && c2.valid() @endcode * @pre @code c1.valid() && c2.valid() @endcode
*/ */
inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) { inline double distance(const osmium::geom::Coordinates& c1, const osmium::geom::Coordinates& c2) noexcept {
double lonh = sin(deg_to_rad(c1.x - c2.x) * 0.5); double lonh = std::sin(deg_to_rad(c1.x - c2.x) * 0.5);
lonh *= lonh; lonh *= lonh;
double lath = sin(deg_to_rad(c1.y - c2.y) * 0.5); double lath = std::sin(deg_to_rad(c1.y - c2.y) * 0.5);
lath *= lath; lath *= lath;
const double tmp = cos(deg_to_rad(c1.y)) * cos(deg_to_rad(c2.y)); const double tmp = std::cos(deg_to_rad(c1.y)) * std::cos(deg_to_rad(c2.y));
return 2.0 * EARTH_RADIUS_IN_METERS * asin(sqrt(lath + tmp * lonh)); return 2.0 * EARTH_RADIUS_IN_METERS * std::asin(std::sqrt(lath + tmp * lonh));
} }
/** /**
@ -87,6 +87,21 @@ namespace osmium {
return sum_length; return sum_length;
} }
/**
* Calculate length of node list.
*/
inline double distance(const osmium::NodeRefList& nrl) {
double sum_length = 0;
for (auto it = nrl.begin(); it != nrl.end(); ++it) {
if (std::next(it) != nrl.end()) {
sum_length += distance(it->location(), std::next(it)->location());
}
}
return sum_length;
}
} // namespace haversine } // namespace haversine
} // namespace geom } // namespace geom

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -49,7 +49,7 @@ namespace osmium {
constexpr double earth_radius_for_epsg3857 = 6378137.0; constexpr double earth_radius_for_epsg3857 = 6378137.0;
constexpr double max_coordinate_epsg3857 = 20037508.34; constexpr double max_coordinate_epsg3857 = 20037508.34;
constexpr inline double lon_to_x(double lon) { constexpr inline double lon_to_x(double lon) noexcept {
return earth_radius_for_epsg3857 * deg_to_rad(lon); return earth_radius_for_epsg3857 * deg_to_rad(lon);
} }
@ -116,6 +116,9 @@ namespace osmium {
* Convert the coordinates from WGS84 lon/lat to web mercator. * Convert the coordinates from WGS84 lon/lat to web mercator.
* *
* @pre @code c.valid() @endcode * @pre @code c.valid() @endcode
* @pre Coordinates must be in valid range, longitude between
* -180 and +180 degree, latitude between -MERCATOR_MAX_LAT
* and MERCATOR_MAX_LAT.
*/ */
inline Coordinates lonlat_to_mercator(const Coordinates& c) { inline Coordinates lonlat_to_mercator(const Coordinates& c) {
return Coordinates{detail::lon_to_x(c.x), detail::lat_to_y(c.y)}; return Coordinates{detail::lon_to_x(c.x), detail::lat_to_y(c.y)};
@ -125,6 +128,8 @@ namespace osmium {
* Convert the coordinates from web mercator to WGS84 lon/lat. * Convert the coordinates from web mercator to WGS84 lon/lat.
* *
* @pre @code c.valid() @endcode * @pre @code c.valid() @endcode
* @pre Coordinates must be in valid range (longitude and
* latidude between -/+20037508.34).
*/ */
inline Coordinates mercator_to_lonlat(const Coordinates& c) { inline Coordinates mercator_to_lonlat(const Coordinates& c) {
return Coordinates{detail::x_to_lon(c.x), detail::y_to_lat(c.y)}; return Coordinates{detail::x_to_lon(c.x), detail::y_to_lat(c.y)};
@ -145,6 +150,13 @@ namespace osmium {
MercatorProjection() { // NOLINT(hicpp-use-equals-default, modernize-use-equals-default) MercatorProjection() { // NOLINT(hicpp-use-equals-default, modernize-use-equals-default)
} }
/**
* Do coordinate transformation.
*
* @pre Coordinates must be in valid range, longitude between
* -180 and +180 degree, latitude between -MERCATOR_MAX_LAT
* and MERCATOR_MAX_LAT.
*/
Coordinates operator()(osmium::Location location) const { Coordinates operator()(osmium::Location location) const {
return Coordinates{detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())}; return Coordinates{detail::lon_to_x(location.lon()), detail::lat_to_y(location.lat())};
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -46,8 +46,15 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/geom/mercator_projection.hpp> #include <osmium/geom/mercator_projection.hpp>
#include <osmium/geom/util.hpp> #include <osmium/geom/util.hpp>
#include <osmium/osm/location.hpp> #include <osmium/osm/location.hpp>
#include <osmium/util/compatibility.hpp>
#include <proj_api.h> #ifdef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
# include <proj_api.h>
#else
# define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
# include <proj_api.h>
# undef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
#endif
#include <memory> #include <memory>
#include <string> #include <string>
@ -58,6 +65,8 @@ namespace osmium {
/** /**
* C++ wrapper for a Coordinate Reference System of the proj library. * C++ wrapper for a Coordinate Reference System of the proj library.
*
* @deprecated Only supports the old PROJ API.
*/ */
class CRS { class CRS {
@ -110,9 +119,11 @@ namespace osmium {
* Coordinates have to be in radians and are produced in radians. * Coordinates have to be in radians and are produced in radians.
* *
* @throws osmium::projection_error if the projection fails * @throws osmium::projection_error if the projection fails
*
* @deprecated Only supports the old PROJ API.
*/ */
// cppcheck-suppress passedByValue (because c is small and we want to change it) // cppcheck-suppress passedByValue (because c is small and we want to change it)
inline Coordinates transform(const CRS& src, const CRS& dest, Coordinates c) { inline OSMIUM_DEPRECATED 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); const int result = pj_transform(src.get(), dest.get(), 1, 1, &c.x, &c.y, nullptr);
if (result != 0) { if (result != 0) {
throw osmium::projection_error{std::string{"projection failed: "} + pj_strerrno(result)}; throw osmium::projection_error{std::string{"projection failed: "} + pj_strerrno(result)};
@ -130,6 +141,8 @@ namespace osmium {
* implementation of the Mercator projection is used, otherwise this * implementation of the Mercator projection is used, otherwise this
* falls back to using the proj.4 library. Note that this "magic" does * 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. * not work if you use any of the constructors taking a string.
*
* @deprecated Only supports the old PROJ API.
*/ */
class Projection { class Projection {
@ -158,6 +171,12 @@ namespace osmium {
m_crs_user(epsg) { m_crs_user(epsg) {
} }
/**
* Do coordinate transformation.
*
* @pre Location must be in valid range (depends on projection
* used).
*/
Coordinates operator()(osmium::Location location) const { Coordinates operator()(osmium::Location location) const {
if (m_epsg == 4326) { if (m_epsg == 4326) {
return Coordinates{location.lon(), location.lat()}; return Coordinates{location.lon(), location.lat()};

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -58,7 +58,7 @@ namespace osmium {
* level. * level.
*/ */
inline constexpr uint32_t num_tiles_in_zoom(uint32_t zoom) noexcept { inline constexpr uint32_t num_tiles_in_zoom(uint32_t zoom) noexcept {
return 1u << zoom; return 1U << zoom;
} }
/** /**
@ -98,6 +98,10 @@ namespace osmium {
*/ */
struct Tile { struct Tile {
enum {
max_zoom = 30U
};
/// x coordinate /// x coordinate
uint32_t x; uint32_t x;
@ -119,7 +123,7 @@ namespace osmium {
x(tx), x(tx),
y(ty), y(ty),
z(zoom) { z(zoom) {
assert(zoom <= 30u); assert(zoom <= max_zoom);
assert(x < num_tiles_in_zoom(zoom)); assert(x < num_tiles_in_zoom(zoom));
assert(y < num_tiles_in_zoom(zoom)); assert(y < num_tiles_in_zoom(zoom));
} }
@ -134,7 +138,7 @@ namespace osmium {
*/ */
explicit Tile(uint32_t zoom, const osmium::Location& location) : explicit Tile(uint32_t zoom, const osmium::Location& location) :
z(zoom) { z(zoom) {
assert(zoom <= 30u); assert(zoom <= max_zoom);
assert(location.valid()); assert(location.valid());
const auto coordinates = lonlat_to_mercator(location); const auto coordinates = lonlat_to_mercator(location);
x = mercx_to_tilex(zoom, coordinates.x); x = mercx_to_tilex(zoom, coordinates.x);
@ -151,7 +155,7 @@ namespace osmium {
*/ */
explicit Tile(uint32_t zoom, const osmium::geom::Coordinates& coordinates) : explicit Tile(uint32_t zoom, const osmium::geom::Coordinates& coordinates) :
z(zoom) { z(zoom) {
assert(zoom <= 30u); assert(zoom <= max_zoom);
x = mercx_to_tilex(zoom, coordinates.x); x = mercx_to_tilex(zoom, coordinates.x);
y = mercy_to_tiley(zoom, coordinates.y); y = mercy_to_tiley(zoom, coordinates.y);
} }
@ -162,7 +166,7 @@ namespace osmium {
* each be between 0 and 2^zoom-1. * each be between 0 and 2^zoom-1.
*/ */
bool valid() const noexcept { bool valid() const noexcept {
if (z > 30) { if (z > max_zoom) {
return false; return false;
} }
const auto max = num_tiles_in_zoom(z); const auto max = num_tiles_in_zoom(z);

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -35,7 +35,6 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/geom/coordinates.hpp> #include <osmium/geom/coordinates.hpp>
#include <osmium/geom/factory.hpp> #include <osmium/geom/factory.hpp>
#include <osmium/util/cast.hpp>
#include <osmium/util/endian.hpp> #include <osmium/util/endian.hpp>
#include <algorithm> #include <algorithm>
@ -70,8 +69,8 @@ namespace osmium {
out.reserve(str.size() * 2); out.reserve(str.size() * 2);
for (char c : str) { for (char c : str) {
out += lookup_hex[(static_cast<unsigned int>(c) >> 4u) & 0xfu]; out += lookup_hex[(static_cast<unsigned int>(c) >> 4U) & 0xfU];
out += lookup_hex[ static_cast<unsigned int>(c) & 0xfu]; out += lookup_hex[ static_cast<unsigned int>(c) & 0xfU];
} }
return out; return out;

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -46,7 +46,9 @@ namespace osmium {
namespace detail { namespace detail {
constexpr size_t mmap_vector_size_increment = 1024 * 1024; enum {
mmap_vector_size_increment = 1024UL * 1024UL
};
/** /**
* This is a base class for implementing classes that look like * This is a base class for implementing classes that look like
@ -58,12 +60,12 @@ namespace osmium {
protected: protected:
size_t m_size = 0; std::size_t m_size = 0;
osmium::TypedMemoryMapping<T> m_mapping; osmium::TypedMemoryMapping<T> m_mapping;
public: public:
mmap_vector_base(int fd, size_t capacity, size_t size = 0) : mmap_vector_base(const int fd, const std::size_t capacity, const std::size_t size = 0) :
m_size(size), m_size(size),
m_mapping(capacity, osmium::MemoryMapping::mapping_mode::write_shared, fd) { m_mapping(capacity, osmium::MemoryMapping::mapping_mode::write_shared, fd) {
assert(size <= capacity); assert(size <= capacity);
@ -71,7 +73,7 @@ namespace osmium {
shrink_to_fit(); shrink_to_fit();
} }
explicit mmap_vector_base(size_t capacity = mmap_vector_size_increment) : explicit mmap_vector_base(const std::size_t capacity = mmap_vector_size_increment) :
m_mapping(capacity) { m_mapping(capacity) {
std::fill_n(data(), capacity, osmium::index::empty_value<T>()); std::fill_n(data(), capacity, osmium::index::empty_value<T>());
} }
@ -88,11 +90,11 @@ namespace osmium {
m_mapping.unmap(); m_mapping.unmap();
} }
size_t capacity() const noexcept { std::size_t capacity() const noexcept {
return m_mapping.size(); return m_mapping.size();
} }
size_t size() const noexcept { std::size_t size() const noexcept {
return m_size; return m_size;
} }
@ -108,17 +110,17 @@ namespace osmium {
return m_mapping.begin(); return m_mapping.begin();
} }
const_reference operator[](size_t n) const { const_reference operator[](const std::size_t n) const {
assert(n < m_size); assert(n < m_size);
return data()[n]; return data()[n];
} }
reference operator[](size_t n) { reference operator[](const std::size_t n) {
assert(n < m_size); assert(n < m_size);
return data()[n]; return data()[n];
} }
value_type at(size_t n) const { value_type at(const std::size_t n) const {
if (n >= m_size) { if (n >= m_size) {
throw std::out_of_range{"out of range"}; throw std::out_of_range{"out of range"};
} }
@ -140,17 +142,17 @@ namespace osmium {
data()[m_size - 1] = value; data()[m_size - 1] = value;
} }
void reserve(size_t new_capacity) { void reserve(const std::size_t new_capacity) {
if (new_capacity > capacity()) { if (new_capacity > capacity()) {
const size_t old_capacity = capacity(); const std::size_t old_capacity = capacity();
m_mapping.resize(new_capacity); m_mapping.resize(new_capacity);
std::fill(data() + old_capacity, data() + new_capacity, osmium::index::empty_value<value_type>()); std::fill(data() + old_capacity, data() + new_capacity, osmium::index::empty_value<value_type>());
} }
} }
void resize(size_t new_size) { void resize(const std::size_t new_size) {
if (new_size > capacity()) { if (new_size > capacity()) {
reserve(new_size + osmium::detail::mmap_vector_size_increment); reserve(new_size + mmap_vector_size_increment);
} }
m_size = new_size; m_size = new_size;
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -53,7 +53,7 @@ namespace osmium {
template <typename T> template <typename T>
class mmap_vector_file : public mmap_vector_base<T> { class mmap_vector_file : public mmap_vector_base<T> {
static std::size_t filesize(int fd) { static std::size_t filesize(const int fd) {
const auto size = osmium::file_size(fd); const auto size = osmium::file_size(fd);
if (size % sizeof(T) != 0) { if (size % sizeof(T) != 0) {
@ -71,10 +71,10 @@ namespace osmium {
osmium::detail::mmap_vector_size_increment) { osmium::detail::mmap_vector_size_increment) {
} }
explicit mmap_vector_file(int fd) : explicit mmap_vector_file(const int fd) :
mmap_vector_base<T>( mmap_vector_base<T>(
fd, fd,
std::max(osmium::detail::mmap_vector_size_increment, filesize(fd)), std::max(static_cast<std::size_t>(mmap_vector_size_increment), filesize(fd)),
filesize(fd)) { filesize(fd)) {
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -39,8 +39,10 @@ DEALINGS IN THE SOFTWARE.
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <memory>
#include <utility> #include <utility>
namespace osmium { namespace osmium {
namespace index { namespace index {
@ -221,6 +223,26 @@ namespace osmium {
std::sort(m_vector.begin(), m_vector.end()); std::sort(m_vector.begin(), m_vector.end());
} }
void dump_as_array(const int fd) final {
constexpr const size_t value_size = sizeof(TValue);
constexpr const size_t buffer_size = (10L * 1024L * 1024L) / value_size;
std::unique_ptr<TValue[]> output_buffer{new TValue[buffer_size]};
size_t buffer_start_id = 0;
for (auto it = cbegin(); it != cend();) {
std::fill_n(output_buffer.get(), buffer_size, osmium::index::empty_value<TValue>());
size_t offset = 0;
for (; offset < buffer_size && it != end(); ++offset) {
if (buffer_start_id + offset == it->first) {
output_buffer[offset] = it->second;
++it;
}
}
osmium::io::detail::reliable_write(fd, reinterpret_cast<const unsigned char*>(output_buffer.get()), offset * value_size);
buffer_start_id += buffer_size;
}
}
void dump_as_list(const int fd) final { void dump_as_list(const int fd) final {
osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size()); osmium::io::detail::reliable_write(fd, reinterpret_cast<const char*>(m_vector.data()), byte_size());
} }

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -37,6 +37,7 @@ DEALINGS IN THE SOFTWARE.
#include <osmium/osm/types.hpp> #include <osmium/osm/types.hpp>
#include <algorithm> #include <algorithm>
#include <array>
#include <cassert> #include <cassert>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
@ -95,33 +96,47 @@ namespace osmium {
}; // class IdSet }; // class IdSet
template <typename T> namespace detail {
// This value is a compromise. For node Ids it could be bigger
// which would mean less (but larger) memory allocations. For
// relations Ids it could be smaller, because they would all fit
// into a smaller allocation.
enum : std::size_t {
default_chunk_bits = 22U
};
} // namespace detail
template <typename T, std::size_t chunk_bits = detail::default_chunk_bits>
class IdSetDense; class IdSetDense;
/** /**
* Const_iterator for iterating over a IdSetDense. * Const_iterator for iterating over a IdSetDense.
*/ */
template <typename T> template <typename T, std::size_t chunk_bits>
class IdSetDenseIterator { class IdSetDenseIterator {
static_assert(std::is_unsigned<T>::value, "Needs unsigned type"); static_assert(std::is_unsigned<T>::value, "Needs unsigned type");
static_assert(sizeof(T) >= 4, "Needs at least 32bit type"); static_assert(sizeof(T) >= 4, "Needs at least 32bit type");
const IdSetDense<T>* m_set; using id_set = IdSetDense<T, chunk_bits>;
const id_set* m_set;
T m_value; T m_value;
T m_last; T m_last;
void next() noexcept { void next() noexcept {
while (m_value != m_last && !m_set->get(m_value)) { while (m_value != m_last && !m_set->get(m_value)) {
const T cid = IdSetDense<T>::chunk_id(m_value); const T cid = id_set::chunk_id(m_value);
assert(cid < m_set->m_data.size()); assert(cid < m_set->m_data.size());
if (!m_set->m_data[cid]) { if (!m_set->m_data[cid]) {
m_value = (cid + 1) << (IdSetDense<T>::chunk_bits + 3); m_value = (cid + 1) << (chunk_bits + 3);
} else { } else {
const auto slot = m_set->m_data[cid][IdSetDense<T>::offset(m_value)]; const auto slot = m_set->m_data[cid][id_set::offset(m_value)];
if (slot == 0) { if (slot == 0) {
m_value += 8; m_value += 8;
m_value &= ~0x7ull; m_value &= ~0x7ULL;
} else { } else {
++m_value; ++m_value;
} }
@ -136,14 +151,14 @@ namespace osmium {
using pointer = value_type*; using pointer = value_type*;
using reference = value_type&; using reference = value_type&;
IdSetDenseIterator(const IdSetDense<T>* set, T value, T last) noexcept : IdSetDenseIterator(const id_set* set, T value, T last) noexcept :
m_set(set), m_set(set),
m_value(value), m_value(value),
m_last(last) { m_last(last) {
next(); next();
} }
IdSetDenseIterator<T>& operator++() noexcept { IdSetDenseIterator& operator++() noexcept {
if (m_value != m_last) { if (m_value != m_last) {
++m_value; ++m_value;
next(); next();
@ -151,17 +166,17 @@ namespace osmium {
return *this; return *this;
} }
IdSetDenseIterator<T> operator++(int) noexcept { IdSetDenseIterator operator++(int) noexcept {
IdSetDenseIterator<T> tmp{*this}; IdSetDenseIterator tmp{*this};
operator++(); operator++();
return tmp; return tmp;
} }
bool operator==(const IdSetDenseIterator<T>& rhs) const noexcept { bool operator==(const IdSetDenseIterator& rhs) const noexcept {
return m_set == rhs.m_set && m_value == rhs.m_value; return m_set == rhs.m_set && m_value == rhs.m_value;
} }
bool operator!=(const IdSetDenseIterator<T>& rhs) const noexcept { bool operator!=(const IdSetDenseIterator& rhs) const noexcept {
return !(*this == rhs); return !(*this == rhs);
} }
@ -179,34 +194,31 @@ namespace osmium {
* and larger Id sets. If it is not used, no memory is allocated at * and larger Id sets. If it is not used, no memory is allocated at
* all. * all.
*/ */
template <typename T> template <typename T, std::size_t chunk_bits>
class IdSetDense : public IdSet<T> { class IdSetDense : public IdSet<T> {
static_assert(std::is_unsigned<T>::value, "Needs unsigned type"); static_assert(std::is_unsigned<T>::value, "Needs unsigned type");
static_assert(sizeof(T) >= 4, "Needs at least 32bit type"); static_assert(sizeof(T) >= 4, "Needs at least 32bit type");
friend class IdSetDenseIterator<T>; friend class IdSetDenseIterator<T, chunk_bits>;
// This value is a compromise. For node Ids it could be bigger enum : std::size_t {
// which would mean less (but larger) memory allocations. For chunk_size = 1U << chunk_bits
// relations Ids it could be smaller, because they would all fit };
// into a smaller allocation.
constexpr static const std::size_t chunk_bits = 22u;
constexpr static const std::size_t chunk_size = 1u << chunk_bits;
std::vector<std::unique_ptr<unsigned char[]>> m_data; std::vector<std::unique_ptr<unsigned char[]>> m_data;
T m_size = 0; T m_size = 0;
static std::size_t chunk_id(T id) noexcept { static std::size_t chunk_id(T id) noexcept {
return id >> (chunk_bits + 3u); return id >> (chunk_bits + 3U);
} }
static std::size_t offset(T id) noexcept { static std::size_t offset(T id) noexcept {
return (id >> 3u) & ((1u << chunk_bits) - 1u); return (id >> 3U) & ((1U << chunk_bits) - 1U);
} }
static unsigned char bitmask(T id) noexcept { static unsigned int bitmask(T id) noexcept {
return 1u << (id & 0x7u); return 1U << (id & 0x7U);
} }
T last() const noexcept { T last() const noexcept {
@ -230,10 +242,43 @@ namespace osmium {
public: public:
using const_iterator = IdSetDenseIterator<T>; using const_iterator = IdSetDenseIterator<T, chunk_bits>;
friend void swap(IdSetDense& first, IdSetDense& second) noexcept {
using std::swap;
swap(first.m_data, second.m_data);
swap(first.m_size, second.m_size);
}
IdSetDense() = default; IdSetDense() = default;
IdSetDense(const IdSetDense& other) :
IdSet<T>(other) {
m_data.reserve(other.m_data.size());
for (const auto& ptr: other.m_data) {
if (ptr) {
m_data.emplace_back(new unsigned char[chunk_size]);
::memcpy(m_data.back().get(), ptr.get(), chunk_size);
} else {
m_data.emplace_back();
}
}
m_size = other.m_size;
}
IdSetDense& operator=(IdSetDense other) {
swap(*this, other);
return *this;
}
IdSetDense(IdSetDense&&) noexcept = default;
// This should really be noexcept, but GCC 4.8 doesn't like it.
// NOLINTNEXTLINE(hicpp-noexcept-move, performance-noexcept-move-constructor)
IdSetDense& operator=(IdSetDense&&) = default;
~IdSetDense() noexcept override = default;
/** /**
* Add the Id to the set if it is not already in there. * Add the Id to the set if it is not already in there.
* *
@ -284,7 +329,7 @@ namespace osmium {
if (chunk_id(id) >= m_data.size()) { if (chunk_id(id) >= m_data.size()) {
return false; return false;
} }
auto* r = m_data[chunk_id(id)].get(); const auto* r = m_data[chunk_id(id)].get();
if (!r) { if (!r) {
return false; return false;
} }
@ -317,11 +362,11 @@ namespace osmium {
return m_data.size() * chunk_size; return m_data.size() * chunk_size;
} }
IdSetDenseIterator<T> begin() const { const_iterator begin() const {
return {this, 0, last()}; return {this, 0, last()};
} }
IdSetDenseIterator<T> end() const { const_iterator end() const {
return {this, last(), last()}; return {this, last(), last()};
} }
@ -342,7 +387,9 @@ namespace osmium {
* Add the given Id to the set. * Add the given Id to the set.
*/ */
void set(T id) final { void set(T id) final {
m_data.push_back(id); if (m_data.empty() || m_data.back() != id) {
m_data.push_back(id);
}
} }
/** /**
@ -385,7 +432,8 @@ namespace osmium {
/** /**
* Sort the internal vector and remove any duplicates. Call this * Sort the internal vector and remove any duplicates. Call this
* before using size(), get_binary_search() or using an iterator. * before using size(), get_binary_search(), merge_sorted() or
* using an iterator.
*/ */
void sort_unique() { void sort_unique() {
std::sort(m_data.begin(), m_data.end()); std::sort(m_data.begin(), m_data.end());
@ -408,6 +456,22 @@ namespace osmium {
return m_data.capacity() * sizeof(T); return m_data.capacity() * sizeof(T);
} }
/**
* Merge the other set into this one. The result is sorted.
*
* @pre Both sets must be sorted and must not contain any
* duplicates. Call sort_unique() if you are not sure.
*/
void merge_sorted(const IdSetSmall<T>& other) {
std::vector<T> new_data;
new_data.reserve(m_data.size() + other.m_data.size());
std::set_union(m_data.cbegin(), m_data.cend(),
other.m_data.cbegin(), other.m_data.cend(),
std::back_inserter(new_data));
using std::swap;
swap(new_data, m_data);
}
/// Iterator type. There is no non-const iterator. /// Iterator type. There is no non-const iterator.
using const_iterator = typename std::vector<T>::const_iterator; using const_iterator = typename std::vector<T>::const_iterator;
@ -435,7 +499,7 @@ namespace osmium {
using id_set_type = IdSetType<osmium::unsigned_object_id_type>; using id_set_type = IdSetType<osmium::unsigned_object_id_type>;
id_set_type m_sets[3]; std::array<id_set_type, 3> m_sets;
public: public:

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003
@ -118,7 +118,7 @@ namespace osmium {
virtual ~Map() noexcept = default; virtual ~Map() noexcept = default;
virtual void reserve(const size_t /*size*/) { virtual void reserve(const std::size_t /*size*/) {
// default implementation is empty // default implementation is empty
} }
@ -151,7 +151,7 @@ namespace osmium {
* accurate. You can not use this to find out how much memory the * accurate. You can not use this to find out how much memory the
* storage uses. Use used_memory() for that. * storage uses. Use used_memory() for that.
*/ */
virtual size_t size() const = 0; virtual std::size_t size() const = 0;
/** /**
* Get the memory used for this storage in bytes. Note that this * Get the memory used for this storage in bytes. Note that this
@ -160,7 +160,7 @@ namespace osmium {
* the main memory used, for storage classes storing data on disk * the main memory used, for storage classes storing data on disk
* this is the memory used on disk. * this is the memory used on disk.
*/ */
virtual size_t used_memory() const = 0; virtual std::size_t used_memory() const = 0;
/** /**
* Clear memory used for this storage. After this you can not * Clear memory used for this storage. After this you can not
@ -210,8 +210,6 @@ namespace osmium {
MapFactory() = default; MapFactory() = default;
~MapFactory() = default;
public: public:
MapFactory(const MapFactory&) = delete; MapFactory(const MapFactory&) = delete;
@ -220,6 +218,8 @@ namespace osmium {
MapFactory(MapFactory&&) = delete; MapFactory(MapFactory&&) = delete;
MapFactory& operator=(MapFactory&&) = delete; MapFactory& operator=(MapFactory&&) = delete;
~MapFactory() = default;
static MapFactory<id_type, value_type>& instance() { static MapFactory<id_type, value_type>& instance() {
static MapFactory<id_type, value_type> factory; static MapFactory<id_type, value_type> factory;
return factory; return factory;

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

View File

@ -3,9 +3,9 @@
/* /*
This file is part of Osmium (http://osmcode.org/libosmium). This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2018 Jochen Topf <jochen@topf.org> and others (see README). Copyright 2013-2020 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003 Boost Software License - Version 1.0 - August 17th, 2003

Some files were not shown because too many files have changed in this diff Show More